mirror of
https://github.com/RPCS3/llvm.git
synced 2025-02-19 10:15:00 +00:00
[if-converter] Handle BBs that terminate in ret during diamond conversion
This fixes https://llvm.org/PR36825. Original patch by Valentin Churavy (D45218). Differential Revision: https://reviews.llvm.org/D45731 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@330345 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
980f5afda1
commit
e21049990a
@ -1714,20 +1714,25 @@ bool IfConverter::IfConvertDiamondCommon(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Remove the duplicated instructions at the beginnings of both paths.
|
// Remove the duplicated instructions at the beginnings of both paths.
|
||||||
// Skip dbg_value instructions
|
// Skip dbg_value instructions.
|
||||||
MachineBasicBlock::iterator DI1 = MBB1.getFirstNonDebugInstr();
|
MachineBasicBlock::iterator DI1 = MBB1.getFirstNonDebugInstr();
|
||||||
MachineBasicBlock::iterator DI2 = MBB2.getFirstNonDebugInstr();
|
MachineBasicBlock::iterator DI2 = MBB2.getFirstNonDebugInstr();
|
||||||
BBI1->NonPredSize -= NumDups1;
|
BBI1->NonPredSize -= NumDups1;
|
||||||
BBI2->NonPredSize -= NumDups1;
|
BBI2->NonPredSize -= NumDups1;
|
||||||
|
|
||||||
// Skip past the dups on each side separately since there may be
|
// Skip past the dups on each side separately since there may be
|
||||||
// differing dbg_value entries.
|
// differing dbg_value entries. NumDups1 can include a "return"
|
||||||
|
// instruction, if it's not marked as "branch".
|
||||||
for (unsigned i = 0; i < NumDups1; ++DI1) {
|
for (unsigned i = 0; i < NumDups1; ++DI1) {
|
||||||
|
if (DI1 == MBB1.end())
|
||||||
|
break;
|
||||||
if (!DI1->isDebugValue())
|
if (!DI1->isDebugValue())
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
while (NumDups1 != 0) {
|
while (NumDups1 != 0) {
|
||||||
++DI2;
|
++DI2;
|
||||||
|
if (DI2 == MBB2.end())
|
||||||
|
break;
|
||||||
if (!DI2->isDebugValue())
|
if (!DI2->isDebugValue())
|
||||||
--NumDups1;
|
--NumDups1;
|
||||||
}
|
}
|
||||||
@ -1738,11 +1743,16 @@ bool IfConverter::IfConvertDiamondCommon(
|
|||||||
Redefs.stepForward(MI, Dummy);
|
Redefs.stepForward(MI, Dummy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BBI.BB->splice(BBI.BB->end(), &MBB1, MBB1.begin(), DI1);
|
BBI.BB->splice(BBI.BB->end(), &MBB1, MBB1.begin(), DI1);
|
||||||
MBB2.erase(MBB2.begin(), DI2);
|
MBB2.erase(MBB2.begin(), DI2);
|
||||||
|
|
||||||
// The branches have been checked to match, so it is safe to remove the branch
|
// The branches have been checked to match, so it is safe to remove the
|
||||||
// in BB1 and rely on the copy in BB2
|
// branch in BB1 and rely on the copy in BB2. The complication is that
|
||||||
|
// the blocks may end with a return instruction, which may or may not
|
||||||
|
// be marked as "branch". If it's not, then it could be included in
|
||||||
|
// "dups1", leaving the blocks potentially empty after moving the common
|
||||||
|
// duplicates.
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
// Unanalyzable branches must match exactly. Check that now.
|
// Unanalyzable branches must match exactly. Check that now.
|
||||||
if (!BBI1->IsBrAnalyzable)
|
if (!BBI1->IsBrAnalyzable)
|
||||||
@ -1768,11 +1778,14 @@ bool IfConverter::IfConvertDiamondCommon(
|
|||||||
if (RemoveBranch)
|
if (RemoveBranch)
|
||||||
BBI2->NonPredSize -= TII->removeBranch(*BBI2->BB);
|
BBI2->NonPredSize -= TII->removeBranch(*BBI2->BB);
|
||||||
else {
|
else {
|
||||||
do {
|
// Make DI2 point to the end of the range where the common "tail"
|
||||||
assert(DI2 != MBB2.begin());
|
// instructions could be found.
|
||||||
DI2--;
|
while (DI2 != MBB2.begin()) {
|
||||||
} while (DI2->isBranch() || DI2->isDebugValue());
|
MachineBasicBlock::iterator Prev = std::prev(DI2);
|
||||||
DI2++;
|
if (!Prev->isBranch() && !Prev->isDebugValue())
|
||||||
|
break;
|
||||||
|
DI2 = Prev;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
while (NumDups2 != 0) {
|
while (NumDups2 != 0) {
|
||||||
// NumDups2 only counted non-dbg_value instructions, so this won't
|
// NumDups2 only counted non-dbg_value instructions, so this won't
|
||||||
@ -1833,11 +1846,15 @@ bool IfConverter::IfConvertDiamondCommon(
|
|||||||
// a non-predicated in BBI2, then we don't want to predicate the one from
|
// a non-predicated in BBI2, then we don't want to predicate the one from
|
||||||
// BBI2. The reason is that if we merged these blocks, we would end up with
|
// BBI2. The reason is that if we merged these blocks, we would end up with
|
||||||
// two predicated terminators in the same block.
|
// two predicated terminators in the same block.
|
||||||
|
// Also, if the branches in MBB1 and MBB2 were non-analyzable, then don't
|
||||||
|
// predicate them either. They were checked to be identical, and so the
|
||||||
|
// same branch would happen regardless of which path was taken.
|
||||||
if (!MBB2.empty() && (DI2 == MBB2.end())) {
|
if (!MBB2.empty() && (DI2 == MBB2.end())) {
|
||||||
MachineBasicBlock::iterator BBI1T = MBB1.getFirstTerminator();
|
MachineBasicBlock::iterator BBI1T = MBB1.getFirstTerminator();
|
||||||
MachineBasicBlock::iterator BBI2T = MBB2.getFirstTerminator();
|
MachineBasicBlock::iterator BBI2T = MBB2.getFirstTerminator();
|
||||||
if (BBI1T != MBB1.end() && TII->isPredicated(*BBI1T) &&
|
bool BB1Predicated = BBI1T != MBB1.end() && TII->isPredicated(*BBI1T);
|
||||||
BBI2T != MBB2.end() && !TII->isPredicated(*BBI2T))
|
bool BB2NonPredicated = BBI2T != MBB2.end() && !TII->isPredicated(*BBI2T);
|
||||||
|
if (BB2NonPredicated && (BB1Predicated || !BBI2->IsBrAnalyzable))
|
||||||
--DI2;
|
--DI2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
25
test/CodeGen/Hexagon/ifcvt-diamond-ret.mir
Normal file
25
test/CodeGen/Hexagon/ifcvt-diamond-ret.mir
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# RUN: llc -march=hexagon -run-pass if-converter %s -o - | FileCheck %s
|
||||||
|
|
||||||
|
# Make sure this gets if-converted and it doesn't crash.
|
||||||
|
# CHECK-LABEL: bb.0
|
||||||
|
# CHECK: PS_jmpret $r31
|
||||||
|
# CHECK-NOT: bb.{{[1-9]+}}:
|
||||||
|
|
||||||
|
---
|
||||||
|
name: fred
|
||||||
|
tracksRegLiveness: true
|
||||||
|
body: |
|
||||||
|
bb.0:
|
||||||
|
successors: %bb.1, %bb.2
|
||||||
|
liveins: $r0
|
||||||
|
renamable $p0 = C2_cmpeqi killed renamable $r0, 0
|
||||||
|
J2_jumpf killed renamable $p0, %bb.2, implicit-def dead $pc
|
||||||
|
|
||||||
|
bb.1:
|
||||||
|
S4_storeiri_io undef renamable $r0, 0, 32768 :: (store 4 into `i32* undef`)
|
||||||
|
PS_jmpret $r31, implicit-def dead $pc
|
||||||
|
|
||||||
|
bb.2:
|
||||||
|
S4_storeiri_io undef renamable $r0, 0, 32768 :: (store 4 into `i32* undef`)
|
||||||
|
PS_jmpret $r31, implicit-def dead $pc
|
||||||
|
...
|
34
test/CodeGen/MIR/PowerPC/ifcvt-diamond-ret.mir
Normal file
34
test/CodeGen/MIR/PowerPC/ifcvt-diamond-ret.mir
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# RUN: llc -mtriple=powerpc64le-unknown-linux-gnu -run-pass=if-converter %s -o - | FileCheck %s
|
||||||
|
---
|
||||||
|
name: foo
|
||||||
|
body: |
|
||||||
|
bb.0:
|
||||||
|
liveins: $x0, $x3
|
||||||
|
successors: %bb.1(0x40000000), %bb.2(0x40000000)
|
||||||
|
|
||||||
|
dead renamable $x3 = ANDIo8 killed renamable $x3, 1, implicit-def dead $cr0, implicit-def $cr0gt
|
||||||
|
$cr2lt = CROR $cr0gt, $cr0gt
|
||||||
|
BCn killed renamable $cr2lt, %bb.2
|
||||||
|
B %bb.1
|
||||||
|
|
||||||
|
bb.1:
|
||||||
|
renamable $x3 = LIS8 4096
|
||||||
|
MTLR8 $x0, implicit-def $lr8
|
||||||
|
BLR8 implicit $lr8, implicit $rm, implicit $x3
|
||||||
|
|
||||||
|
bb.2:
|
||||||
|
renamable $x3 = LIS8 4096
|
||||||
|
MTLR8 $x0, implicit-def $lr8
|
||||||
|
BLR8 implicit $lr8, implicit $rm, implicit $x3
|
||||||
|
...
|
||||||
|
|
||||||
|
# Diamond testcase with equivalent branches terminating in returns.
|
||||||
|
|
||||||
|
# CHECK: body: |
|
||||||
|
# CHECK: bb.0:
|
||||||
|
# CHECK: dead renamable $x3 = ANDIo8 killed renamable $x3, 1, implicit-def dead $cr0, implicit-def $cr0gt
|
||||||
|
# CHECK: $cr2lt = CROR $cr0gt, $cr0gt
|
||||||
|
# CHECK: renamable $x3 = LIS8 4096
|
||||||
|
# CHECK: MTLR8 $x0, implicit-def $lr8
|
||||||
|
# CHECK: BLR8 implicit $lr8, implicit $rm, implicit $x3
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user