diff options
Diffstat (limited to 'llvm/lib/Target/ARM/ARMConstantIslandPass.cpp')
-rw-r--r-- | llvm/lib/Target/ARM/ARMConstantIslandPass.cpp | 16 |
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)); |