Make Thumb2 LEA-like instruction into pseudos, which map down to ADR. Provide correc...
authorOwen Anderson <resistor@mac.com>
Mon, 13 Dec 2010 22:29:52 +0000 (22:29 +0000)
committerOwen Anderson <resistor@mac.com>
Mon, 13 Dec 2010 22:29:52 +0000 (22:29 +0000)
which is _of course_ different from ARM ADR fixups, or any other Thumb2 fixup.

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

lib/Target/ARM/ARMAsmBackend.cpp
lib/Target/ARM/ARMCodeEmitter.cpp
lib/Target/ARM/ARMConstantIslandPass.cpp
lib/Target/ARM/ARMExpandPseudoInsts.cpp
lib/Target/ARM/ARMFixupKinds.h
lib/Target/ARM/ARMInstrThumb2.td
lib/Target/ARM/ARMMCCodeEmitter.cpp
utils/TableGen/EDEmitter.cpp

index cb0c54386ed67e95d7663b157d773d7d5ef039cd..789bae09bee1e9f1eb611d14e4f381966fcec36c 100644 (file)
@@ -136,6 +136,25 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
     // Encode the immediate and shift the opcode into place.
     return ARM_AM::getSOImmVal(Value) | (opc << 21);
   }
+  
+  case ARM::fixup_t2_adr_pcrel_12: {
+    Value -= 4;
+    unsigned opc = 0;
+    if ((int64_t)Value < 0) {
+      Value = -Value;
+      opc = 5;
+    }
+
+    uint32_t out = (opc << 21);
+    out |= (Value & 0x800) << 14;
+    out |= (Value & 0x700) << 4;
+    out |= (Value & 0x0FF);
+    
+    uint64_t swapped = (out & 0xFFFF0000) >> 16;
+    swapped |= (out & 0x0000FFFF) << 16;
+    return swapped;
+  }
+  
   case ARM::fixup_arm_branch:
     // These values don't encode the low two bits since they're always zero.
     // Offset by 8 just as above.
@@ -356,6 +375,7 @@ static unsigned getFixupKindNumBytes(unsigned Kind) {
   case ARM::fixup_t2_condbranch:
   case ARM::fixup_t2_uncondbranch:
   case ARM::fixup_t2_pcrel_10:
+  case ARM::fixup_t2_adr_pcrel_12:
   case ARM::fixup_arm_thumb_bl:
   case ARM::fixup_arm_thumb_blx:
     return 4;
index 101c07b4db623c4fedef3492f26827d3b1f63223..5e302ae28136c95dc2ee9f2081fef1b8be06e273 100644 (file)
@@ -213,6 +213,8 @@ namespace {
       const { return 0; }
     unsigned getImmMinusOneOpValue(const MachineInstr &MI, unsigned Op)
       const { return 0; }
+    unsigned getT2AdrLabelOpValue(const MachineInstr &MI, unsigned Op)
+      const { return 0; }
     unsigned getAddrMode6AddressOpValue(const MachineInstr &MI, unsigned Op)
       const { return 0; }
     unsigned getAddrMode6DupAddressOpValue(const MachineInstr &MI, unsigned Op)
index 8066cb735b1361167070ba933aa2487016cf6f25..9434ecf40bdc958022945ca5f2cdf05e73ac94a5 100644 (file)
@@ -594,7 +594,7 @@ void ARMConstantIslands::InitialFunctionScan(MachineFunction &MF,
             NegOk = true;
             IsSoImm = true;
             break;
-          case ARM::t2LEApcrel:
+          case ARM::t2ADR:
             Bits = 12;
             NegOk = true;
             break;
@@ -1555,7 +1555,7 @@ bool ARMConstantIslands::OptimizeThumb2Instructions(MachineFunction &MF) {
     unsigned Bits = 0;
     switch (Opcode) {
     default: break;
-    case ARM::t2LEApcrel:
+    case ARM::t2ADR:
       if (isARMLowRegister(U.MI->getOperand(0).getReg())) {
         NewOpc = ARM::tLEApcrel;
         Bits = 8;
@@ -1754,16 +1754,16 @@ bool ARMConstantIslands::OptimizeThumb2JumpTables(MachineFunction &MF) {
       if (!OptOk)
         continue;
 
-      // Now scan back again to find the tLEApcrel or t2LEApcrelJT instruction
+      // Now scan back again to find the tLEApcrel or t2ADR instruction
       // that gave us the initial base register definition.
       for (--PrevI; PrevI != B && !PrevI->definesRegister(BaseReg); --PrevI)
         ;
 
-      // The instruction should be a tLEApcrel or t2LEApcrelJT; we want
+      // The instruction should be a tLEApcrel or t2ADR; we want
       // to delete it as well.
       MachineInstr *LeaMI = PrevI;
       if ((LeaMI->getOpcode() != ARM::tLEApcrelJT &&
-           LeaMI->getOpcode() != ARM::t2LEApcrelJT) ||
+           LeaMI->getOpcode() != ARM::t2ADR) ||
           LeaMI->getOperand(0).getReg() != BaseReg)
         OptOk = false;
 
index 2714dd256db84b436618a226915fbdd9bf8f2253..109ec0c4478e56251dfa0b5dbd9bb5bfedbe0f1a 100644 (file)
@@ -763,6 +763,21 @@ bool ARMExpandPseudo::ExpandMBB(MachineBasicBlock &MBB) {
       break;
     }
 
+    case ARM::t2LEApcrel:
+    case ARM::t2LEApcrelJT: {
+      bool DstIsDead = MI.getOperand(0).isDead();
+      MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(),
+                                TII->get(ARM::t2ADR))
+        .addReg(MI.getOperand(0).getReg(),
+                RegState::Define | getDeadRegState(DstIsDead)) // Dst reg
+        .addOperand(MI.getOperand(1))      // Label
+        .addOperand(MI.getOperand(2))      // Pred
+        .addOperand(MI.getOperand(3));
+      TransferImpOps(MI, MIB, MIB);
+      MI.eraseFromParent();
+      return MIB;
+    }
+
     case ARM::MOVi32imm:
     case ARM::MOVCCi32imm:
     case ARM::t2MOVi32imm:
index 48d495396e2285bf4ffedb64db7e97c5e7e62ae1..f535608d89a5e84efae85f8ddfa8ba8095e3e40b 100644 (file)
@@ -33,6 +33,9 @@ enum Fixups {
   // fixup_arm_adr_pcrel_12 - 12-bit PC relative relocation for the ADR
   // instruction.
   fixup_arm_adr_pcrel_12,
+  // fixup_t2_adr_pcrel_12 - 12-bit PC relative relocation for the ADR
+  // instruction.
+  fixup_t2_adr_pcrel_12,
   // fixup_arm_branch - 24-bit PC relative relocation for direct branch
   // instructions.
   fixup_arm_branch,
index 2fedb5398ebc2b2c1c540c0fa408c21cc0159634..30d94e4205f96f6fcaa6cb15a9633f9d37f3f758 100644 (file)
@@ -131,6 +131,12 @@ def t2addrmode_imm12 : Operand<i32>,
   let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
 }
 
+// ADR instruction labels.
+def t2adrlabel : Operand<i32> {
+  let EncoderMethod = "getT2AdrLabelOpValue";
+}
+
+
 // t2addrmode_imm8  := reg +/- imm8
 def t2addrmode_imm8 : Operand<i32>,
                       ComplexPattern<i32, 2, "SelectT2AddrModeImm8", []> {
@@ -1128,10 +1134,11 @@ class T2PCOneRegImm<dag oops, dag iops, InstrItinClass itin,
 
 // LEApcrel - Load a pc-relative address into a register without offending the
 // assembler.
-let neverHasSideEffects = 1 in {
-let isReMaterializable = 1 in
-def t2LEApcrel : T2PCOneRegImm<(outs rGPR:$Rd), (ins i32imm:$label, pred:$p), IIC_iALUi,
-                      "adr${p}.w\t$Rd, #$label", []> {
+let neverHasSideEffects = 1, isReMaterializable = 1 in {
+
+def t2ADR : T2PCOneRegImm<(outs rGPR:$Rd),
+              (ins t2adrlabel:$addr, pred:$p),
+              IIC_iALUi, "adr{$p}.w\t$Rd, #$addr", []> {
   let Inst{31-27} = 0b11110;
   let Inst{25-24} = 0b10;
   // Inst{23:21} = '11' (add = FALSE) or '00' (add = TRUE)
@@ -1139,20 +1146,22 @@ def t2LEApcrel : T2PCOneRegImm<(outs rGPR:$Rd), (ins i32imm:$label, pred:$p), II
   let Inst{20} = 0;
   let Inst{19-16} = 0b1111; // Rn
   let Inst{15} = 0;
-
-
+  
+  bits<4> Rd;
+  bits<13> addr;
+  let Inst{11-8} = Rd;
+  let Inst{23}    = addr{12};
+  let Inst{21}    = addr{12};
+  let Inst{26}    = addr{11};
+  let Inst{14-12} = addr{10-8};
+  let Inst{7-0}   = addr{7-0};
 }
-} // neverHasSideEffects
-def t2LEApcrelJT : T2PCOneRegImm<(outs rGPR:$Rd),
+
+def t2LEApcrel : PseudoInst<(outs rGPR:$Rd), (ins i32imm:$label, pred:$p),
+                            IIC_iALUi, []>;
+def t2LEApcrelJT : PseudoInst<(outs rGPR:$Rd),
                         (ins i32imm:$label, nohash_imm:$id, pred:$p), IIC_iALUi,
-                        "adr${p}.w\t$Rd, #${label}_${id}", []> {
-  let Inst{31-27} = 0b11110;
-  let Inst{25-24} = 0b10;
-  // Inst{23:21} = '11' (add = FALSE) or '00' (add = TRUE)
-  let Inst{22} = 0;
-  let Inst{20} = 0;
-  let Inst{19-16} = 0b1111; // Rn
-  let Inst{15} = 0;
+                        []>;
 }
 
 
index 7f34ee96e379ed4eeebb3d0ef26d230bff9ead53..8dca2c35c65b7c3f31e55d798d3f6b2739a72274 100644 (file)
@@ -56,6 +56,8 @@ public:
 { "fixup_t2_pcrel_10",       0,            32,  MCFixupKindInfo::FKF_IsPCRel |
                                                 MCFixupKindInfo::FKF_IsAligned},
 { "fixup_arm_adr_pcrel_12",  1,            24,  MCFixupKindInfo::FKF_IsPCRel },
+{ "fixup_t2_adr_pcrel_12",   0,            32,  MCFixupKindInfo::FKF_IsPCRel |
+                                                MCFixupKindInfo::FKF_IsAligned},
 { "fixup_arm_branch",        1,            24,  MCFixupKindInfo::FKF_IsPCRel },
 { "fixup_t2_condbranch",     0,            32,  MCFixupKindInfo::FKF_IsPCRel },
 { "fixup_t2_uncondbranch",   0,            32,  MCFixupKindInfo::FKF_IsPCRel },
@@ -133,6 +135,9 @@ public:
   /// ADR label target.
   uint32_t getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
                               SmallVectorImpl<MCFixup> &Fixups) const;
+  uint32_t getT2AdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
+                              SmallVectorImpl<MCFixup> &Fixups) const;
+  
 
   /// getAddrModeImm12OpValue - Return encoding info for 'reg +/- imm12'
   /// operand.
@@ -544,6 +549,16 @@ getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
                                   Fixups);
 }
 
+/// getAdrLabelOpValue - Return encoding info for 12-bit immediate ADR label
+/// target.
+uint32_t ARMMCCodeEmitter::
+getT2AdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
+                   SmallVectorImpl<MCFixup> &Fixups) const {
+  assert(MI.getOperand(OpIdx).isExpr() && "Unexpected adr target type!");
+  return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_adr_pcrel_12,
+                                  Fixups);
+}
+
 /// getTAddrModeRegRegOpValue - Return encoding info for 'reg + reg' operand.
 uint32_t ARMMCCodeEmitter::
 getTAddrModeRegRegOpValue(const MCInst &MI, unsigned OpIdx,
index dede4b0244642c03253dd4d0f17c0e2b11062c24..9c27515ec779ef2638fb55f4bab982d1847f9e7c 100644 (file)
@@ -584,6 +584,7 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
   IMM("t_imm_s4");
   IMM("pclabel");
   IMM("adrlabel");
+  IMM("t2adrlabel");
   IMM("shift_imm");
   IMM("neon_vcvt_imm32");