From 54ad87ab786cae4e5b654f4295e9697f0c72dbb1 Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Tue, 3 May 2011 17:29:22 +0000 Subject: [PATCH] Add a few ARM coprocessor intrinsics. Testcases included git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@130763 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/IntrinsicsARM.td | 37 +++++++++++++++++++++++++++++ lib/Target/ARM/ARMInstrFormats.td | 8 +++++++ lib/Target/ARM/ARMInstrInfo.td | 30 ++++++++++++++++++++++++ lib/Target/ARM/ARMInstrThumb.td | 17 ++++++++++++++ lib/Target/ARM/ARMInstrThumb2.td | 16 +++++++++++++ test/CodeGen/ARM/intrinsics.ll | 39 +++++++++++++++++++++++++++++++ 6 files changed, 147 insertions(+) create mode 100644 test/CodeGen/ARM/intrinsics.ll diff --git a/include/llvm/IntrinsicsARM.td b/include/llvm/IntrinsicsARM.td index 03e9261e60c..3954412a76e 100644 --- a/include/llvm/IntrinsicsARM.td +++ b/include/llvm/IntrinsicsARM.td @@ -49,6 +49,43 @@ let TargetPrefix = "arm" in { // All intrinsics start with "llvm.arm.". [IntrNoMem]>; } +//===----------------------------------------------------------------------===// +// Coprocessor + +let TargetPrefix = "arm" in { // All intrinsics start with "llvm.arm.". + // Move to coprocessor + def int_arm_mcr : GCCBuiltin<"__builtin_arm_mcr">, + Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; + def int_arm_mcr2 : GCCBuiltin<"__builtin_arm_mcr2">, + Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; + + // Move from coprocessor + def int_arm_mrc : GCCBuiltin<"__builtin_arm_mrc">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty], []>; + def int_arm_mrc2 : GCCBuiltin<"__builtin_arm_mrc2">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty], []>; + + // Coprocessor data processing + def int_arm_cdp : GCCBuiltin<"__builtin_arm_cdp">, + Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; + def int_arm_cdp2 : GCCBuiltin<"__builtin_arm_cdp2">, + Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; + + // Move from two registers to coprocessor + def int_arm_mcrr : GCCBuiltin<"__builtin_arm_mcrr">, + Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty], []>; + def int_arm_mcrr2 : GCCBuiltin<"__builtin_arm_mcrr2">, + Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty], []>; +} + //===----------------------------------------------------------------------===// // Advanced SIMD (NEON) diff --git a/lib/Target/ARM/ARMInstrFormats.td b/lib/Target/ARM/ARMInstrFormats.td index f5fb98ece4a..a547fd0444f 100644 --- a/lib/Target/ARM/ARMInstrFormats.td +++ b/lib/Target/ARM/ARMInstrFormats.td @@ -860,6 +860,9 @@ class APKHI opcod, bit tb, dag oops, dag iops, InstrItinClass itin, class ARMPat : Pat { list Predicates = [IsARM]; } +class ARMV5TPat : Pat { + list Predicates = [IsARM, HasV5T]; +} class ARMV5TEPat : Pat { list Predicates = [IsARM, HasV5TE]; } @@ -1208,6 +1211,11 @@ class T1Pat : Pat { list Predicates = [IsThumb, IsThumb1Only]; } +// T2v6Pat - Same as Pat<>, but requires V6T2 Thumb2 mode. +class T2v6Pat : Pat { + list Predicates = [IsThumb2, HasV6T2]; +} + // T2Pat - Same as Pat<>, but requires that the compiler be in Thumb2 mode. class T2Pat : Pat { list Predicates = [IsThumb2]; diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index 209c1a3fd96..cee5060dcc6 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -3415,6 +3415,10 @@ def CDP : ABI<0b1110, (outs), (ins p_imm:$cop, i32imm:$opc1, let Inst{23-20} = opc1; } +def : ARMPat<(int_arm_cdp imm:$cop, imm:$opc1, imm:$CRd, imm:$CRn, + imm:$CRm, imm:$opc2), + (CDP imm:$cop, imm:$opc1, imm:$CRd, imm:$CRn, imm:$CRm,imm:$opc2)>; + def CDP2 : ABXI<0b1110, (outs), (ins p_imm:$cop, i32imm:$opc1, c_imm:$CRd, c_imm:$CRn, c_imm:$CRm, i32imm:$opc2), NoItinerary, "cdp2\t$cop, $opc1, $CRd, $CRn, $CRm, $opc2", @@ -3436,6 +3440,11 @@ def CDP2 : ABXI<0b1110, (outs), (ins p_imm:$cop, i32imm:$opc1, let Inst{23-20} = opc1; } +def : ARMPat<(int_arm_cdp2 imm:$cop, imm:$opc1, imm:$CRd, imm:$CRn, + imm:$CRm, imm:$opc2), + (CDP2 imm:$cop, imm:$opc1, imm:$CRd, imm:$CRn, imm:$CRm, + imm:$opc2)>; + class ACI : InoP; +def : ARMPat<(int_arm_mcr imm:$cop, imm:$opc1, GPR:$Rt, imm:$CRn, + imm:$CRm, imm:$opc2), + (MCR imm:$cop, imm:$opc1, GPR:$Rt, imm:$CRn, imm:$CRm, imm:$opc2)>; +def : ARMPat<(int_arm_mrc imm:$cop, imm:$opc1, imm:$CRn, imm:$CRm, imm:$opc2), + (MRC imm:$cop, imm:$opc1, imm:$CRn, imm:$CRm, imm:$opc2)>; + class MovRCopro2 : ABXI<0b1110, oops, iops, NoItinerary, !strconcat(opc, "\t$cop, $opc1, $Rt, $CRn, $CRm, $opc2"), @@ -3604,6 +3619,14 @@ def MRC2 : MovRCopro2<"mrc2", 1 /* from coprocessor to ARM core register */, c_imm:$CRn, c_imm:$CRm, i32imm:$opc2)>; +def : ARMV5TPat<(int_arm_mcr2 imm:$cop, imm:$opc1, GPR:$Rt, imm:$CRn, + imm:$CRm, imm:$opc2), + (MCR2 imm:$cop, imm:$opc1, GPR:$Rt, imm:$CRn, + imm:$CRm, imm:$opc2)>; +def : ARMV5TPat<(int_arm_mrc2 imm:$cop, imm:$opc1, imm:$CRn, + imm:$CRm, imm:$opc2), + (MRC2 imm:$cop, imm:$opc1, imm:$CRn, imm:$CRm, imm:$opc2)>; + class MovRRCopro : ABI<0b1100, (outs), (ins p_imm:$cop, i32imm:$opc1, GPR:$Rt, GPR:$Rt2, c_imm:$CRm), @@ -3628,6 +3651,10 @@ class MovRRCopro def MCRR : MovRRCopro<"mcrr", 0 /* from ARM core register to coprocessor */>; def MRRC : MovRRCopro<"mrrc", 1 /* from coprocessor to ARM core register */>; +def : ARMV5TEPat<(int_arm_mcrr imm:$cop, imm:$opc1, GPR:$Rt, GPR:$Rt2, + imm:$CRm), + (MCRR imm:$cop, imm:$opc1, GPR:$Rt, GPR:$Rt2, imm:$CRm)>; + class MovRRCopro2 : ABXI<0b1100, (outs), (ins p_imm:$cop, i32imm:$opc1, GPR:$Rt, GPR:$Rt2, c_imm:$CRm), @@ -3653,6 +3680,9 @@ class MovRRCopro2 def MCRR2 : MovRRCopro2<"mcrr2", 0 /* from ARM core register to coprocessor */>; def MRRC2 : MovRRCopro2<"mrrc2", 1 /* from coprocessor to ARM core register */>; +def : ARMV6Pat<(int_arm_mcrr2 imm:$cop, imm:$opc1, GPR:$Rt, GPR:$Rt2, imm:$CRm), + (MCRR2 imm:$cop, imm:$opc1, GPR:$Rt, GPR:$Rt2, imm:$CRm)>; + //===----------------------------------------------------------------------===// // Move between special register and ARM core register -- for disassembly only // diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td index 8c542fe60bb..1957ef8abe7 100644 --- a/lib/Target/ARM/ARMInstrThumb.td +++ b/lib/Target/ARM/ARMInstrThumb.td @@ -1381,6 +1381,14 @@ def tMRC : tMovRCopro<"mrc", 1 /* from coprocessor to ARM core register */, (outs GPR:$Rt), (ins p_imm:$cop, i32imm:$opc1, c_imm:$CRn, c_imm:$CRm, i32imm:$opc2)>; +def : Pat<(int_arm_mcr imm:$cop, imm:$opc1, GPR:$Rt, imm:$CRn, + imm:$CRm, imm:$opc2), + (tMCR imm:$cop, imm:$opc1, GPR:$Rt, imm:$CRn, + imm:$CRm, imm:$opc2)>, Requires<[IsThumb, HasV6T2]>; +def : Pat<(int_arm_mrc imm:$cop, imm:$opc1, imm:$CRn, imm:$CRm, imm:$opc2), + (tMRC imm:$cop, imm:$opc1, imm:$CRn, imm:$CRm, imm:$opc2)>, + Requires<[IsThumb, HasV6T2]>; + class tMovRRCopro : T1Cop<(outs), (ins p_imm:$cop, i32imm:$opc1, GPR:$Rt, GPR:$Rt2, c_imm:$CRm), !strconcat(opc, "\t$cop, $opc1, $Rt, $Rt2, $CRm"), @@ -1405,6 +1413,10 @@ class tMovRRCopro def tMCRR : tMovRRCopro<"mcrr", 0 /* from ARM core register to coprocessor */>; def tMRRC : tMovRRCopro<"mrrc", 1 /* from coprocessor to ARM core register */>; +def : Pat<(int_arm_mcrr imm:$cop, imm:$opc1, GPR:$Rt, GPR:$Rt2, imm:$CRm), + (tMCRR imm:$cop, imm:$opc1, GPR:$Rt, GPR:$Rt2, imm:$CRm)>, + Requires<[IsThumb, HasV6T2]>; + //===----------------------------------------------------------------------===// // Other Coprocessor Instructions. For disassembly only. // @@ -1430,6 +1442,11 @@ def tCDP : T1Cop<(outs), (ins p_imm:$cop, i32imm:$opc1, let Inst{23-20} = opc1; } +def : Pat<(int_arm_cdp imm:$cop, imm:$opc1, imm:$CRd, imm:$CRn, + imm:$CRm, imm:$opc2), + (tCDP imm:$cop, imm:$opc1, imm:$CRd, imm:$CRn, + imm:$CRm, imm:$opc2)>, Requires<[IsThumb, HasV6T2]>; + //===----------------------------------------------------------------------===// // TLS Instructions // diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td index 600a12180fc..8ca10d88e94 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -3376,6 +3376,14 @@ def t2MRC2 : t2MovRCopro<"mrc2", 1 /* from coprocessor to ARM core register */, (outs GPR:$Rt), (ins p_imm:$cop, i32imm:$opc1, c_imm:$CRn, c_imm:$CRm, i32imm:$opc2)>; +def : T2v6Pat<(int_arm_mcr2 imm:$cop, imm:$opc1, GPR:$Rt, imm:$CRn, + imm:$CRm, imm:$opc2), + (t2MCR2 imm:$cop, imm:$opc1, GPR:$Rt, imm:$CRn, + imm:$CRm, imm:$opc2)>; +def : T2v6Pat<(int_arm_mrc2 imm:$cop, imm:$opc1, imm:$CRn, + imm:$CRm, imm:$opc2), + (t2MRC2 imm:$cop, imm:$opc1, imm:$CRn, imm:$CRm, imm:$opc2)>; + class t2MovRRCopro : T2Cop<(outs), (ins p_imm:$cop, i32imm:$opc1, GPR:$Rt, GPR:$Rt2, c_imm:$CRm), !strconcat(opc, "\t$cop, $opc1, $Rt, $Rt2, $CRm"), @@ -3402,6 +3410,9 @@ def t2MCRR2 : t2MovRRCopro<"mcrr2", def t2MRRC2 : t2MovRRCopro<"mrrc2", 1 /* from coprocessor to ARM core register */>; +def : T2v6Pat<(int_arm_mcrr2 imm:$cop, imm:$opc1, GPR:$Rt, GPR:$Rt2, imm:$CRm), + (t2MCRR2 imm:$cop, imm:$opc1, GPR:$Rt, GPR:$Rt2, imm:$CRm)>; + //===----------------------------------------------------------------------===// // Other Coprocessor Instructions. For disassembly only. // @@ -3427,3 +3438,8 @@ def t2CDP2 : T2Cop<(outs), (ins p_imm:$cop, i32imm:$opc1, let Inst{19-16} = CRn; let Inst{23-20} = opc1; } + +def : T2v6Pat<(int_arm_cdp2 imm:$cop, imm:$opc1, imm:$CRd, imm:$CRn, + imm:$CRm, imm:$opc2), + (t2CDP2 imm:$cop, imm:$opc1, imm:$CRd, imm:$CRn, + imm:$CRm, imm:$opc2)>; diff --git a/test/CodeGen/ARM/intrinsics.ll b/test/CodeGen/ARM/intrinsics.ll new file mode 100644 index 00000000000..54cc3e0a027 --- /dev/null +++ b/test/CodeGen/ARM/intrinsics.ll @@ -0,0 +1,39 @@ +; RUN: llc < %s -mtriple=armv7-eabi -mcpu=cortex-a8 | FileCheck %s +; RUN: llc < %s -march=thumb -mtriple=thumbv7-eabi -mcpu=cortex-a8 | FileCheck %s + +define void @coproc() nounwind { +entry: + ; CHECK: mrc + %0 = tail call i32 @llvm.arm.mrc(i32 7, i32 1, i32 1, i32 1, i32 4) nounwind + ; CHECK: mcr + tail call void @llvm.arm.mcr(i32 7, i32 1, i32 %0, i32 1, i32 1, i32 4) nounwind + ; CHECK: mrc2 + %1 = tail call i32 @llvm.arm.mrc2(i32 7, i32 1, i32 1, i32 1, i32 4) nounwind + ; CHECK: mcr2 + tail call void @llvm.arm.mcr2(i32 7, i32 1, i32 %1, i32 1, i32 1, i32 4) nounwind + ; CHECK: mcrr + tail call void @llvm.arm.mcrr(i32 7, i32 1, i32 %0, i32 %1, i32 1) nounwind + ; CHECK: mcrr2 + tail call void @llvm.arm.mcrr2(i32 7, i32 1, i32 %0, i32 %1, i32 1) nounwind + ; CHECK: cdp + tail call void @llvm.arm.cdp(i32 7, i32 3, i32 1, i32 1, i32 1, i32 5) nounwind + ; CHECK: cdp2 + tail call void @llvm.arm.cdp2(i32 7, i32 3, i32 1, i32 1, i32 1, i32 5) nounwind + ret void +} + +declare void @llvm.arm.cdp2(i32, i32, i32, i32, i32, i32) nounwind + +declare void @llvm.arm.cdp(i32, i32, i32, i32, i32, i32) nounwind + +declare void @llvm.arm.mcrr2(i32, i32, i32, i32, i32) nounwind + +declare void @llvm.arm.mcrr(i32, i32, i32, i32, i32) nounwind + +declare void @llvm.arm.mcr2(i32, i32, i32, i32, i32, i32) nounwind + +declare i32 @llvm.arm.mrc2(i32, i32, i32, i32, i32) nounwind + +declare void @llvm.arm.mcr(i32, i32, i32, i32, i32, i32) nounwind + +declare i32 @llvm.arm.mrc(i32, i32, i32, i32, i32) nounwind -- 2.34.1