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 4 5target datalayout = "p:32:32-p1:32:32-p2:16:16" 6 7@global = global i8 0 8 9; This shouldn't convert to getelementptr because the relationship 10; between the arithmetic and the layout of allocated memory is 11; entirely unknown. 12 13define 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]] 19; 20 %tc = ptrtoint i8* %t to i32 21 %ta = add i32 %tc, 32 22 %tv = inttoptr i32 %ta to i8* 23 ret i8* %tv 24} 25 26; These casts should be folded away. 27 28define 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]] 32; 33 %ta = ptrtoint i8* %a to i32 34 %tb = ptrtoint i8* %b to i32 35 %r = icmp eq i32 %ta, %tb 36 ret i1 %r 37} 38 39; These casts should be folded away. 40 41define 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]] 45; 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 49 ret i1 %r 50} 51 52; These casts should be folded away. 53 54define 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]] 58; 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 62 ret i1 %r 63} 64 65; These casts should not be folded away. 66 67define 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]] 73; 74 %i0 = ptrtoint i8* %p to i32 75 %i1 = ptrtoint i8 addrspace(1)* %q to i32 76 %r0 = icmp sge i32 %i0, %i1 77 ret i1 %r0 78} 79 80; These casts should not be folded away. 81 82define 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]] 87; 88 %i0 = ptrtoint i8* @global to i32 89 %i1 = ptrtoint i8 addrspace(1)* %q to i32 90 %r0 = icmp sge i32 %i1, %i0 91 ret i1 %r0 92} 93 94; These casts should also be folded away. 95 96define i1 @test3(i8* %a) { 97; CHECK-LABEL: @test3( 98; CHECK-NEXT: [[R:%.*]] = icmp eq i8* [[A:%.*]], @global 99; CHECK-NEXT: ret i1 [[R]] 100; 101 %ta = ptrtoint i8* %a to i32 102 %r = icmp eq i32 %ta, ptrtoint (i8* @global to i32) 103 ret i1 %r 104} 105 106define i1 @test4(i32 %A) { 107; CHECK-LABEL: @test4( 108; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[A:%.*]], 0 109; CHECK-NEXT: ret i1 [[C]] 110; 111 %B = inttoptr i32 %A to i8* 112 %C = icmp eq i8* %B, null 113 ret i1 %C 114} 115 116define 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]] 120; 121 %B = inttoptr i16 %A to i8 addrspace(2)* 122 %C = icmp eq i8 addrspace(2)* %B, null 123 ret i1 %C 124} 125 126 127; Pulling the cast out of the load allows us to eliminate the load, and then 128; the whole array. 129 130 %op = type { float } 131 %unop = type { i32 } 132@Array = internal constant [1 x %op* (%op*)*] [ %op* (%op*)* @foo ] 133 134declare %op* @foo(%op* %X) 135 136define %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]] 141; 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 ) 144 ret %unop* %t.2 145} 146 147 148 149; InstCombine can not 'load (cast P)' -> cast (load P)' if the cast changes 150; the address space. 151 152define i8 @test6(i8 addrspace(1)* %source) { 153; CHECK-LABEL: @test6( 154; CHECK-NEXT: entry: 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]] 158; 159entry: 160 %arrayidx223 = addrspacecast i8 addrspace(1)* %source to i8* 161 %t4 = load i8, i8* %arrayidx223 162 ret i8 %t4 163} 164 165define <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]] 170; 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> 174 ret <2 x i32> %r 175} 176 177define <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]] 183; 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> 187 ret <2 x i32> %r 188} 189 190define <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]] 196; 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> 200 ret <2 x i32> %r 201} 202 203define <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]] 210; 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> 214 ret <2 x i64> %r 215} 216 217declare void @use(<2 x i32*>) 218 219define <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]] 226; 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> 231 ret <2 x i32> %r 232} 233 234define <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]] 241; 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> 246 ret <2 x i32> %r 247} 248