Skip to content

Commit 4331f19

Browse files
[ISEL][BitTestBlock] omit additional bit test when default destination is unreachable
Otherwise we end up with an extra conditional jump, following by an unconditional jump off the end of a function. ie. bb.0: BT32rr .. JCC_1 %bb.4 ... bb.1: BT32rr .. JCC_1 %bb.2 ... JMP_1 %bb.3 bb.2: ... bb.3.unreachable: bb.4: ... Should be equivalent to: bb.0: BT32rr .. JCC_1 %bb.4 ... JMP_1 %bb.2 bb.1: bb.2: ... bb.3.unreachable: bb.4: ... This can occur since at the higher level IR (Instruction) SwitchInsts are required to have BBs for default destinations, even when it can be deduced that such BBs are unreachable. For most programs, this isn't an issue, just wasted instructions since the unreachable has been statically proven. The x86_64 Linux kernel when built with CONFIG_LTO_CLANG_THIN=y fails to boot though once D106056 is re-applied. D106056 makes it more likely that correlation-propagation (CVP) can deduce that the default case of SwitchInsts are unreachable. The x86_64 kernel uses a binary post processor called objtool, which emits this warning: vmlinux.o: warning: objtool: cfg80211_edmg_chandef_valid()+0x169: can't find jump dest instruction at .text.cfg80211_edmg_chandef_valid+0x17b I haven't debugged precisely why this causes a failure at boot time, but fixing this very obvious jump off the end of the function fixes the warning and boot problem. Link: https://bugs.llvm.org/show_bug.cgi?id=50080 Fixes: ClangBuiltLinux/linux#679 Fixes: ClangBuiltLinux/linux#1440 Reviewed By: hans Differential Revision: https://reviews.llvm.org/D109103
1 parent 3f87513 commit 4331f19

File tree

5 files changed

+29
-58
lines changed

5 files changed

+29
-58
lines changed

llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3019,7 +3019,7 @@ void IRTranslator::finalizeBasicBlock() {
30193019
// test, and delete the last bit test.
30203020

30213021
MachineBasicBlock *NextMBB;
3022-
if (BTB.ContiguousRange && j + 2 == ej) {
3022+
if ((BTB.ContiguousRange || BTB.OmitRangeCheck) && j + 2 == ej) {
30233023
// Second-to-last bit-test with contiguous range: fall through to the
30243024
// target of the final bit test.
30253025
NextMBB = BTB.Cases[j + 1].TargetBB;
@@ -3033,7 +3033,7 @@ void IRTranslator::finalizeBasicBlock() {
30333033

30343034
emitBitTestCase(BTB, NextMBB, UnhandledProb, BTB.Reg, BTB.Cases[j], MBB);
30353035

3036-
if (BTB.ContiguousRange && j + 2 == ej) {
3036+
if ((BTB.ContiguousRange || BTB.OmitRangeCheck) && j + 2 == ej) {
30373037
// We need to record the replacement phi edge here that normally
30383038
// happens in emitBitTestCase before we delete the case, otherwise the
30393039
// phi edge will be lost.

llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10869,10 +10869,9 @@ void SelectionDAGBuilder::lowerWorkItem(SwitchWorkListItem W, Value *Cond,
1086910869
BTB->DefaultProb -= DefaultProb / 2;
1087010870
}
1087110871

10872-
if (FallthroughUnreachable) {
10873-
// Skip the range check if the fallthrough block is unreachable.
10872+
// Skip the range check if the fallthrough block is unreachable.
10873+
if (FallthroughUnreachable)
1087410874
BTB->OmitRangeCheck = true;
10875-
}
1087610875

1087710876
// If we're in the right place, emit the bit test header right now.
1087810877
if (CurMBB == SwitchMBB) {

llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1864,9 +1864,9 @@ SelectionDAGISel::FinishBasicBlock() {
18641864
// test, and delete the last bit test.
18651865

18661866
MachineBasicBlock *NextMBB;
1867-
if (BTB.ContiguousRange && j + 2 == ej) {
1868-
// Second-to-last bit-test with contiguous range: fall through to the
1869-
// target of the final bit test.
1867+
if ((BTB.ContiguousRange || BTB.OmitRangeCheck) && j + 2 == ej) {
1868+
// Second-to-last bit-test with contiguous range or omitted range
1869+
// check: fall through to the target of the final bit test.
18701870
NextMBB = BTB.Cases[j + 1].TargetBB;
18711871
} else if (j + 1 == ej) {
18721872
// For the last bit test, fall through to Default.
@@ -1883,7 +1883,7 @@ SelectionDAGISel::FinishBasicBlock() {
18831883
SDB->clear();
18841884
CodeGenAndEmitDAG();
18851885

1886-
if (BTB.ContiguousRange && j + 2 == ej) {
1886+
if ((BTB.ContiguousRange || BTB.OmitRangeCheck) && j + 2 == ej) {
18871887
// Since we're not going to use the final bit test, remove it.
18881888
BTB.Cases.pop_back();
18891889
break;

llvm/test/CodeGen/X86/SwitchLowering.ll

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -62,27 +62,22 @@ bb7: ; preds = %bb, %bb
6262

6363
declare void @foo(i8)
6464

65+
; PR50080
66+
; The important part of this test is that we emit only 1 bit test rather than
67+
; 2 since the default BB of the switch is unreachable.
6568
define i32 @baz(i32 %0) {
66-
; FIXME: Get rid of this conditional jump and bit test in .LBB1_1.
67-
; FIXME: .LBB1_4 should not have .LBB1_1 as a predecessor, or be past the end
68-
; FIXME: of the function.
6969
; CHECK-LABEL: baz:
7070
; CHECK: # %bb.0:
7171
; CHECK-NEXT: xorl %eax, %eax
7272
; CHECK-NEXT: movl {{[0-9]+}}(%esp), %ecx
7373
; CHECK-NEXT: movl $13056, %edx # imm = 0x3300
7474
; CHECK-NEXT: btl %ecx, %edx
7575
; CHECK-NEXT: jae .LBB1_1
76-
; CHECK-NEXT: # %bb.3: # %return
76+
; CHECK-NEXT: # %bb.2: # %return
7777
; CHECK-NEXT: retl
78-
; CHECK-NEXT: .LBB1_1:
79-
; CHECK-NEXT: movl $48, %eax
80-
; CHECK-NEXT: btl %ecx, %eax
81-
; CHECK-NEXT: jae .LBB1_4
82-
; CHECK-NEXT: # %bb.2: # %sw.epilog8
78+
; CHECK-NEXT: .LBB1_1: # %sw.epilog8
8379
; CHECK-NEXT: movl $1, %eax
8480
; CHECK-NEXT: retl
85-
; CHECK-NEXT: .LBB1_4: # %if.then.unreachabledefault
8681
switch i32 %0, label %if.then.unreachabledefault [
8782
i32 4, label %sw.epilog8
8883
i32 5, label %sw.epilog8

llvm/test/CodeGen/X86/switch-bit-test-unreachable-default.ll

Lines changed: 16 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77

88
; PR50080
99
define i32 @baz(i32 %0) {
10-
; FIXME: Get rid of this conditional jump and bit test in bb.5.
11-
; FIXME: bb.2 should not have bb.5 as a predecessor.
1210
; CHECK-SDISEL: bb.0 (%ir-block.1):
1311
; CHECK-SDISEL: successors: %bb.4(0x80000000); %bb.4(100.00%)
1412
; CHECK-SDISEL: liveins: $edi
@@ -17,77 +15,56 @@ define i32 @baz(i32 %0) {
1715
; CHECK-SDISEL: %3:gr32 = COPY %1:gr32
1816
; CHECK-SDISEL: bb.4 (%ir-block.1):
1917
; CHECK-SDISEL: ; predecessors: %bb.0
20-
; CHECK-SDISEL: successors: %bb.3(0x55555555), %bb.5(0x2aaaaaab); %bb.3(66.67%), %bb.5(33.33%)
18+
; CHECK-SDISEL: successors: %bb.3(0x55555555), %bb.1(0x2aaaaaab); %bb.3(66.67%), %bb.1(33.33%)
2119
; CHECK-SDISEL: %4:gr32 = MOV32ri 13056
2220
; CHECK-SDISEL: BT32rr killed %4:gr32, %3:gr32, implicit-def $eflags
2321
; CHECK-SDISEL: JCC_1 %bb.3, 2, implicit $eflags
22+
; CHECK-SDISEL: JMP_1 %bb.1
2423
; CHECK-SDISEL: bb.5 (%ir-block.1):
25-
; CHECK-SDISEL: ; predecessors: %bb.4
26-
; CHECK-SDISEL: successors: %bb.1(0x80000000), %bb.2(0x00000000); %bb.1(100.00%), %bb.2(0.00%)
27-
; CHECK-SDISEL: %5:gr32 = MOV32ri 48
28-
; CHECK-SDISEL: BT32rr killed %5:gr32, %3:gr32, implicit-def $eflags
29-
; CHECK-SDISEL: JCC_1 %bb.1, 2, implicit $eflags
30-
; CHECK-SDISEL: JMP_1 %bb.2
3124
; CHECK-SDISEL: bb.1.sw.epilog8:
32-
; CHECK-SDISEL: ; predecessors: %bb.5
25+
; CHECK-SDISEL: ; predecessors: %bb.4
3326
; CHECK-SDISEL: successors: %bb.3(0x80000000); %bb.3(100.00%)
34-
; CHECK-SDISEL: %6:gr32 = MOV32ri 1
27+
; CHECK-SDISEL: %5:gr32 = MOV32ri 1
3528
; CHECK-SDISEL: JMP_1 %bb.3
3629
; CHECK-SDISEL: bb.2.if.then.unreachabledefault:
37-
; CHECK-SDISEL: ; predecessors: %bb.5
3830
; CHECK-SDISEL: bb.3.return:
3931
; CHECK-SDISEL: ; predecessors: %bb.4, %bb.1
40-
; CHECK-SDISEL: %0:gr32 = PHI %2:gr32, %bb.4, %6:gr32, %bb.1
32+
; CHECK-SDISEL: %0:gr32 = PHI %2:gr32, %bb.4, %5:gr32, %bb.1
4133
; CHECK-SDISEL: $eax = COPY %0:gr32
4234
; CHECK-SDISEL: RET 0, $eax
4335

4436

45-
; FIXME: Get rid of this conditional jump and bit test in bb.6.
46-
; FIXME: bb.3 should not have bb.6 as a predecessor.
4737
; CHECK-GISEL: bb.1 (%ir-block.1):
4838
; CHECK-GISEL: successors: %bb.5(0x80000000); %bb.5(100.00%)
4939
; CHECK-GISEL: liveins: $edi
5040
; CHECK-GISEL: %0:gr32 = COPY $edi
51-
; CHECK-GISEL: %16:gr32 = MOV32ri 1
52-
; CHECK-GISEL: %17:gr32 = MOV32r0 implicit-def $eflags
41+
; CHECK-GISEL: %10:gr32 = MOV32ri 1
42+
; CHECK-GISEL: %11:gr32 = MOV32r0 implicit-def $eflags
5343
; CHECK-GISEL: %2:gr32 = SUB32ri8 %0:gr32(tied-def 0), 0, implicit-def $eflags
5444
; CHECK-GISEL: bb.5 (%ir-block.1):
5545
; CHECK-GISEL: ; predecessors: %bb.1
56-
; CHECK-GISEL: successors: %bb.4(0x55555555), %bb.6(0x2aaaaaab); %bb.4(66.67%), %bb.6(33.33%)
46+
; CHECK-GISEL: successors: %bb.4(0x55555555), %bb.2(0x2aaaaaab); %bb.4(66.67%), %bb.2(33.33%)
5747
; CHECK-GISEL: %3:gr32 = MOV32ri 1
58-
; CHECK-GISEL: %21:gr8 = COPY %2.sub_8bit:gr32
59-
; CHECK-GISEL: $cl = COPY %21:gr8
48+
; CHECK-GISEL: %13:gr8 = COPY %2.sub_8bit:gr32
49+
; CHECK-GISEL: $cl = COPY %13:gr8
6050
; CHECK-GISEL: %4:gr32 = SHL32rCL %3:gr32(tied-def 0), implicit-def $eflags, implicit $cl
6151
; CHECK-GISEL: %6:gr32 = AND32ri %4:gr32(tied-def 0), 13056, implicit-def $eflags
6252
; CHECK-GISEL: %7:gr32 = MOV32r0 implicit-def $eflags
6353
; CHECK-GISEL: CMP32rr %6:gr32, %7:gr32, implicit-def $eflags
64-
; CHECK-GISEL: %20:gr8 = SETCCr 5, implicit $eflags
65-
; CHECK-GISEL: TEST8ri %20:gr8, 1, implicit-def $eflags
54+
; CHECK-GISEL: %12:gr8 = SETCCr 5, implicit $eflags
55+
; CHECK-GISEL: TEST8ri %12:gr8, 1, implicit-def $eflags
6656
; CHECK-GISEL: JCC_1 %bb.4, 5, implicit $eflags
57+
; CHECK-GISEL: JMP_1 %bb.2
6758
; CHECK-GISEL: bb.6 (%ir-block.1):
68-
; CHECK-GISEL: ; predecessors: %bb.5
69-
; CHECK-GISEL: successors: %bb.2(0x80000000), %bb.3(0x00000000); %bb.2(100.00%), %bb.3(0.00%)
70-
; CHECK-GISEL: %9:gr32 = MOV32ri 1
71-
; CHECK-GISEL: %19:gr8 = COPY %2.sub_8bit:gr32
72-
; CHECK-GISEL: $cl = COPY %19:gr8
73-
; CHECK-GISEL: %10:gr32 = SHL32rCL %9:gr32(tied-def 0), implicit-def $eflags, implicit $cl
74-
; CHECK-GISEL: %12:gr32 = AND32ri8 %10:gr32(tied-def 0), 48, implicit-def $eflags
75-
; CHECK-GISEL: %13:gr32 = MOV32r0 implicit-def $eflags
76-
; CHECK-GISEL: CMP32rr %12:gr32, %13:gr32, implicit-def $eflags
77-
; CHECK-GISEL: %18:gr8 = SETCCr 5, implicit $eflags
78-
; CHECK-GISEL: TEST8ri %18:gr8, 1, implicit-def $eflags
79-
; CHECK-GISEL: JCC_1 %bb.2, 5, implicit $eflags
80-
; CHECK-GISEL: JMP_1 %bb.3
8159
; CHECK-GISEL: bb.2.sw.epilog8:
82-
; CHECK-GISEL: ; predecessors: %bb.6
60+
; CHECK-GISEL: ; predecessors: %bb.5
8361
; CHECK-GISEL: successors: %bb.4(0x80000000); %bb.4(100.00%)
8462
; CHECK-GISEL: JMP_1 %bb.4
8563
; CHECK-GISEL: bb.3.if.then.unreachabledefault:
86-
; CHECK-GISEL: ; predecessors: %bb.6
8764
; CHECK-GISEL: bb.4.return:
8865
; CHECK-GISEL: ; predecessors: %bb.5, %bb.2
89-
; CHECK-GISEL: %15:gr32 = PHI %16:gr32, %bb.2, %17:gr32, %bb.5
90-
; CHECK-GISEL: $eax = COPY %15:gr32
66+
; CHECK-GISEL: %9:gr32 = PHI %10:gr32, %bb.2, %11:gr32, %bb.5
67+
; CHECK-GISEL: $eax = COPY %9:gr32
9168
; CHECK-GISEL: RET 0, implicit $eax
9269

9370
switch i32 %0, label %if.then.unreachabledefault [

0 commit comments

Comments
 (0)