Skip to content

Commit a916794

Browse files
committed
add alloca exception
1 parent 6ff890f commit a916794

File tree

2 files changed

+65
-1
lines changed

2 files changed

+65
-1
lines changed

llvm/lib/Analysis/BasicAliasAnalysis.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -950,9 +950,11 @@ ModRefInfo BasicAAResult::getModRefInfo(const CallBase *Call,
950950
//
951951
// We model calls that can return twice (setjmp) as clobbering non-escaping
952952
// objects, to model any accesses that may occur prior to the second return.
953+
// As an exception, ignore allocas, as setjmp is not required to preserve
954+
// non-volatile stores for them.
953955
if (!isa<Constant>(Object) && Call != Object &&
954956
AAQI.CA->isNotCapturedBefore(Object, Call, /*OrAt*/ false) &&
955-
!Call->hasFnAttr(Attribute::ReturnsTwice)) {
957+
(isa<AllocaInst>(Object) || !Call->hasFnAttr(Attribute::ReturnsTwice))) {
956958

957959
// Optimistically assume that call doesn't touch Object and check this
958960
// assumption in the following loop.

llvm/test/Transforms/GVN/setjmp.ll

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,65 @@ if.end:
3535
%res = load i32, ptr %malloc
3636
ret i32 %res
3737
}
38+
39+
; We are still allowed to optimize non-volatile accesses to allocas.
40+
define i32 @test_alloca() {
41+
; CHECK-LABEL: define i32 @test_alloca() {
42+
; CHECK-NEXT: [[ALLOC:%.*]] = alloca i43, align 8
43+
; CHECK-NEXT: store i32 10, ptr [[ALLOC]], align 4
44+
; CHECK-NEXT: [[SJ:%.*]] = call i32 @setjmp()
45+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[SJ]], 0
46+
; CHECK-NEXT: br i1 [[CMP]], label %[[IF_THEN:.*]], label %[[IF_END:.*]]
47+
; CHECK: [[IF_THEN]]:
48+
; CHECK-NEXT: store i32 20, ptr [[ALLOC]], align 4
49+
; CHECK-NEXT: call void @longjmp()
50+
; CHECK-NEXT: unreachable
51+
; CHECK: [[IF_END]]:
52+
; CHECK-NEXT: ret i32 10
53+
;
54+
%alloc = alloca i43
55+
store i32 10, ptr %alloc, align 4
56+
%sj = call i32 @setjmp()
57+
%cmp = icmp eq i32 %sj, 0
58+
br i1 %cmp, label %if.then, label %if.end
59+
60+
if.then:
61+
store i32 20, ptr %alloc
62+
call void @longjmp()
63+
unreachable
64+
65+
if.end:
66+
%res = load i32, ptr %alloc
67+
ret i32 %res
68+
}
69+
70+
define i32 @test_alloca_volatile() {
71+
; CHECK-LABEL: define i32 @test_alloca_volatile() {
72+
; CHECK-NEXT: [[ALLOC:%.*]] = alloca i43, align 8
73+
; CHECK-NEXT: store volatile i32 10, ptr [[ALLOC]], align 4
74+
; CHECK-NEXT: [[SJ:%.*]] = call i32 @setjmp()
75+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[SJ]], 0
76+
; CHECK-NEXT: br i1 [[CMP]], label %[[IF_THEN:.*]], label %[[IF_END:.*]]
77+
; CHECK: [[IF_THEN]]:
78+
; CHECK-NEXT: store volatile i32 20, ptr [[ALLOC]], align 4
79+
; CHECK-NEXT: call void @longjmp()
80+
; CHECK-NEXT: unreachable
81+
; CHECK: [[IF_END]]:
82+
; CHECK-NEXT: [[RES:%.*]] = load volatile i32, ptr [[ALLOC]], align 4
83+
; CHECK-NEXT: ret i32 [[RES]]
84+
;
85+
%alloc = alloca i43
86+
store volatile i32 10, ptr %alloc, align 4
87+
%sj = call i32 @setjmp()
88+
%cmp = icmp eq i32 %sj, 0
89+
br i1 %cmp, label %if.then, label %if.end
90+
91+
if.then:
92+
store volatile i32 20, ptr %alloc
93+
call void @longjmp()
94+
unreachable
95+
96+
if.end:
97+
%res = load volatile i32, ptr %alloc
98+
ret i32 %res
99+
}

0 commit comments

Comments
 (0)