From 5ab1d107bb247db7e802e7041c4314bc6afcaa05 Mon Sep 17 00:00:00 2001 From: Martin Storsjo Date: Wed, 22 Aug 2018 20:34:12 +0000 Subject: [ARM] Avoid injecting constant islands in movw+movt pairs on Windows On Windows, movw+movt pairs with relocations are handled with a single relocation that covers them both. Therefore we can't inject anything between these instructions, otherwise the relocation (which in LLVM only is treated as the movw instruction's relocation, while the movt instruction's relocation is dropped) will end up bogus. These instructions are bundled up until right before the constant islands pass, making this effectively the only place that can split them apart. Differential Revision: https://reviews.llvm.org/D51032 llvm-svn: 340451 --- llvm/lib/Target/ARM/ARMConstantIslandPass.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'llvm/lib/Target/ARM/ARMConstantIslandPass.cpp') 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)); -- cgit v1.2.3