From daba8d4a7c5782356a0cd3a637c4f71469066378 Mon Sep 17 00:00:00 2001 From: Simi Pallipurath Date: Wed, 24 Jul 2019 13:54:14 +0000 Subject: [PATCH] [ARM] Make sure that the constant pool does not keep in the middle of an IT block. This change make sure that llvm does not emit an invalid IT block by putting the constant pool in the middle of an IT block. We have code to try to avoid putting a constant island in the middle of an IT block, but it only works if we see an IT between the one currently referencing CPE and possible insertion point. If the first instruction we look at is the VLDRD after the IT , we never see the IT and does not realize that the instruction doing the load could be in an IT block itself. Differential Revision: https://reviews.llvm.org/D64621 Change-Id: I24cecb37cded75e8992870bd997f6226853bd920 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@366905 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMConstantIslandPass.cpp | 29 ++++- .../CodeGen/ARM/constant-islands-split-IT.mir | 107 ++++++++++++++++++ 2 files changed, 133 insertions(+), 3 deletions(-) create mode 100644 test/CodeGen/ARM/constant-islands-split-IT.mir diff --git a/lib/Target/ARM/ARMConstantIslandPass.cpp b/lib/Target/ARM/ARMConstantIslandPass.cpp index 60e5d7bf609..46e497ea098 100644 --- a/lib/Target/ARM/ARMConstantIslandPass.cpp +++ b/lib/Target/ARM/ARMConstantIslandPass.cpp @@ -1337,6 +1337,28 @@ void ARMConstantIslands::createNewWater(unsigned CPUserIndex, BaseInsertOffset = std::max(UserBBI.postOffset() - UPad - 8, UserOffset + TII->getInstSizeInBytes(*UserMI) + 1); + // If the CP is referenced(ie, UserOffset) is in first four instructions + // after IT, this recalculated BaseInsertOffset could be in the middle of + // an IT block. If it is, change the BaseInsertOffset to just after the + // IT block. This still make the CP Entry is in range becuase of the + // following reasons. + // 1. The initial BaseseInsertOffset calculated is (UserOffset + + // U.getMaxDisp() - UPad). + // 2. An IT block is only at most 4 instructions plus the "it" itself (18 + // bytes). + // 3. All the relevant instructions support much larger Maximum + // displacement. + MachineBasicBlock::iterator I = UserMI; + ++I; + for (unsigned Offset = UserOffset + TII->getInstSizeInBytes(*UserMI), + PredReg = 0; + I->getOpcode() != ARM::t2IT && + getITInstrPredicate(*I, PredReg) != ARMCC::AL; + Offset += TII->getInstSizeInBytes(*I), I = std::next(I)) { + BaseInsertOffset = + std::max(BaseInsertOffset, Offset + TII->getInstSizeInBytes(*I) + 1); + assert(I != UserMBB->end() && "Fell off end of block"); + } LLVM_DEBUG(dbgs() << format("Move inside block: %#x\n", BaseInsertOffset)); } unsigned EndInsertOffset = BaseInsertOffset + 4 + UPad + @@ -1397,9 +1419,10 @@ void ARMConstantIslands::createNewWater(unsigned CPUserIndex, } // We really must not split an IT block. - LLVM_DEBUG(unsigned PredReg; assert( - !isThumb || getITInstrPredicate(*MI, PredReg) == ARMCC::AL)); - +#ifndef NDEBUG + unsigned PredReg; + assert(!isThumb || getITInstrPredicate(*MI, PredReg) == ARMCC::AL); +#endif NewMBB = splitBlockBeforeInstr(&*MI); } diff --git a/test/CodeGen/ARM/constant-islands-split-IT.mir b/test/CodeGen/ARM/constant-islands-split-IT.mir new file mode 100644 index 00000000000..47b3cd1c43d --- /dev/null +++ b/test/CodeGen/ARM/constant-islands-split-IT.mir @@ -0,0 +1,107 @@ +# RUN: llc -run-pass=arm-cp-islands %s -o - | FileCheck %s + +# This test make sure that the constant pool does not keep in the middle of an IT block +# when needs to split a block to place them. +# + +--- | + ; ModuleID = '' + source_filename = "" + target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" + target triple = "thumbv8m.main-arm-none-eabi" + + %struct.e = type { double, double, double } + + declare i32 @llvm.arm.space(i32, i32) + + define hidden arm_aapcs_vfpcc %struct.e @h() { + unreachable + } + +... +--- +name: h +alignment: 2 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +failedISel: false +tracksRegLiveness: true +hasWinCFI: false +registers: [] +liveins: [] +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 64 + offsetAdjustment: -40 + maxAlignment: 4 + adjustsStack: true + hasCalls: true + maxCallFrameSize: 0 + cvBytesOfCalleeSavedRegisters: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + localFrameSize: 28 + savePoint: '' + restorePoint: '' +fixedStack: [] +callSites: [] +constants: + - id: 0 + value: 'double 0.000000e+00' + alignment: 8 + isTargetSpecific: false + - id: 1 + value: 'double 7.020000e+02' + alignment: 8 + isTargetSpecific: false + - id: 2 + value: 'double 2.020000e+02' + alignment: 8 + isTargetSpecific: false +machineFunctionInfo: {} +body: | + bb.0: + successors: %bb.1(0x80000000) + + renamable $d0 = VLDRD %const.0, 0, 14, $noreg :: (load 8 from constant-pool) + dead renamable $r0 = SPACE 40, undef renamable $r0 + + bb.1: + successors: %bb.2(0x80000000) + + dead renamable $r0 = SPACE 790, undef renamable $r0 + + bb.2: + successors: + + renamable $r0 = t2MOVi 0, 14, _, _ + t2CMPri $r0, 32, 14, $noreg, implicit-def $cpsr + renamable $r0 = SPACE 200, undef renamable $r0 + ; CHECK: t2IT 0, 1, implicit-def $itstate + ; CHECK-NEXT: renamable $d0 = VLDRD %const.7, 0, 0, $cpsr, implicit $itstate :: (load 8 from constant-pool) + ; CHECK-NEXT: renamable $d1 = VLDRD %const.5, 0, 0, $cpsr, implicit $itstate :: (load 8 from constant-pool) + ; CHECK-NEXT: renamable $d2 = VLDRD %const.6, 0, 0, $cpsr, implicit $itstate :: (load 8 from constant-pool) + ; CHECK-NEXT: $r0 = t2SUBri $r0, 12, 0, $cpsr, $noreg, implicit killed $itstate + t2IT 0, 1, implicit-def $itstate + renamable $d0 = VLDRD %const.1, 0, 0, $cpsr, implicit $itstate :: (load 8 from constant-pool) + renamable $d1 = VLDRD %const.2, 0, 0, $cpsr, implicit $itstate :: (load 8 from constant-pool) + renamable $d2 = VLDRD %const.0, 0, 0, $cpsr, implicit $itstate :: (load 8 from constant-pool) + $r0 = t2SUBri $r0, 12, 0, $cpsr, $noreg, implicit killed $itstate + t2IT 0, 4, implicit-def $itstate + $sp = tMOVr $r0, 0, $cpsr, implicit $itstate + $sp = t2LDMIA_RET $sp, 0, killed $cpsr, def $r4, def $r5, def $r6, def $r7, def $r8, def $r9, def $r10, def $r11, def $pc, implicit killed $d0, implicit killed $d1, implicit killed $d2, implicit $sp, implicit killed $itstate + tBL 14, $noreg, &__stack_chk_fail, csr_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp + + bb.3: + successors: %bb.3(0x80000000) + liveins: $r0 + + dead renamable $r0 = SPACE 4000, undef renamable $r0 + t2B %bb.3, 14, $noreg + -- 2.40.0