Index: lib/Target/ARM/ARMHazardRecognizer.cpp =================================================================== --- lib/Target/ARM/ARMHazardRecognizer.cpp +++ lib/Target/ARM/ARMHazardRecognizer.cpp @@ -11,6 +11,7 @@ #include "ARMBaseInstrInfo.h" #include "ARMBaseRegisterInfo.h" #include "ARMSubtarget.h" +#include "llvm/ADT/Triple.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/ScheduleDAG.h" #include "llvm/Target/TargetRegisterInfo.h" @@ -31,12 +32,56 @@ return false; } +static bool IsAddress(const MachineOperand &MO) { + return MO.isGlobal() || MO.isSymbol() || MO.isCPI(); +} + +static bool IsAddressPair(const MachineOperand &MO0, const MachineOperand &MO1) { + if (MO0.getType() != MO1.getType()) + return false; + + switch (MO0.getType()) { + case MachineOperand::MO_ConstantPoolIndex: + if (MO0.getIndex() == MO1.getIndex()) + break; + return false; + case MachineOperand::MO_GlobalAddress: + if (MO0.getGlobal() == MO1.getGlobal()) + break; + return false; + case MachineOperand::MO_ExternalSymbol: + if (StringRef(MO0.getSymbolName()) == StringRef(MO1.getSymbolName())) + break; + return false; + default: + return false; + } + return MO0.getOffset() == MO1.getOffset(); +} + ScheduleHazardRecognizer::HazardType ARMHazardRecognizer::getHazardType(SUnit *SU, int Stalls) { assert(Stalls == 0 && "ARM hazards don't support scoreboard lookahead"); MachineInstr *MI = SU->getInstr(); + const Triple TT(MI->getParent()->getParent()->getTarget().getTargetTriple()); + if (TT.isOSWindows()) { + if (LastMI && LastMI->getOpcode() == ARM::t2MOVi16 && + IsAddress(LastMI->getOperand(1))) { + // If there is a previous instruction of type mov.w of an address, there + // is a hazard for any instruction other than the mov.t that loads the + // high portion of the address as the Windows loader expects that the two + // instructions are contiguous. + assert(LastMI->getOperand(1).getTargetFlags() == ARMII::MO_LO16 && + "expected low address load"); + if (MI->getOpcode() == ARM::t2MOVTi16 && + IsAddressPair(LastMI->getOperand(1), MI->getOperand(2))) + return NoHazard; + return Hazard; + } + } + if (!MI->isDebugValue()) { // Look for special VMLA / VMLS hazards. A VMUL / VADD / VSUB following // a VMLA / VMLS will cause 4 cycle stall. Index: test/CodeGen/ARM/Windows/movw-movt-relocations.ll =================================================================== --- /dev/null +++ test/CodeGen/ARM/Windows/movw-movt-relocations.ll @@ -0,0 +1,28 @@ +; 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 +