1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; Tests to make sure elimination of casts is working correctly
3 ; RUN: opt < %s -instcombine -S | FileCheck %s
5 target datalayout = "p:32:32-p1:32:32-p2:16:16"
9 ; This shouldn't convert to getelementptr because the relationship
10 ; between the arithmetic and the layout of allocated memory is
13 define i8* @test1(i8* %t) {
14 ; CHECK-LABEL: @test1(
15 ; CHECK-NEXT: [[TC:%.*]] = ptrtoint i8* [[T:%.*]] to i32
16 ; CHECK-NEXT: [[TA:%.*]] = add i32 [[TC]], 32
17 ; CHECK-NEXT: [[TV:%.*]] = inttoptr i32 [[TA]] to i8*
18 ; CHECK-NEXT: ret i8* [[TV]]
20 %tc = ptrtoint i8* %t to i32
22 %tv = inttoptr i32 %ta to i8*
26 ; These casts should be folded away.
28 define i1 @test2(i8* %a, i8* %b) {
29 ; CHECK-LABEL: @test2(
30 ; CHECK-NEXT: [[R:%.*]] = icmp eq i8* [[A:%.*]], [[B:%.*]]
31 ; CHECK-NEXT: ret i1 [[R]]
33 %ta = ptrtoint i8* %a to i32
34 %tb = ptrtoint i8* %b to i32
35 %r = icmp eq i32 %ta, %tb
39 ; These casts should be folded away.
41 define i1 @test2_as2_same_int(i8 addrspace(2)* %a, i8 addrspace(2)* %b) {
42 ; CHECK-LABEL: @test2_as2_same_int(
43 ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 addrspace(2)* [[A:%.*]], [[B:%.*]]
44 ; CHECK-NEXT: ret i1 [[R]]
46 %ta = ptrtoint i8 addrspace(2)* %a to i16
47 %tb = ptrtoint i8 addrspace(2)* %b to i16
48 %r = icmp eq i16 %ta, %tb
52 ; These casts should be folded away.
54 define i1 @test2_as2_larger(i8 addrspace(2)* %a, i8 addrspace(2)* %b) {
55 ; CHECK-LABEL: @test2_as2_larger(
56 ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 addrspace(2)* [[A:%.*]], [[B:%.*]]
57 ; CHECK-NEXT: ret i1 [[R]]
59 %ta = ptrtoint i8 addrspace(2)* %a to i32
60 %tb = ptrtoint i8 addrspace(2)* %b to i32
61 %r = icmp eq i32 %ta, %tb
65 ; These casts should not be folded away.
67 define i1 @test2_diff_as(i8* %p, i8 addrspace(1)* %q) {
68 ; CHECK-LABEL: @test2_diff_as(
69 ; CHECK-NEXT: [[I0:%.*]] = ptrtoint i8* [[P:%.*]] to i32
70 ; CHECK-NEXT: [[I1:%.*]] = ptrtoint i8 addrspace(1)* [[Q:%.*]] to i32
71 ; CHECK-NEXT: [[R0:%.*]] = icmp sge i32 [[I0]], [[I1]]
72 ; CHECK-NEXT: ret i1 [[R0]]
74 %i0 = ptrtoint i8* %p to i32
75 %i1 = ptrtoint i8 addrspace(1)* %q to i32
76 %r0 = icmp sge i32 %i0, %i1
80 ; These casts should not be folded away.
82 define i1 @test2_diff_as_global(i8 addrspace(1)* %q) {
83 ; CHECK-LABEL: @test2_diff_as_global(
84 ; CHECK-NEXT: [[I1:%.*]] = ptrtoint i8 addrspace(1)* [[Q:%.*]] to i32
85 ; CHECK-NEXT: [[R0:%.*]] = icmp sge i32 [[I1]], ptrtoint (i8* @global to i32)
86 ; CHECK-NEXT: ret i1 [[R0]]
88 %i0 = ptrtoint i8* @global to i32
89 %i1 = ptrtoint i8 addrspace(1)* %q to i32
90 %r0 = icmp sge i32 %i1, %i0
94 ; These casts should also be folded away.
96 define i1 @test3(i8* %a) {
97 ; CHECK-LABEL: @test3(
98 ; CHECK-NEXT: [[R:%.*]] = icmp eq i8* [[A:%.*]], @global
99 ; CHECK-NEXT: ret i1 [[R]]
101 %ta = ptrtoint i8* %a to i32
102 %r = icmp eq i32 %ta, ptrtoint (i8* @global to i32)
106 define i1 @test4(i32 %A) {
107 ; CHECK-LABEL: @test4(
108 ; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[A:%.*]], 0
109 ; CHECK-NEXT: ret i1 [[C]]
111 %B = inttoptr i32 %A to i8*
112 %C = icmp eq i8* %B, null
116 define i1 @test4_as2(i16 %A) {
117 ; CHECK-LABEL: @test4_as2(
118 ; CHECK-NEXT: [[C:%.*]] = icmp eq i16 [[A:%.*]], 0
119 ; CHECK-NEXT: ret i1 [[C]]
121 %B = inttoptr i16 %A to i8 addrspace(2)*
122 %C = icmp eq i8 addrspace(2)* %B, null
127 ; Pulling the cast out of the load allows us to eliminate the load, and then
132 @Array = internal constant [1 x %op* (%op*)*] [ %op* (%op*)* @foo ]
134 declare %op* @foo(%op* %X)
136 define %unop* @test5(%op* %O) {
137 ; CHECK-LABEL: @test5(
138 ; CHECK-NEXT: [[T_2:%.*]] = call %op* @foo(%op* [[O:%.*]])
139 ; CHECK-NEXT: [[TMP1:%.*]] = bitcast %op* [[T_2]] to %unop*
140 ; CHECK-NEXT: ret %unop* [[TMP1]]
142 %t = load %unop* (%op*)*, %unop* (%op*)** bitcast ([1 x %op* (%op*)*]* @Array to %unop* (%op*)**); <%unop* (%op*)*> [#uses=1]
143 %t.2 = call %unop* %t( %op* %O )
149 ; InstCombine can not 'load (cast P)' -> cast (load P)' if the cast changes
152 define i8 @test6(i8 addrspace(1)* %source) {
153 ; CHECK-LABEL: @test6(
155 ; CHECK-NEXT: [[ARRAYIDX223:%.*]] = addrspacecast i8 addrspace(1)* [[SOURCE:%.*]] to i8*
156 ; CHECK-NEXT: [[T4:%.*]] = load i8, i8* [[ARRAYIDX223]], align 1
157 ; CHECK-NEXT: ret i8 [[T4]]
160 %arrayidx223 = addrspacecast i8 addrspace(1)* %source to i8*
161 %t4 = load i8, i8* %arrayidx223
165 define <2 x i32> @insertelt(<2 x i32> %x, i32* %p, i133 %index) {
166 ; CHECK-LABEL: @insertelt(
167 ; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint i32* [[P:%.*]] to i32
168 ; CHECK-NEXT: [[R:%.*]] = insertelement <2 x i32> [[X:%.*]], i32 [[TMP1]], i133 [[INDEX:%.*]]
169 ; CHECK-NEXT: ret <2 x i32> [[R]]
171 %v = inttoptr <2 x i32> %x to <2 x i32*>
172 %i = insertelement <2 x i32*> %v, i32* %p, i133 %index
173 %r = ptrtoint <2 x i32*> %i to <2 x i32>
177 define <2 x i32> @insertelt_intptr_trunc(<2 x i64> %x, i32* %p) {
178 ; CHECK-LABEL: @insertelt_intptr_trunc(
179 ; CHECK-NEXT: [[TMP1:%.*]] = trunc <2 x i64> [[X:%.*]] to <2 x i32>
180 ; CHECK-NEXT: [[TMP2:%.*]] = ptrtoint i32* [[P:%.*]] to i32
181 ; CHECK-NEXT: [[R:%.*]] = insertelement <2 x i32> [[TMP1]], i32 [[TMP2]], i32 0
182 ; CHECK-NEXT: ret <2 x i32> [[R]]
184 %v = inttoptr <2 x i64> %x to <2 x i32*>
185 %i = insertelement <2 x i32*> %v, i32* %p, i32 0
186 %r = ptrtoint <2 x i32*> %i to <2 x i32>
190 define <2 x i32> @insertelt_intptr_zext(<2 x i8> %x, i32* %p) {
191 ; CHECK-LABEL: @insertelt_intptr_zext(
192 ; CHECK-NEXT: [[TMP1:%.*]] = zext <2 x i8> [[X:%.*]] to <2 x i32>
193 ; CHECK-NEXT: [[TMP2:%.*]] = ptrtoint i32* [[P:%.*]] to i32
194 ; CHECK-NEXT: [[R:%.*]] = insertelement <2 x i32> [[TMP1]], i32 [[TMP2]], i32 1
195 ; CHECK-NEXT: ret <2 x i32> [[R]]
197 %v = inttoptr <2 x i8> %x to <2 x i32*>
198 %i = insertelement <2 x i32*> %v, i32* %p, i32 1
199 %r = ptrtoint <2 x i32*> %i to <2 x i32>
203 define <2 x i64> @insertelt_intptr_zext_zext(<2 x i8> %x, i32* %p) {
204 ; CHECK-LABEL: @insertelt_intptr_zext_zext(
205 ; CHECK-NEXT: [[TMP1:%.*]] = zext <2 x i8> [[X:%.*]] to <2 x i32>
206 ; CHECK-NEXT: [[TMP2:%.*]] = ptrtoint i32* [[P:%.*]] to i32
207 ; CHECK-NEXT: [[TMP3:%.*]] = insertelement <2 x i32> [[TMP1]], i32 [[TMP2]], i32 0
208 ; CHECK-NEXT: [[R:%.*]] = zext <2 x i32> [[TMP3]] to <2 x i64>
209 ; CHECK-NEXT: ret <2 x i64> [[R]]
211 %v = inttoptr <2 x i8> %x to <2 x i32*>
212 %i = insertelement <2 x i32*> %v, i32* %p, i32 0
213 %r = ptrtoint <2 x i32*> %i to <2 x i64>
217 declare void @use(<2 x i32*>)
219 define <2 x i32> @insertelt_extra_use1(<2 x i32> %x, i32* %p) {
220 ; CHECK-LABEL: @insertelt_extra_use1(
221 ; CHECK-NEXT: [[V:%.*]] = inttoptr <2 x i32> [[X:%.*]] to <2 x i32*>
222 ; CHECK-NEXT: call void @use(<2 x i32*> [[V]])
223 ; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint i32* [[P:%.*]] to i32
224 ; CHECK-NEXT: [[R:%.*]] = insertelement <2 x i32> [[X]], i32 [[TMP1]], i32 0
225 ; CHECK-NEXT: ret <2 x i32> [[R]]
227 %v = inttoptr <2 x i32> %x to <2 x i32*>
228 call void @use(<2 x i32*> %v)
229 %i = insertelement <2 x i32*> %v, i32* %p, i32 0
230 %r = ptrtoint <2 x i32*> %i to <2 x i32>
234 define <2 x i32> @insertelt_extra_use2(<2 x i32> %x, i32* %p) {
235 ; CHECK-LABEL: @insertelt_extra_use2(
236 ; CHECK-NEXT: [[V:%.*]] = inttoptr <2 x i32> [[X:%.*]] to <2 x i32*>
237 ; CHECK-NEXT: [[I:%.*]] = insertelement <2 x i32*> [[V]], i32* [[P:%.*]], i32 0
238 ; CHECK-NEXT: call void @use(<2 x i32*> [[I]])
239 ; CHECK-NEXT: [[R:%.*]] = ptrtoint <2 x i32*> [[I]] to <2 x i32>
240 ; CHECK-NEXT: ret <2 x i32> [[R]]
242 %v = inttoptr <2 x i32> %x to <2 x i32*>
243 %i = insertelement <2 x i32*> %v, i32* %p, i32 0
244 call void @use(<2 x i32*> %i)
245 %r = ptrtoint <2 x i32*> %i to <2 x i32>