Skip to content

Commit c4bb584

Browse files
author
Frank Tetzel
committed
[CGP] Do not eliminate blocks which have their address taken
When eliminating a block, codegenprepare updates all blockaddress expressions which reference the block. In case the blockaddress is located in a different function, it leads to updates across function boundaries, which is problematic for a function pass like codegenprepare. If blockaddress is in a function defined before the current one, the update to the blockaddress is lost. This change adds a check to avoid eliminations of any block which has its address taken. Fixes: #161164
1 parent 50d65a5 commit c4bb584

File tree

3 files changed

+112
-0
lines changed

3 files changed

+112
-0
lines changed

llvm/lib/CodeGen/CodeGenPrepare.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -954,6 +954,12 @@ bool CodeGenPrepare::eliminateMostlyEmptyBlocks(Function &F) {
954954
bool CodeGenPrepare::isMergingEmptyBlockProfitable(BasicBlock *BB,
955955
BasicBlock *DestBB,
956956
bool isPreheader) {
957+
// Do not eliminate blocks which have their address taken.
958+
// This could lead to updates across functions which is problematic in a
959+
// function pass like codegenprepare. The update to a blockaddress in a
960+
// function defined before the function with the eliminated block is lost.
961+
if(BB->hasAddressTaken()) return false;
962+
957963
// Do not delete loop preheaders if doing so would create a critical edge.
958964
// Loop preheaders can be good locations to spill registers. If the
959965
// preheader is deleted and we create a critical edge, registers may be
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
; RUN: llc <%s | FileCheck %s
2+
target triple = "x86_64-unknown-linux-gnu"
3+
4+
; CHECK: .Ltmp0: # Address of block that was removed by CodeGen
5+
; CHECK-NEXT: .Ltmp1: # Address of block that was removed by CodeGen
6+
7+
define i64 @main(ptr %p, i1 %c1) {
8+
first:
9+
br label %loop_head
10+
11+
loop_head: ; preds = %loop_end, %first
12+
br i1 %c1, label %scope0, label %scope1
13+
14+
scope1: ; preds = %loop_head
15+
br i1 %c1, label %scope1_exit, label %scope2
16+
17+
scope2: ; preds = %scope1
18+
br i1 %c1, label %scope2_exit, label %inner
19+
20+
inner: ; preds = %scope2
21+
br label %scope2_exit
22+
23+
scope2_exit: ; preds = %inner, %scope2
24+
%phi2 = phi ptr [ %p, %inner ], [ null, %scope2 ]
25+
br label %scope1_exit
26+
27+
scope1_exit: ; preds = %scope2_exit, %scope1
28+
%phi1 = phi ptr [ %phi2, %scope2_exit ], [ null, %scope1 ]
29+
%val1 = load i128, ptr %phi1, align 16
30+
br label %loop_end
31+
32+
scope0: ; preds = %loop_head
33+
%ptr0 = select i1 %c1, ptr null, ptr %p
34+
%val0 = load i128, ptr %ptr0, align 16
35+
br label %loop_end
36+
37+
loop_end: ; preds = %scope0, %scope1_exit
38+
%storemerge = phi i128 [ %val1, %scope1_exit ], [ %val0, %scope0 ]
39+
store i128 %storemerge, ptr %p, align 16
40+
br label %loop_head
41+
}
42+
43+
define void @foo0(ptr %jumpAddr) {
44+
; CHECK: movq $.Ltmp0, (%rdi)
45+
store ptr blockaddress(@main, %scope2_exit), ptr %jumpAddr, align 8
46+
ret void
47+
}
48+
49+
define void @foo1(ptr %jumpAddr) {
50+
; CHECK: movq $.Ltmp1, (%rdi)
51+
store ptr blockaddress(@main, %scope1_exit), ptr %jumpAddr, align 8
52+
ret void
53+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
; RUN: llc <%s | FileCheck %s
2+
target triple = "x86_64-unknown-linux-gnu"
3+
4+
define void @foo0(ptr %jumpAddr) {
5+
; CHECK: movq $.Ltmp0, (%rdi)
6+
store ptr blockaddress(@main, %scope2_exit), ptr %jumpAddr, align 8
7+
ret void
8+
}
9+
10+
define void @foo1(ptr %jumpAddr) {
11+
; CHECK: movq $.Ltmp1, (%rdi)
12+
store ptr blockaddress(@main, %scope1_exit), ptr %jumpAddr, align 8
13+
ret void
14+
}
15+
16+
; CHECK: .Ltmp0: # Address of block that was removed by CodeGen
17+
; CHECK-NEXT: .Ltmp1: # Address of block that was removed by CodeGen
18+
19+
define i64 @main(ptr %p, i1 %c1) {
20+
first:
21+
br label %loop_head
22+
23+
loop_head: ; preds = %loop_end, %first
24+
br i1 %c1, label %scope0, label %scope1
25+
26+
scope1: ; preds = %loop_head
27+
br i1 %c1, label %scope1_exit, label %scope2
28+
29+
scope2: ; preds = %scope1
30+
br i1 %c1, label %scope2_exit, label %inner
31+
32+
inner: ; preds = %scope2
33+
br label %scope2_exit
34+
35+
scope2_exit: ; preds = %inner, %scope2
36+
%phi2 = phi ptr [ %p, %inner ], [ null, %scope2 ]
37+
br label %scope1_exit
38+
39+
scope1_exit: ; preds = %scope2_exit, %scope1
40+
%phi1 = phi ptr [ %phi2, %scope2_exit ], [ null, %scope1 ]
41+
%val1 = load i128, ptr %phi1, align 16
42+
br label %loop_end
43+
44+
scope0: ; preds = %loop_head
45+
%ptr0 = select i1 %c1, ptr null, ptr %p
46+
%val0 = load i128, ptr %ptr0, align 16
47+
br label %loop_end
48+
49+
loop_end: ; preds = %scope0, %scope1_exit
50+
%storemerge = phi i128 [ %val1, %scope1_exit ], [ %val0, %scope0 ]
51+
store i128 %storemerge, ptr %p, align 16
52+
br label %loop_head
53+
}

0 commit comments

Comments
 (0)