[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / test / Transforms / InstCombine / compare-unescaped.ll
bloba19f803968473b196d8ed4d6ac739fa03e0e0165
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -instcombine -S < %s | FileCheck %s
4 @gp = global i32* null, align 8
6 declare i8* @malloc(i64) #1
8 define i1 @compare_global_trivialeq() {
9 ; CHECK-LABEL: @compare_global_trivialeq(
10 ; CHECK-NEXT:    ret i1 false
12   %m = call i8* @malloc(i64 4)
13   %bc = bitcast i8* %m to i32*
14   %lgp = load i32*, i32** @gp, align 8
15   %cmp = icmp eq i32* %bc, %lgp
16   ret i1 %cmp
19 define i1 @compare_global_trivialne() {
20 ; CHECK-LABEL: @compare_global_trivialne(
21 ; CHECK-NEXT:    ret i1 true
23   %m = call i8* @malloc(i64 4)
24   %bc = bitcast i8* %m to i32*
25   %lgp = load i32*, i32** @gp, align 8
26   %cmp = icmp ne i32* %bc, %lgp
27   ret i1 %cmp
31 ; Although the %m is marked nocapture in the deopt operand in call to function f,
32 ; we cannot remove the alloc site: call to malloc
33 ; The comparison should fold to false irrespective of whether the call to malloc can be elided or not
34 declare void @f()
35 define i1 @compare_and_call_with_deopt() {
36 ; CHECK-LABEL: @compare_and_call_with_deopt(
37 ; CHECK-NEXT:    [[M:%.*]] = call dereferenceable_or_null(24) i8* @malloc(i64 24)
38 ; CHECK-NEXT:    tail call void @f() [ "deopt"(i8* [[M]]) ]
39 ; CHECK-NEXT:    ret i1 false
41   %m = call i8* @malloc(i64 24)
42   %bc = bitcast i8* %m to i32*
43   %lgp = load i32*, i32** @gp, align 8, !nonnull !0
44   %cmp = icmp eq i32* %lgp, %bc
45   tail call void @f() [ "deopt"(i8* %m) ]
46   ret i1 %cmp
49 ; Same functon as above with deopt operand in function f, but comparison is NE
50 define i1 @compare_ne_and_call_with_deopt() {
51 ; CHECK-LABEL: @compare_ne_and_call_with_deopt(
52 ; CHECK-NEXT:    [[M:%.*]] = call dereferenceable_or_null(24) i8* @malloc(i64 24)
53 ; CHECK-NEXT:    tail call void @f() [ "deopt"(i8* [[M]]) ]
54 ; CHECK-NEXT:    ret i1 true
56   %m = call i8* @malloc(i64 24)
57   %bc = bitcast i8* %m to i32*
58   %lgp = load i32*, i32** @gp, align 8, !nonnull !0
59   %cmp = icmp ne i32* %lgp, %bc
60   tail call void @f() [ "deopt"(i8* %m) ]
61   ret i1 %cmp
64 ; Same function as above, but global not marked nonnull, and we cannot fold the comparison
65 define i1 @compare_ne_global_maybe_null() {
66 ; CHECK-LABEL: @compare_ne_global_maybe_null(
67 ; CHECK-NEXT:    [[M:%.*]] = call dereferenceable_or_null(24) i8* @malloc(i64 24)
68 ; CHECK-NEXT:    [[BC:%.*]] = bitcast i8* [[M]] to i32*
69 ; CHECK-NEXT:    [[LGP:%.*]] = load i32*, i32** @gp, align 8
70 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32* [[LGP]], [[BC]]
71 ; CHECK-NEXT:    tail call void @f() [ "deopt"(i8* [[M]]) ]
72 ; CHECK-NEXT:    ret i1 [[CMP]]
74   %m = call i8* @malloc(i64 24)
75   %bc = bitcast i8* %m to i32*
76   %lgp = load i32*, i32** @gp
77   %cmp = icmp ne i32* %lgp, %bc
78   tail call void @f() [ "deopt"(i8* %m) ]
79   ret i1 %cmp
82 ; FIXME: The comparison should fold to false since %m escapes (call to function escape)
83 ; after the comparison.
84 declare void @escape(i8*)
85 define i1 @compare_and_call_after() {
86 ; CHECK-LABEL: @compare_and_call_after(
87 ; CHECK-NEXT:    [[M:%.*]] = call dereferenceable_or_null(24) i8* @malloc(i64 24)
88 ; CHECK-NEXT:    [[BC:%.*]] = bitcast i8* [[M]] to i32*
89 ; CHECK-NEXT:    [[LGP:%.*]] = load i32*, i32** @gp, align 8, !nonnull !0
90 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32* [[LGP]], [[BC]]
91 ; CHECK-NEXT:    br i1 [[CMP]], label [[ESCAPE_CALL:%.*]], label [[JUST_RETURN:%.*]]
92 ; CHECK:       escape_call:
93 ; CHECK-NEXT:    call void @escape(i8* [[M]])
94 ; CHECK-NEXT:    ret i1 true
95 ; CHECK:       just_return:
96 ; CHECK-NEXT:    ret i1 [[CMP]]
98   %m = call i8* @malloc(i64 24)
99   %bc = bitcast i8* %m to i32*
100   %lgp = load i32*, i32** @gp, align 8, !nonnull !0
101   %cmp = icmp eq i32* %bc, %lgp
102   br i1 %cmp, label %escape_call, label %just_return
104 escape_call:
105   call void @escape(i8* %m)
106   ret i1 true
108 just_return:
109   ret i1 %cmp
112 define i1 @compare_distinct_mallocs() {
113 ; CHECK-LABEL: @compare_distinct_mallocs(
114 ; CHECK-NEXT:    ret i1 false
116   %m = call i8* @malloc(i64 4)
117   %n = call i8* @malloc(i64 4)
118   %cmp = icmp eq i8* %m, %n
119   ret i1 %cmp
122 ; the compare is folded to true since the folding compare looks through bitcasts.
123 ; call to malloc and the bitcast instructions are elided after that since there are no uses of the malloc
124 define i1 @compare_samepointer_under_bitcast() {
125 ; CHECK-LABEL: @compare_samepointer_under_bitcast(
126 ; CHECK-NEXT:    ret i1 true
128   %m = call i8* @malloc(i64 4)
129   %bc = bitcast i8* %m to i32*
130   %bcback = bitcast i32* %bc to i8*
131   %cmp = icmp eq i8* %m, %bcback
132   ret i1 %cmp
135 ; the compare is folded to true since the folding compare looks through bitcasts.
136 ; The malloc call for %m cannot be elided since it is used in the call to function f.
137 define i1 @compare_samepointer_escaped() {
138 ; CHECK-LABEL: @compare_samepointer_escaped(
139 ; CHECK-NEXT:    [[M:%.*]] = call dereferenceable_or_null(4) i8* @malloc(i64 4)
140 ; CHECK-NEXT:    call void @f() [ "deopt"(i8* [[M]]) ]
141 ; CHECK-NEXT:    ret i1 true
143   %m = call i8* @malloc(i64 4)
144   %bc = bitcast i8* %m to i32*
145   %bcback = bitcast i32* %bc to i8*
146   %cmp = icmp eq i8* %m, %bcback
147   call void @f() [ "deopt"(i8* %m) ]
148   ret i1 %cmp
151 ; Technically, we can fold the %cmp2 comparison, even though %m escapes through
152 ; the ret statement since `ret` terminates the function and we cannot reach from
153 ; the ret to cmp.
154 ; FIXME: Folding this %cmp2 when %m escapes through ret could be an issue with
155 ; cross-threading data dependencies since we do not make the distinction between
156 ; atomic and non-atomic loads in capture tracking.
157 define i8* @compare_ret_escape(i8* %c) {
158 ; CHECK-LABEL: @compare_ret_escape(
159 ; CHECK-NEXT:    [[M:%.*]] = call dereferenceable_or_null(4) i8* @malloc(i64 4)
160 ; CHECK-NEXT:    [[N:%.*]] = call dereferenceable_or_null(4) i8* @malloc(i64 4)
161 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8* [[N]], [[C:%.*]]
162 ; CHECK-NEXT:    br i1 [[CMP]], label [[RETST:%.*]], label [[CHK:%.*]]
163 ; CHECK:       retst:
164 ; CHECK-NEXT:    ret i8* [[M]]
165 ; CHECK:       chk:
166 ; CHECK-NEXT:    [[BC:%.*]] = bitcast i8* [[M]] to i32*
167 ; CHECK-NEXT:    [[LGP:%.*]] = load i32*, i32** @gp, align 8, !nonnull !0
168 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i32* [[LGP]], [[BC]]
169 ; CHECK-NEXT:    br i1 [[CMP2]], label [[RETST]], label [[CHK2:%.*]]
170 ; CHECK:       chk2:
171 ; CHECK-NEXT:    ret i8* [[N]]
173   %m = call i8* @malloc(i64 4)
174   %n = call i8* @malloc(i64 4)
175   %cmp = icmp eq i8* %n, %c
176   br i1 %cmp, label %retst, label %chk
178 retst:
179   ret i8* %m
181 chk:
182   %bc = bitcast i8* %m to i32*
183   %lgp = load i32*, i32** @gp, align 8, !nonnull !0
184   %cmp2 = icmp eq i32* %bc, %lgp
185   br i1 %cmp2, label %retst,  label %chk2
187 chk2:
188   ret i8* %n
191 ; The malloc call for %m cannot be elided since it is used in the call to function f.
192 ; However, the cmp can be folded to true as %n doesnt escape and %m, %n are distinct allocations
193 define i1 @compare_distinct_pointer_escape() {
194 ; CHECK-LABEL: @compare_distinct_pointer_escape(
195 ; CHECK-NEXT:    [[M:%.*]] = call dereferenceable_or_null(4) i8* @malloc(i64 4)
196 ; CHECK-NEXT:    tail call void @f() [ "deopt"(i8* [[M]]) ]
197 ; CHECK-NEXT:    ret i1 true
199   %m = call i8* @malloc(i64 4)
200   %n = call i8* @malloc(i64 4)
201   tail call void @f() [ "deopt"(i8* %m) ]
202   %cmp = icmp ne i8* %m, %n
203   ret i1 %cmp
206 !0 = !{}