summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r--llvm/lib/Target/ARM/ARMConstantIslandPass.cpp16
1 files changed, 16 insertions, 0 deletions
diff --git a/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp b/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp
index 2c4738d3cb7..5e97c4cb35e 100644
--- a/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp
+++ b/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp
@@ -1420,6 +1420,22 @@ void ARMConstantIslands::createNewWater(unsigned CPUserIndex,
MI = LastIT;
}
+ // Avoid splitting a MOVW+MOVT pair with a relocation on Windows.
+ // On Windows, this instruction pair is covered by one single
+ // IMAGE_REL_ARM_MOV32T relocation which covers both instructions. If a
+ // constant island is injected inbetween them, the relocation will clobber
+ // the instruction and fail to update the MOVT instruction.
+ // (These instructions are bundled up until right before the ConstantIslands
+ // pass.)
+ if (STI->isTargetWindows() && isThumb && MI->getOpcode() == ARM::t2MOVTi16 &&
+ (MI->getOperand(2).getTargetFlags() & ARMII::MO_OPTION_MASK) ==
+ ARMII::MO_HI16) {
+ --MI;
+ assert(MI->getOpcode() == ARM::t2MOVi16 &&
+ (MI->getOperand(1).getTargetFlags() & ARMII::MO_OPTION_MASK) ==
+ ARMII::MO_LO16);
+ }
+
// We really must not split an IT block.
LLVM_DEBUG(unsigned PredReg; assert(
!isThumb || getITInstrPredicate(*MI, PredReg) == ARMCC::AL));
OpenPOWER on IntegriCloud