diff --git a/lib/Target/ARM/ARMExpandPseudoInsts.cpp b/lib/Target/ARM/ARMExpandPseudoInsts.cpp index d3219aa6ef0..f9b612f5890 100644 --- a/lib/Target/ARM/ARMExpandPseudoInsts.cpp +++ b/lib/Target/ARM/ARMExpandPseudoInsts.cpp @@ -615,6 +615,39 @@ void ARMExpandPseudo::ExpandVTBL(MachineBasicBlock::iterator &MBBI, MI.eraseFromParent(); } +static bool IsAnAddressOperand(const MachineOperand &MO) { + // This check is overly conservative. Unless we are certain that the machine + // operand is not a symbol reference, we return that it is a symbol reference. + // This is important as the load pair may not be split up Windows. + switch (MO.getType()) { + default: llvm_unreachable("unhandled machine operand type"); + case MachineOperand::MO_Register: + case MachineOperand::MO_Immediate: + case MachineOperand::MO_CImmediate: + case MachineOperand::MO_FPImmediate: + return false; + case MachineOperand::MO_MachineBasicBlock: + return true; + case MachineOperand::MO_FrameIndex: + return false; + case MachineOperand::MO_ConstantPoolIndex: + case MachineOperand::MO_TargetIndex: + case MachineOperand::MO_JumpTableIndex: + case MachineOperand::MO_ExternalSymbol: + case MachineOperand::MO_GlobalAddress: + case MachineOperand::MO_BlockAddress: + return true; + case MachineOperand::MO_RegisterMask: + case MachineOperand::MO_RegisterLiveOut: + return false; + case MachineOperand::MO_Metadata: + case MachineOperand::MO_MCSymbol: + return true; + case MachineOperand::MO_CFIIndex: + return false; + } +} + void ARMExpandPseudo::ExpandMOV32BitImm(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI) { MachineInstr &MI = *MBBI; @@ -625,10 +658,14 @@ void ARMExpandPseudo::ExpandMOV32BitImm(MachineBasicBlock &MBB, bool DstIsDead = MI.getOperand(0).isDead(); bool isCC = Opcode == ARM::MOVCCi32imm || Opcode == ARM::t2MOVCCi32imm; const MachineOperand &MO = MI.getOperand(isCC ? 2 : 1); + bool RequiresBundling = STI->isTargetWindows() && IsAnAddressOperand(MO); MachineInstrBuilder LO16, HI16; if (!STI->hasV6T2Ops() && (Opcode == ARM::MOVi32imm || Opcode == ARM::MOVCCi32imm)) { + // FIXME Windows CE supports older ARM CPUs + assert(!STI->isTargetWindows() && "Windows on ARM requires ARMv7+"); + // Expand into a movi + orr. LO16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVi), DstReg); HI16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::ORRri)) @@ -660,6 +697,9 @@ void ARMExpandPseudo::ExpandMOV32BitImm(MachineBasicBlock &MBB, HI16Opc = ARM::MOVTi16; } + if (RequiresBundling) + BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(TargetOpcode::BUNDLE)); + 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)) @@ -683,6 +723,11 @@ void ARMExpandPseudo::ExpandMOV32BitImm(MachineBasicBlock &MBB, LO16.addImm(Pred).addReg(PredReg); HI16.addImm(Pred).addReg(PredReg); + if (RequiresBundling) { + LO16->bundleWithPred(); + HI16->bundleWithPred(); + } + TransferImpOps(MI, LO16, HI16); MI.eraseFromParent(); } diff --git a/test/CodeGen/ARM/Windows/movw-movt-relocations.ll b/test/CodeGen/ARM/Windows/movw-movt-relocations.ll new file mode 100644 index 00000000000..3ae6428d3a6 --- /dev/null +++ b/test/CodeGen/ARM/Windows/movw-movt-relocations.ll @@ -0,0 +1,27 @@ +; RUN: llc -mtriple=thumbv7-windows -o - %s \ +; RUN: | FileCheck %s -check-prefix CHECK-WINDOWS + +; RUN: llc -mtriple=thumbv7-eabi -o - %s \ +; RUN: | FileCheck %s -check-prefix CHECK-EABI + +@i = common global i32 0, align 4 +@j = common global i32 0, align 4 + +; Function Attrs: nounwind optsize readonly +define i32 @relocation(i32 %j, i32 %k) { +entry: + %0 = load i32* @i, align 4 + %1 = load i32* @j, align 4 + %add = add nsw i32 %1, %0 + ret i32 %add +} + +; CHECK-WINDOWS: movw r[[i:[0-4]]], :lower16:i +; CHECK-WINDOWS-NEXT: movt r[[i]], :upper16:i +; CHECK-WINDOWS: movw r[[j:[0-4]]], :lower16:j +; CHECK-WINDOWS-NEXT: movt r[[j]], :upper16:j + +; CHECK-EABI: movw r[[i:[0-4]]], :lower16:i +; CHECK-EABI: movw r[[j:[0-4]]], :lower16:j +; CHECK-EABI-NEXT: movt r[[i]], :upper16:i +; CHECK-EABI-NEXT: movt r[[j]], :upper16:j