Index: lib/Target/ARM/ARMExpandPseudoInsts.cpp |
diff --git a/lib/Target/ARM/ARMExpandPseudoInsts.cpp b/lib/Target/ARM/ARMExpandPseudoInsts.cpp |
index 2d805185e6cdd19a5d54dcc74a308fafe6dfa042..fd5de81a8ddfd626e7dc926d6040130821711112 100644 |
--- a/lib/Target/ARM/ARMExpandPseudoInsts.cpp |
+++ b/lib/Target/ARM/ARMExpandPseudoInsts.cpp |
@@ -24,6 +24,7 @@ |
#include "llvm/CodeGen/MachineFunctionPass.h" |
#include "llvm/CodeGen/MachineInstrBundle.h" |
#include "llvm/CodeGen/MachineInstrBuilder.h" |
+#include "llvm/Target/TargetOptions.h" // @LOCALMOD for llvm::TLSUseCall |
#include "llvm/IR/GlobalValue.h" |
#include "llvm/Support/CommandLine.h" |
#include "llvm/Support/raw_ostream.h" // FIXME: for debug only. remove! |
@@ -47,6 +48,7 @@ namespace { |
const TargetRegisterInfo *TRI; |
const ARMSubtarget *STI; |
ARMFunctionInfo *AFI; |
+ bool IsRelocPIC; // @LOCALMOD |
bool runOnMachineFunction(MachineFunction &Fn) override; |
@@ -67,6 +69,16 @@ namespace { |
unsigned Opc, bool IsExt); |
void ExpandMOV32BitImm(MachineBasicBlock &MBB, |
MachineBasicBlock::iterator &MBBI); |
+ // @LOCALMOD-BEGIN |
+ void AddPICADD_MOVi16_PICID(MachineInstr &MI, |
+ MachineBasicBlock &MBB, |
+ MachineBasicBlock::iterator &MBBI, |
+ bool NotThumb, |
+ unsigned PredReg, ARMCC::CondCodes Pred, |
+ unsigned DstReg, bool DstIsDead, |
+ MachineInstrBuilder &LO16, |
+ MachineInstrBuilder &HI16); |
+ // @LOCALMOD-END |
}; |
char ARMExpandPseudo::ID = 0; |
} |
@@ -493,6 +505,41 @@ void ARMExpandPseudo::ExpandVST(MachineBasicBlock::iterator &MBBI) { |
MI.eraseFromParent(); |
} |
+// @LOCALMOD-BEGIN |
+// AddPICADD_MOVi16_PICID - Inserts a PICADD into the given basic block, |
+// and adds the PC label ID (of the PICADD) as an operand of the LO16 / HI16 |
+// MOVs. The ID operand will follow the "Immediate" operand (assumes that |
+// operand is already added). |
+void ARMExpandPseudo::AddPICADD_MOVi16_PICID(MachineInstr &MI, |
+ MachineBasicBlock &MBB, |
+ MachineBasicBlock::iterator &MBBI, |
+ bool NotThumb, |
+ unsigned PredReg, ARMCC::CondCodes Pred, |
+ unsigned DstReg, bool DstIsDead, |
+ MachineInstrBuilder &LO16, |
+ MachineInstrBuilder &HI16) { |
+ // Throw in a PICADD, and tack on the PC label ID to the MOVT/MOVWs |
+ MachineFunction &MF = *MI.getParent()->getParent(); |
+ ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); |
+ |
+ // Make a unique ID for this PC by pulling from pool of constPoolIDs |
+ unsigned PC_ID = AFI->createPICLabelUId(); |
+ MachineInstrBuilder PicADD = |
+ BuildMI(MBB, MBBI, MI.getDebugLoc(), |
+ TII->get(NotThumb ? ARM::PICADD : ARM::tPICADD)) |
+ .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead)) |
+ .addReg(DstReg) |
+ .addImm(PC_ID) |
+ .addImm(Pred) |
+ .addReg(PredReg); |
+ (void)PicADD; // squelch unused warning. |
+ |
+ // Add the PC label ID after what would have been an absolute address. |
+ LO16 = LO16.addImm(PC_ID); |
+ HI16 = HI16.addImm(PC_ID); |
+} |
+// @LOCALMOD-END |
+ |
/// ExpandLaneOp - Translate VLD*LN and VST*LN instructions with Q, QQ or QQQQ |
/// register operands to real instructions with D register operands. |
void ARMExpandPseudo::ExpandLaneOp(MachineBasicBlock::iterator &MBBI) { |
@@ -690,7 +737,9 @@ void ARMExpandPseudo::ExpandMOV32BitImm(MachineBasicBlock &MBB, |
unsigned LO16Opc = 0; |
unsigned HI16Opc = 0; |
- if (Opcode == ARM::t2MOVi32imm || Opcode == ARM::t2MOVCCi32imm) { |
+ // @LOCALMOD |
+ bool isThumb2 = (Opcode == ARM::t2MOVi32imm || Opcode == ARM::t2MOVCCi32imm); |
+ if (isThumb2) { |
LO16Opc = ARM::t2MOVi16; |
HI16Opc = ARM::t2MOVTi16; |
} else { |
@@ -698,10 +747,28 @@ void ARMExpandPseudo::ExpandMOV32BitImm(MachineBasicBlock &MBB, |
HI16Opc = ARM::MOVTi16; |
} |
+ // @LOCALMOD-BEGIN |
+ // If constant pools are "disabled" (actually, moved to rodata), then |
+ // many addresses (e.g., the addresses of what used to be the "pools") |
+ // may not be materialized in a pc-relative manner, because MOVT / MOVW |
+ // are used to materialize the addresses. |
+ // We need to know if it matters that references are pc-relative |
+ // (e.g., to be PIC). |
+ // See the comments on MOVi16PIC / MOVTi16PIC for more details. |
+ const bool ShouldUseMOV16PIC = !STI->useConstIslands() && IsRelocPIC && |
+ (MO.isCPI() || MO.isJTI() || MO.isGlobal()); // TODO check this list. |
+ if (ShouldUseMOV16PIC) { |
+ if (isThumb2) |
+ llvm_unreachable("FIXME: add PIC versions of t2MOVi16"); |
+ LO16Opc = ARM::MOVi16PIC; |
+ HI16Opc = ARM::MOVTi16PIC; |
+ } |
+ // @LOCALMOD-END |
+ |
LO16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(LO16Opc), DstReg); |
HI16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(HI16Opc)) |
.addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead)) |
- .addReg(DstReg); |
+ .addReg(DstReg, RegState::Kill); // @LOCALMOD |
switch (MO.getType()) { |
case MachineOperand::MO_Immediate: { |
@@ -720,14 +787,35 @@ void ARMExpandPseudo::ExpandMOV32BitImm(MachineBasicBlock &MBB, |
break; |
} |
default: { |
+ if (MO.isGlobal()) { // @LOCALMOD |
const GlobalValue *GV = MO.getGlobal(); |
unsigned TF = MO.getTargetFlags(); |
LO16 = LO16.addGlobalAddress(GV, MO.getOffset(), TF | ARMII::MO_LO16); |
HI16 = HI16.addGlobalAddress(GV, MO.getOffset(), TF | ARMII::MO_HI16); |
+ // @LOCALMOD-START - support for jumptable addresses and CPI |
+ } else if (MO.isCPI()) { |
+ int i = MO.getIndex(); |
+ unsigned TF = MO.getTargetFlags(); |
+ LO16 = LO16.addConstantPoolIndex(i, MO.getOffset(), TF|ARMII::MO_LO16); |
+ HI16 = HI16.addConstantPoolIndex(i, MO.getOffset(), TF|ARMII::MO_HI16); |
+ } else if (MO.isJTI()){ |
+ unsigned TF = MO.getTargetFlags(); |
+ LO16 = LO16.addJumpTableIndex(MO.getIndex(), TF | ARMII::MO_LO16); |
+ HI16 = HI16.addJumpTableIndex(MO.getIndex(), TF | ARMII::MO_HI16); |
+ } else { |
+ assert (0 && "unexpected operand"); |
+ } |
+ // @LOCALMOD-END |
break; |
} |
} |
+ // @LOCALMOD-BEGIN |
+ if (ShouldUseMOV16PIC) { |
+ AddPICADD_MOVi16_PICID(MI, MBB, MBBI, !isThumb2, |
+ PredReg, Pred, DstReg, DstIsDead, LO16, HI16); |
+ } |
+ // @LOCALMOD-END |
LO16->setMemRefs(MI.memoperands_begin(), MI.memoperands_end()); |
HI16->setMemRefs(MI.memoperands_begin(), MI.memoperands_end()); |
LO16.addImm(Pred).addReg(PredReg); |
@@ -927,6 +1015,8 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB, |
} |
case ARM::tTPsoft: |
case ARM::TPsoft: { |
+ // @LOCALMOD-BEGIN |
+ if (!STI->isTargetNaCl() || llvm::TLSUseCall) { |
MachineInstrBuilder MIB; |
if (Opcode == ARM::tTPsoft) |
MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(), |
@@ -934,12 +1024,24 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB, |
.addImm((unsigned)ARMCC::AL).addReg(0) |
.addExternalSymbol("__aeabi_read_tp", 0); |
else |
- MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(), |
+ MIB = BuildMI_NoImp(MBB, MBBI, MI.getDebugLoc(), // @LOCALMOD |
TII->get( ARM::BL)) |
.addExternalSymbol("__aeabi_read_tp", 0); |
MIB->setMemRefs(MI.memoperands_begin(), MI.memoperands_end()); |
TransferImpOps(MI, MIB, MIB); |
+ } else { |
+ // Inline version for native client. |
+ // See native_client/src/untrusted/nacl/aeabi_read_tp.S |
+ // .nexe builds use this version, while irt builds use a call to |
+ // __aeabi_read_tp. |
+ // ldr r0, [r9, #0] |
+ AddDefaultPred(BuildMI(MBB, MBBI, MI.getDebugLoc(), |
+ TII->get(ARM::LDRi12), ARM::R0) |
+ .addReg(ARM::R9) |
+ .addImm(0)); |
+ } |
+ // @LOCALMOD-END |
MI.eraseFromParent(); |
return true; |
} |
@@ -1325,6 +1427,62 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB, |
case ARM::VTBL4Pseudo: ExpandVTBL(MBBI, ARM::VTBL4, false); return true; |
case ARM::VTBX3Pseudo: ExpandVTBL(MBBI, ARM::VTBX3, true); return true; |
case ARM::VTBX4Pseudo: ExpandVTBL(MBBI, ARM::VTBX4, true); return true; |
+ |
+ // @LOCALMOD-BEGIN |
+ case ARM::ARMeh_return: { |
+ // This pseudo instruction is generated as part of the lowering of |
+ // ISD::EH_RETURN (c.f. ARMISelLowering.cpp) |
+ // we convert it to a stack increment by OffsetReg and |
+ // indirect jump to TargetReg |
+ unsigned PredReg = 0; |
+ ARMCC::CondCodes Pred = llvm::getInstrPredicate(&MI, PredReg); |
+ unsigned OffsetReg = MI.getOperand(0).getReg(); |
+ unsigned TargetReg = MI.getOperand(1).getReg(); |
+ BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::ADDrr), ARM::SP) |
+ .addReg(OffsetReg) |
+ .addReg(ARM::SP) |
+ .addImm(Pred) |
+ .addReg(PredReg) |
+ .addReg(0); |
+ |
+ BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::BX)) |
+ .addReg(TargetReg); |
+ MI.eraseFromParent(); |
+ return true; |
+ } |
+ case ARM::MOVGOTAddr : { |
+ // Expand the pseudo-inst that requests for the GOT address |
+ // to be materialized into a register. We use MOVW/MOVT for this. |
+ // See ARMISelLowering.cpp for a comment on the strategy. |
+ unsigned PredReg = 0; |
+ ARMCC::CondCodes Pred = llvm::getInstrPredicate(&MI, PredReg); |
+ unsigned DstReg = MI.getOperand(0).getReg(); |
+ bool DstIsDead = MI.getOperand(0).isDead(); |
+ MachineInstrBuilder LO16, HI16; |
+ |
+ LO16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), |
+ TII->get(ARM::MOVi16PIC), |
+ DstReg) |
+ .addExternalSymbol("_GLOBAL_OFFSET_TABLE_", ARMII::MO_LO16); |
+ |
+ HI16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), |
+ TII->get(ARM::MOVTi16PIC)) |
+ .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead)) |
+ .addReg(DstReg) |
+ .addExternalSymbol("_GLOBAL_OFFSET_TABLE_", ARMII::MO_HI16); |
+ |
+ AddPICADD_MOVi16_PICID(MI, MBB, MBBI, true, |
+ PredReg, Pred, DstReg, DstIsDead, LO16, HI16); |
+ |
+ (*LO16).setMemRefs(MI.memoperands_begin(), MI.memoperands_end()); |
+ (*HI16).setMemRefs(MI.memoperands_begin(), MI.memoperands_end()); |
+ LO16.addImm(Pred).addReg(PredReg); |
+ HI16.addImm(Pred).addReg(PredReg); |
+ TransferImpOps(MI, LO16, HI16); |
+ MI.eraseFromParent(); |
+ return true; |
+ } |
+ // @LOCALMOD-END |
} |
} |
@@ -1348,6 +1506,7 @@ bool ARMExpandPseudo::runOnMachineFunction(MachineFunction &MF) { |
TRI = TM.getSubtargetImpl()->getRegisterInfo(); |
STI = &TM.getSubtarget<ARMSubtarget>(); |
AFI = MF.getInfo<ARMFunctionInfo>(); |
+ IsRelocPIC = MF.getTarget().getRelocationModel() == Reloc::PIC_; |
bool Modified = false; |
for (MachineFunction::iterator MFI = MF.begin(), E = MF.end(); MFI != E; |