Add a few ARM coprocessor intrinsics. Testcases included
authorBruno Cardoso Lopes <bruno.cardoso@gmail.com>
Tue, 3 May 2011 17:29:22 +0000 (17:29 +0000)
committerBruno Cardoso Lopes <bruno.cardoso@gmail.com>
Tue, 3 May 2011 17:29:22 +0000 (17:29 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@130763 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/IntrinsicsARM.td
lib/Target/ARM/ARMInstrFormats.td
lib/Target/ARM/ARMInstrInfo.td
lib/Target/ARM/ARMInstrThumb.td
lib/Target/ARM/ARMInstrThumb2.td
test/CodeGen/ARM/intrinsics.ll [new file with mode: 0644]

index 03e9261e60cb25935891a8b4f65c585a5635469b..3954412a76e87dc0da702a703551ec4df329b71b 100644 (file)
@@ -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)
 
index f5fb98ece4af78b1e935f1a3dbf7b70b8f649255..a547fd0444f0e3ba6f4ded95f8ceb75c88b310df 100644 (file)
@@ -860,6 +860,9 @@ class APKHI<bits<8> opcod, bit tb, dag oops, dag iops, InstrItinClass itin,
 class ARMPat<dag pattern, dag result> : Pat<pattern, result> {
   list<Predicate> Predicates = [IsARM];
 }
+class ARMV5TPat<dag pattern, dag result> : Pat<pattern, result> {
+  list<Predicate> Predicates = [IsARM, HasV5T];
+}
 class ARMV5TEPat<dag pattern, dag result> : Pat<pattern, result> {
   list<Predicate> Predicates = [IsARM, HasV5TE];
 }
@@ -1208,6 +1211,11 @@ class T1Pat<dag pattern, dag result> : Pat<pattern, result> {
   list<Predicate> Predicates = [IsThumb, IsThumb1Only];
 }
 
+// T2v6Pat - Same as Pat<>, but requires V6T2 Thumb2 mode.
+class T2v6Pat<dag pattern, dag result> : Pat<pattern, result> {
+  list<Predicate> Predicates = [IsThumb2, HasV6T2];
+}
+
 // T2Pat - Same as Pat<>, but requires that the compiler be in Thumb2 mode.
 class T2Pat<dag pattern, dag result> : Pat<pattern, result> {
   list<Predicate> Predicates = [IsThumb2];
index 209c1a3fd96ab850458efe869bbe5428cb060d28..cee5060dcc64416ff98b083f800b15864ca9f775 100644 (file)
@@ -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<dag oops, dag iops, string opc, string asm,
           IndexMode im = IndexModeNone>
   : InoP<oops, iops, AddrModeNone, Size4Bytes, im, BrFrm, NoItinerary,
@@ -3572,6 +3581,12 @@ def MRC : MovRCopro<"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 : 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<string opc, bit direction, dag oops, dag iops>
   : 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<string opc, bit direction>
   : ABI<0b1100, (outs), (ins p_imm:$cop, i32imm:$opc1,
         GPR:$Rt, GPR:$Rt2, c_imm:$CRm),
@@ -3628,6 +3651,10 @@ class MovRRCopro<string opc, bit direction>
 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<string opc, bit direction>
   : ABXI<0b1100, (outs), (ins p_imm:$cop, i32imm:$opc1,
          GPR:$Rt, GPR:$Rt2, c_imm:$CRm),
@@ -3653,6 +3680,9 @@ class MovRRCopro2<string opc, bit direction>
 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
 //
index 8c542fe60bba666e99222a38baa97e26405a2d1c..1957ef8abe7cdbdd4463e453c7b7d1076da0dd2a 100644 (file)
@@ -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<string opc, bit direction>
   : 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<string opc, bit direction>
 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
 //
index 600a12180fc530e308e8beda431ac1e9b78aaac6..8ca10d88e94bbd28927d4d64458a868cd4bdd1bc 100644 (file)
@@ -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<string opc, bit direction>
   : 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 (file)
index 0000000..54cc3e0
--- /dev/null
@@ -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