Skip to content

Commit

Permalink
[ARM] Make sure that the constant pool does not keep in the middle of…
Browse files Browse the repository at this point in the history
… 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
llvm-svn: 366905
  • Loading branch information
simpal01 committed Jul 24, 2019
1 parent a19f5a7 commit 724888a
Show file tree
Hide file tree
Showing 2 changed files with 133 additions and 3 deletions.
29 changes: 26 additions & 3 deletions llvm/lib/Target/ARM/ARMConstantIslandPass.cpp
Expand Up @@ -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 +
Expand Down Expand Up @@ -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);
}

Expand Down
107 changes: 107 additions & 0 deletions llvm/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 = '<stdin>'
source_filename = "<stdin>"
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

0 comments on commit 724888a

Please sign in to comment.