]> granicus.if.org Git - llvm/commitdiff
[ARM] Add Thumb2 ADD with SP narrowing from 3 operand to 2
authorScott Douglass <sdouglass@arm.com>
Mon, 13 Jul 2015 15:31:40 +0000 (15:31 +0000)
committerScott Douglass <sdouglass@arm.com>
Mon, 13 Jul 2015 15:31:40 +0000 (15:31 +0000)
Differential Revision: http://reviews.llvm.org/D11131

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@242035 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/AsmParser/ARMAsmParser.cpp
test/MC/ARM/thumb2-narrow-dp.ll

index 901627df1295104c67305ef4ceb789d9c4797949..ede7549e187b38b808e9df58f8dde8f45e70535f 100644 (file)
@@ -5486,13 +5486,22 @@ void ARMAsmParser::tryConvertingToTwoOperandForm(StringRef Mnemonic,
   auto Op4Reg = Op4.getReg();
 
   // For most Thumb2 cases we just generate the 3 operand form and reduce
-  // it in processInstruction(), but for ADD involving PC the the 3 operand
-  // form won't accept PC so we do the transformation here.
+  // it in processInstruction(), but the 3 operand form of ADD (t2ADDrr)
+  // won't accept SP or PC so we do the transformation here taking care
+  // with immediate range in the 'add sp, sp #imm' case.
   auto &Op5 = static_cast<ARMOperand &>(*Operands[5]);
   if (isThumbTwo()) {
-    if (Mnemonic != "add" ||
-        !(Op3Reg == ARM::PC || Op4Reg == ARM::PC ||
-          (Op5.isReg() && Op5.getReg() == ARM::PC)))
+    if (Mnemonic != "add")
+      return;
+    bool TryTransform = Op3Reg == ARM::PC || Op4Reg == ARM::PC ||
+                        (Op5.isReg() && Op5.getReg() == ARM::PC);
+    if (!TryTransform) {
+      TryTransform = (Op3Reg == ARM::SP || Op4Reg == ARM::SP ||
+                      (Op5.isReg() && Op5.getReg() == ARM::SP)) &&
+                     !(Op3Reg == ARM::SP && Op4Reg == ARM::SP &&
+                       Op5.isImm() && !Op5.isImm0_508s4());
+    }
+    if (!TryTransform)
       return;
   } else if (!isThumbOne())
     return;
index 13bbd1ff754af473b65d6ead1069cd40d47f29de..0c2aae9164377524c8eba79a37f7cd1ab2f2e9f2 100644 (file)
 // CHECK: add  pc, r2               @ encoding: [0x97,0x44]
     ADD      pc, r2, pc          // T2
 // CHECK: add  pc, r2               @ encoding: [0x97,0x44]
+    ADD      pc, pc, sp          // T2
+// CHECK: add   pc, sp              @ encoding: [0xef,0x44]
+    ADD      pc, sp, pc          // T2
+// CHECK: add   pc, sp, pc          @ encoding: [0xef,0x44]
 
 // ADD (SP plus immediate) A8.8.9
     ADD      sp, sp, #20         // T2
 // FIXME: ARMARM says 'add   sp, sp, #20'
-// CHECK: add   sp, #20         @ encoding: [0x05,0xb0]
+// CHECK: add   sp, #20             @ encoding: [0x05,0xb0]
+    ADD      sp, sp, #508        // T2
+// CHECK: add   sp, #508            @ encoding: [0x7f,0xb0]
+    ADD      sp, sp, #512        // T3
+// CHECK: add.w sp, sp, #512        @ encoding: [0x0d,0xf5,0x00,0x7d]
 
 // ADD (SP plus register) A8.8.10 (commutative)
     ADD      r9, sp, r9          // T1
 // CHECK: add   r9, sp, r9          @ encoding: [0xe9,0x44]
+    ADD      r9, r9, sp          // T1
+// FIXME: ARMARM says 'add   r9, sp, r9'
+// CHECK: add   r9, sp              @ encoding: [0xe9,0x44]
     ADD      sp, sp, r10         // T2
 // CHECK: add   sp, r10             @ encoding: [0xd5,0x44]
+    ADD      sp, r10, sp         // T2
+// CHECK: add   sp, r10             @ encoding: [0xd5,0x44]
+    ADD      sp, sp, pc          // T2
+// CHECK: add   sp, pc              @ encoding: [0xfd,0x44]
 
 // AND (commutative)
     ANDS     r0, r2, r1          // Must be wide - 3 distinct registers