[llvm] r293634 - [ARM] Avoid using ARM instructions in Thumb mode

Sam Parker via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 31 06:35:02 PST 2017


Author: sam_parker
Date: Tue Jan 31 08:35:01 2017
New Revision: 293634

URL: http://llvm.org/viewvc/llvm-project?rev=293634&view=rev
Log:
[ARM] Avoid using ARM instructions in Thumb mode

The Requires class overrides the target requirements of an instruction,
rather than adding to them, so all ARM instructions need to include the
IsARM predicate when they have overwitten requirements.

This caused the swp and swpb instructions to be allowed in thumb mode
assembly, and the ARM encoding of CDP to be selected in codegen (which
is different for conditional instructions).

Differential Revision: https://reviews.llvm.org/D29283


Added:
    llvm/trunk/test/CodeGen/Thumb2/intrinsics-coprocessor.ll
Modified:
    llvm/trunk/include/llvm/Object/ELFObjectFile.h
    llvm/trunk/include/llvm/Object/ObjectFile.h
    llvm/trunk/lib/Target/ARM/ARMInstrInfo.td
    llvm/trunk/test/CodeGen/ARM/2009-05-18-InlineAsmMem.ll
    llvm/trunk/test/CodeGen/ARM/intrinsics-coprocessor.ll
    llvm/trunk/test/MC/ARM/thumb2-diagnostics.s

Modified: llvm/trunk/include/llvm/Object/ELFObjectFile.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/ELFObjectFile.h?rev=293634&r1=293633&r2=293634&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/ELFObjectFile.h (original)
+++ llvm/trunk/include/llvm/Object/ELFObjectFile.h Tue Jan 31 08:35:01 2017
@@ -74,9 +74,9 @@ public:
 
   SubtargetFeatures getFeatures() const override;
 
-  SubtargetFeatures getMIPSFeatures() const override;
+  SubtargetFeatures getMIPSFeatures() const;
 
-  SubtargetFeatures getARMFeatures() const override;
+  SubtargetFeatures getARMFeatures() const;
 
   void setARMSubArch(Triple &TheTriple) const override;
 };

Modified: llvm/trunk/include/llvm/Object/ObjectFile.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/ObjectFile.h?rev=293634&r1=293633&r2=293634&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/ObjectFile.h (original)
+++ llvm/trunk/include/llvm/Object/ObjectFile.h Tue Jan 31 08:35:01 2017
@@ -267,8 +267,6 @@ public:
   virtual StringRef getFileFormatName() const = 0;
   virtual /* Triple::ArchType */ unsigned getArch() const = 0;
   virtual SubtargetFeatures getFeatures() const = 0;
-  virtual SubtargetFeatures getMIPSFeatures() const { return SubtargetFeatures(); }
-  virtual SubtargetFeatures getARMFeatures() const { return SubtargetFeatures(); }
   virtual void setARMSubArch(Triple &TheTriple) const { }
 
   /// Returns platform-specific object flags, if any.

Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.td?rev=293634&r1=293633&r2=293634&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Tue Jan 31 08:35:01 2017
@@ -4831,14 +4831,15 @@ let AddedComplexity = 8 in {
   def : ARMPat<(atomic_store_release_32 addr_offset_none:$addr, GPR:$val), (STL  GPR:$val, addr_offset_none:$addr)>;
 }
 
-// SWP/SWPB are deprecated in V6/V7.
+// SWP/SWPB are deprecated in V6/V7 and optional in v7VE.
+// FIXME Use InstAlias to generate LDREX/STREX pairs instead.
 let mayLoad = 1, mayStore = 1 in {
 def SWP : AIswp<0, (outs GPRnopc:$Rt),
                 (ins GPRnopc:$Rt2, addr_offset_none:$addr), "swp", []>,
-                Requires<[PreV8]>;
+                Requires<[IsARM,PreV8]>;
 def SWPB: AIswp<1, (outs GPRnopc:$Rt),
                 (ins GPRnopc:$Rt2, addr_offset_none:$addr), "swpb", []>,
-                Requires<[PreV8]>;
+                Requires<[IsARM,PreV8]>;
 }
 
 //===----------------------------------------------------------------------===//
@@ -4850,7 +4851,7 @@ def CDP : ABI<0b1110, (outs), (ins p_imm
             NoItinerary, "cdp", "\t$cop, $opc1, $CRd, $CRn, $CRm, $opc2",
             [(int_arm_cdp imm:$cop, imm:$opc1, imm:$CRd, imm:$CRn,
                           imm:$CRm, imm:$opc2)]>,
-            Requires<[PreV8]> {
+            Requires<[IsARM,PreV8]> {
   bits<4> opc1;
   bits<4> CRn;
   bits<4> CRd;
@@ -4872,7 +4873,7 @@ def CDP2 : ABXI<0b1110, (outs), (ins p_i
                NoItinerary, "cdp2\t$cop, $opc1, $CRd, $CRn, $CRm, $opc2",
                [(int_arm_cdp2 imm:$cop, imm:$opc1, imm:$CRd, imm:$CRn,
                               imm:$CRm, imm:$opc2)]>,
-               Requires<[PreV8]> {
+               Requires<[IsARM,PreV8]> {
   let Inst{31-28} = 0b1111;
   bits<4> opc1;
   bits<4> CRn;
@@ -5048,13 +5049,13 @@ multiclass LdSt2Cop<bit load, bit Dbit,
 
 defm LDC   : LdStCop <1, 0, "ldc", [(int_arm_ldc imm:$cop, imm:$CRd, addrmode5:$addr)]>;
 defm LDCL  : LdStCop <1, 1, "ldcl", [(int_arm_ldcl imm:$cop, imm:$CRd, addrmode5:$addr)]>;
-defm LDC2  : LdSt2Cop<1, 0, "ldc2", [(int_arm_ldc2 imm:$cop, imm:$CRd, addrmode5:$addr)]>, Requires<[PreV8]>;
-defm LDC2L : LdSt2Cop<1, 1, "ldc2l", [(int_arm_ldc2l imm:$cop, imm:$CRd, addrmode5:$addr)]>, Requires<[PreV8]>;
+defm LDC2  : LdSt2Cop<1, 0, "ldc2", [(int_arm_ldc2 imm:$cop, imm:$CRd, addrmode5:$addr)]>, Requires<[IsARM,PreV8]>;
+defm LDC2L : LdSt2Cop<1, 1, "ldc2l", [(int_arm_ldc2l imm:$cop, imm:$CRd, addrmode5:$addr)]>, Requires<[IsARM,PreV8]>;
 
 defm STC   : LdStCop <0, 0, "stc", [(int_arm_stc imm:$cop, imm:$CRd, addrmode5:$addr)]>;
 defm STCL  : LdStCop <0, 1, "stcl", [(int_arm_stcl imm:$cop, imm:$CRd, addrmode5:$addr)]>;
-defm STC2  : LdSt2Cop<0, 0, "stc2", [(int_arm_stc2 imm:$cop, imm:$CRd, addrmode5:$addr)]>, Requires<[PreV8]>;
-defm STC2L : LdSt2Cop<0, 1, "stc2l", [(int_arm_stc2l imm:$cop, imm:$CRd, addrmode5:$addr)]>, Requires<[PreV8]>;
+defm STC2  : LdSt2Cop<0, 0, "stc2", [(int_arm_stc2 imm:$cop, imm:$CRd, addrmode5:$addr)]>, Requires<[IsARM,PreV8]>;
+defm STC2L : LdSt2Cop<0, 1, "stc2l", [(int_arm_stc2l imm:$cop, imm:$CRd, addrmode5:$addr)]>, Requires<[IsARM,PreV8]>;
 
 //===----------------------------------------------------------------------===//
 // Move between coprocessor and ARM core register.
@@ -5132,7 +5133,7 @@ def MCR2 : MovRCopro2<"mcr2", 0 /* from
                            c_imm:$CRm, imm0_7:$opc2),
                       [(int_arm_mcr2 imm:$cop, imm:$opc1, GPR:$Rt, imm:$CRn,
                                      imm:$CRm, imm:$opc2)]>,
-                      Requires<[PreV8]>;
+                      Requires<[IsARM,PreV8]>;
 def : ARMInstAlias<"mcr2 $cop, $opc1, $Rt, $CRn, $CRm",
                    (MCR2 p_imm:$cop, imm0_7:$opc1, GPR:$Rt, c_imm:$CRn,
                          c_imm:$CRm, 0)>;
@@ -5140,7 +5141,7 @@ def MRC2 : MovRCopro2<"mrc2", 1 /* from
                       (outs GPRwithAPSR:$Rt),
                       (ins p_imm:$cop, imm0_7:$opc1, c_imm:$CRn, c_imm:$CRm,
                            imm0_7:$opc2), []>,
-                      Requires<[PreV8]>;
+                      Requires<[IsARM,PreV8]>;
 def : ARMInstAlias<"mrc2 $cop, $opc1, $Rt, $CRn, $CRm",
                    (MRC2 GPRwithAPSR:$Rt, p_imm:$cop, imm0_7:$opc1, c_imm:$CRn,
                          c_imm:$CRm, 0)>;
@@ -5183,7 +5184,7 @@ class MovRRCopro2<string opc, bit direct
                   list<dag> pattern = []>
   : ABXI<0b1100, oops, iops, NoItinerary,
          !strconcat(opc, "\t$cop, $opc1, $Rt, $Rt2, $CRm"), pattern>,
-    Requires<[PreV8]> {
+    Requires<[IsARM,PreV8]> {
   let Inst{31-28} = 0b1111;
   let Inst{23-21} = 0b010;
   let Inst{20} = direction;

Modified: llvm/trunk/test/CodeGen/ARM/2009-05-18-InlineAsmMem.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/2009-05-18-InlineAsmMem.ll?rev=293634&r1=293633&r2=293634&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/2009-05-18-InlineAsmMem.ll (original)
+++ llvm/trunk/test/CodeGen/ARM/2009-05-18-InlineAsmMem.ll Tue Jan 31 08:35:01 2017
@@ -1,5 +1,4 @@
 ; RUN: llc -mtriple=arm-eabi %s -o - | FileCheck %s
-; RUN: llc -mtriple=thumb-eabi %s -o - | FileCheck %s
 ; PR4091
 
 define void @foo(i32 %i, i32* %p) nounwind {

Modified: llvm/trunk/test/CodeGen/ARM/intrinsics-coprocessor.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/intrinsics-coprocessor.ll?rev=293634&r1=293633&r2=293634&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/intrinsics-coprocessor.ll (original)
+++ llvm/trunk/test/CodeGen/ARM/intrinsics-coprocessor.ll Tue Jan 31 08:35:01 2017
@@ -1,5 +1,4 @@
 ; 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(i8* %i) nounwind {
 entry:

Added: llvm/trunk/test/CodeGen/Thumb2/intrinsics-coprocessor.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Thumb2/intrinsics-coprocessor.ll?rev=293634&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/Thumb2/intrinsics-coprocessor.ll (added)
+++ llvm/trunk/test/CodeGen/Thumb2/intrinsics-coprocessor.ll Tue Jan 31 08:35:01 2017
@@ -0,0 +1,93 @@
+; RUN: llc < %s -march=thumb -mtriple=thumbv7-eabi -mcpu=cortex-a8 -show-mc-encoding | FileCheck %s
+define void @coproc(i8* %i) nounwind {
+entry:
+  ; CHECK: mrc p7, #1, r{{[0-9]+}}, c1, c1, #4
+  %0 = tail call i32 @llvm.arm.mrc(i32 7, i32 1, i32 1, i32 1, i32 4) nounwind
+  ; CHECK: mcr p7, #1, r{{[0-9]+}}, c1, c1, #4
+  tail call void @llvm.arm.mcr(i32 7, i32 1, i32 %0, i32 1, i32 1, i32 4) nounwind
+  ; CHECK: mrc2 p7, #1, r{{[0-9]+}}, c1, c1, #4
+  %1 = tail call i32 @llvm.arm.mrc2(i32 7, i32 1, i32 1, i32 1, i32 4) nounwind
+  ; CHECK: mcr2 p7, #1, r{{[0-9]+}}, c1, c1, #4
+  tail call void @llvm.arm.mcr2(i32 7, i32 1, i32 %1, i32 1, i32 1, i32 4) nounwind
+  ; CHECK: mcrr p7, #1, r{{[0-9]+}}, r{{[0-9]+}}, c1
+  tail call void @llvm.arm.mcrr(i32 7, i32 1, i32 %0, i32 %1, i32 1) nounwind
+  ; CHECK: mcrr2 p7, #1, r{{[0-9]+}}, r{{[0-9]+}}, c1
+  tail call void @llvm.arm.mcrr2(i32 7, i32 1, i32 %0, i32 %1, i32 1) nounwind
+  ; CHECK: cdp p7, #3, c1, c1, c1, #5
+  tail call void @llvm.arm.cdp(i32 7, i32 3, i32 1, i32 1, i32 1, i32 5) nounwind
+  ; CHECK: cdp2 p7, #3, c1, c1, c1, #5
+  tail call void @llvm.arm.cdp2(i32 7, i32 3, i32 1, i32 1, i32 1, i32 5) nounwind
+  ; CHECK: ldc p7, c3, [r{{[0-9]+}}]
+  tail call void @llvm.arm.ldc(i32 7, i32 3, i8* %i) nounwind
+  ; CHECK: ldcl p7, c3, [r{{[0-9]+}}]
+  tail call void @llvm.arm.ldcl(i32 7, i32 3, i8* %i) nounwind
+  ; CHECK: ldc2 p7, c3, [r{{[0-9]+}}]
+  tail call void @llvm.arm.ldc2(i32 7, i32 3, i8* %i) nounwind
+  ; CHECK: ldc2l p7, c3, [r{{[0-9]+}}]
+  tail call void @llvm.arm.ldc2l(i32 7, i32 3, i8* %i) nounwind
+  ; CHECK: stc p7, c3, [r{{[0-9]+}}]
+  tail call void @llvm.arm.stc(i32 7, i32 3, i8* %i) nounwind
+  ; CHECK: stcl p7, c3, [r{{[0-9]+}}]
+  tail call void @llvm.arm.stcl(i32 7, i32 3, i8* %i) nounwind
+  ; CHECK: stc2 p7, c3, [r{{[0-9]+}}]
+  tail call void @llvm.arm.stc2(i32 7, i32 3, i8* %i) nounwind
+  ; CHECK: stc2l p7, c3, [r{{[0-9]+}}]
+  tail call void @llvm.arm.stc2l(i32 7, i32 3, i8* %i) nounwind
+  ; CHECK: mrrc p1, #2, r{{[0-9]+}}, r{{[0-9]+}}, c3
+  %2 = tail call { i32, i32 } @llvm.arm.mrrc(i32 1, i32 2, i32 3) nounwind
+  ; CHECK: mrrc2 p1, #2, r{{[0-9]+}}, r{{[0-9]+}}, c3
+  %3 = tail call { i32, i32 } @llvm.arm.mrrc2(i32 1, i32 2, i32 3) nounwind
+  ret void
+}
+
+define hidden void @cond_cdp(i32 %a) {
+; CHECK-LABEL: cond_cdp:
+entry:
+  %tobool = icmp eq i32 %a, 0
+  br i1 %tobool, label %if.end, label %if.then
+
+if.then:
+; CHECK: it ne
+; CHECK: cdpne   p15, #0, c0, c0, c0, #0 @ encoding: [0x00,0xee,0x00,0x0f]
+  tail call void @llvm.arm.cdp(i32 15, i32 0, i32 0, i32 0, i32 0, i32 0)
+  br label %if.end
+
+if.end:
+  ret void
+}
+
+declare void @llvm.arm.ldc(i32, i32, i8*) nounwind
+
+declare void @llvm.arm.ldcl(i32, i32, i8*) nounwind
+
+declare void @llvm.arm.ldc2(i32, i32, i8*) nounwind
+
+declare void @llvm.arm.ldc2l(i32, i32, i8*) nounwind
+
+declare void @llvm.arm.stc(i32, i32, i8*) nounwind
+
+declare void @llvm.arm.stcl(i32, i32, i8*) nounwind
+
+declare void @llvm.arm.stc2(i32, i32, i8*) nounwind
+
+declare void @llvm.arm.stc2l(i32, i32, i8*) nounwind
+
+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
+
+declare { i32, i32 } @llvm.arm.mrrc(i32, i32, i32) nounwind
+
+declare { i32, i32 } @llvm.arm.mrrc2(i32, i32, i32) nounwind

Modified: llvm/trunk/test/MC/ARM/thumb2-diagnostics.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/thumb2-diagnostics.s?rev=293634&r1=293633&r2=293634&view=diff
==============================================================================
--- llvm/trunk/test/MC/ARM/thumb2-diagnostics.s (original)
+++ llvm/trunk/test/MC/ARM/thumb2-diagnostics.s Tue Jan 31 08:35:01 2017
@@ -118,3 +118,9 @@ foo2:
 @ CHECK-ERRORS: error: instruction requires: arm-mode
 @ CHECK-ERRORS: error: immediate value expected for vector index
 @ CHECK-ERRORS: error: instruction requires: arm-mode
+
+        @ SWP(B) is an ARM-only instruction
+        swp  r0, r1, [r2]
+        swpb r3, r4, [r5]
+@ CHECK-ERRORS: error: instruction requires: arm-mode
+@ CHECK-ERRORS: error: instruction requires: arm-mode




More information about the llvm-commits mailing list