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 -passes=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 ptr @test1(ptr %t) { 14; CHECK-LABEL: @test1( 15; CHECK-NEXT: [[TC:%.*]] = ptrtoint ptr [[T:%.*]] to i32 16; CHECK-NEXT: [[TA:%.*]] = add i32 [[TC]], 32 17; CHECK-NEXT: [[TV:%.*]] = inttoptr i32 [[TA]] to ptr 18; CHECK-NEXT: ret ptr [[TV]] 19; 20 %tc = ptrtoint ptr %t to i32 21 %ta = add i32 %tc, 32 22 %tv = inttoptr i32 %ta to ptr 23 ret ptr %tv 24} 25 26; These casts should be folded away. 27 28define i1 @test2(ptr %a, ptr %b) { 29; CHECK-LABEL: @test2( 30; CHECK-NEXT: [[R:%.*]] = icmp eq ptr [[A:%.*]], [[B:%.*]] 31; CHECK-NEXT: ret i1 [[R]] 32; 33 %ta = ptrtoint ptr %a to i32 34 %tb = ptrtoint ptr %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(ptr addrspace(2) %a, ptr addrspace(2) %b) { 42; CHECK-LABEL: @test2_as2_same_int( 43; CHECK-NEXT: [[R:%.*]] = icmp eq ptr addrspace(2) [[A:%.*]], [[B:%.*]] 44; CHECK-NEXT: ret i1 [[R]] 45; 46 %ta = ptrtoint ptr addrspace(2) %a to i16 47 %tb = ptrtoint ptr 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(ptr addrspace(2) %a, ptr addrspace(2) %b) { 55; CHECK-LABEL: @test2_as2_larger( 56; CHECK-NEXT: [[R:%.*]] = icmp eq ptr addrspace(2) [[A:%.*]], [[B:%.*]] 57; CHECK-NEXT: ret i1 [[R]] 58; 59 %ta = ptrtoint ptr addrspace(2) %a to i32 60 %tb = ptrtoint ptr 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(ptr %p, ptr addrspace(1) %q) { 68; CHECK-LABEL: @test2_diff_as( 69; CHECK-NEXT: [[I0:%.*]] = ptrtoint ptr [[P:%.*]] to i32 70; CHECK-NEXT: [[I1:%.*]] = ptrtoint ptr addrspace(1) [[Q:%.*]] to i32 71; CHECK-NEXT: [[R0:%.*]] = icmp sge i32 [[I0]], [[I1]] 72; CHECK-NEXT: ret i1 [[R0]] 73; 74 %i0 = ptrtoint ptr %p to i32 75 %i1 = ptrtoint ptr 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(ptr addrspace(1) %q) { 83; CHECK-LABEL: @test2_diff_as_global( 84; CHECK-NEXT: [[I1:%.*]] = ptrtoint ptr addrspace(1) [[Q:%.*]] to i32 85; CHECK-NEXT: [[R0:%.*]] = icmp sge i32 [[I1]], ptrtoint (ptr @global to i32) 86; CHECK-NEXT: ret i1 [[R0]] 87; 88 %i0 = ptrtoint ptr @global to i32 89 %i1 = ptrtoint ptr 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(ptr %a) { 97; CHECK-LABEL: @test3( 98; CHECK-NEXT: [[R:%.*]] = icmp eq ptr [[A:%.*]], @global 99; CHECK-NEXT: ret i1 [[R]] 100; 101 %ta = ptrtoint ptr %a to i32 102 %r = icmp eq i32 %ta, ptrtoint (ptr @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 ptr 112 %C = icmp eq ptr %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 ptr addrspace(2) 122 %C = icmp eq ptr 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 ptr] [ ptr @foo ] 133 134declare ptr @foo(ptr %X) 135 136define ptr @test5(ptr %O) { 137; CHECK-LABEL: @test5( 138; CHECK-NEXT: [[T_2:%.*]] = call ptr @foo(ptr [[O:%.*]]) 139; CHECK-NEXT: ret ptr [[T_2]] 140; 141 %t = load ptr, ptr @Array; <ptr> [#uses=1] 142 %t.2 = call ptr %t( ptr %O ) 143 ret ptr %t.2 144} 145 146 147 148; InstCombine can not 'load (cast P)' -> cast (load P)' if the cast changes 149; the address space. 150 151define i8 @test6(ptr addrspace(1) %source) { 152; CHECK-LABEL: @test6( 153; CHECK-NEXT: entry: 154; CHECK-NEXT: [[ARRAYIDX223:%.*]] = addrspacecast ptr addrspace(1) [[SOURCE:%.*]] to ptr 155; CHECK-NEXT: [[T4:%.*]] = load i8, ptr [[ARRAYIDX223]], align 1 156; CHECK-NEXT: ret i8 [[T4]] 157; 158entry: 159 %arrayidx223 = addrspacecast ptr addrspace(1) %source to ptr 160 %t4 = load i8, ptr %arrayidx223 161 ret i8 %t4 162} 163 164define <2 x i32> @insertelt(<2 x i32> %x, ptr %p, i133 %index) { 165; CHECK-LABEL: @insertelt( 166; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[P:%.*]] to i32 167; CHECK-NEXT: [[R:%.*]] = insertelement <2 x i32> [[X:%.*]], i32 [[TMP1]], i133 [[INDEX:%.*]] 168; CHECK-NEXT: ret <2 x i32> [[R]] 169; 170 %v = inttoptr <2 x i32> %x to <2 x ptr> 171 %i = insertelement <2 x ptr> %v, ptr %p, i133 %index 172 %r = ptrtoint <2 x ptr> %i to <2 x i32> 173 ret <2 x i32> %r 174} 175 176define <2 x i32> @insertelt_intptr_trunc(<2 x i64> %x, ptr %p) { 177; CHECK-LABEL: @insertelt_intptr_trunc( 178; CHECK-NEXT: [[TMP1:%.*]] = trunc <2 x i64> [[X:%.*]] to <2 x i32> 179; CHECK-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[P:%.*]] to i32 180; CHECK-NEXT: [[R:%.*]] = insertelement <2 x i32> [[TMP1]], i32 [[TMP2]], i64 0 181; CHECK-NEXT: ret <2 x i32> [[R]] 182; 183 %v = inttoptr <2 x i64> %x to <2 x ptr> 184 %i = insertelement <2 x ptr> %v, ptr %p, i32 0 185 %r = ptrtoint <2 x ptr> %i to <2 x i32> 186 ret <2 x i32> %r 187} 188 189define <2 x i32> @insertelt_intptr_zext(<2 x i8> %x, ptr %p) { 190; CHECK-LABEL: @insertelt_intptr_zext( 191; CHECK-NEXT: [[TMP1:%.*]] = zext <2 x i8> [[X:%.*]] to <2 x i32> 192; CHECK-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[P:%.*]] to i32 193; CHECK-NEXT: [[R:%.*]] = insertelement <2 x i32> [[TMP1]], i32 [[TMP2]], i64 1 194; CHECK-NEXT: ret <2 x i32> [[R]] 195; 196 %v = inttoptr <2 x i8> %x to <2 x ptr> 197 %i = insertelement <2 x ptr> %v, ptr %p, i32 1 198 %r = ptrtoint <2 x ptr> %i to <2 x i32> 199 ret <2 x i32> %r 200} 201 202define <2 x i64> @insertelt_intptr_zext_zext(<2 x i8> %x, ptr %p) { 203; CHECK-LABEL: @insertelt_intptr_zext_zext( 204; CHECK-NEXT: [[TMP1:%.*]] = zext <2 x i8> [[X:%.*]] to <2 x i32> 205; CHECK-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[P:%.*]] to i32 206; CHECK-NEXT: [[TMP3:%.*]] = insertelement <2 x i32> [[TMP1]], i32 [[TMP2]], i64 0 207; CHECK-NEXT: [[R:%.*]] = zext <2 x i32> [[TMP3]] to <2 x i64> 208; CHECK-NEXT: ret <2 x i64> [[R]] 209; 210 %v = inttoptr <2 x i8> %x to <2 x ptr> 211 %i = insertelement <2 x ptr> %v, ptr %p, i32 0 212 %r = ptrtoint <2 x ptr> %i to <2 x i64> 213 ret <2 x i64> %r 214} 215 216declare void @use(<2 x ptr>) 217 218define <2 x i32> @insertelt_extra_use1(<2 x i32> %x, ptr %p) { 219; CHECK-LABEL: @insertelt_extra_use1( 220; CHECK-NEXT: [[V:%.*]] = inttoptr <2 x i32> [[X:%.*]] to <2 x ptr> 221; CHECK-NEXT: call void @use(<2 x ptr> [[V]]) 222; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[P:%.*]] to i32 223; CHECK-NEXT: [[R:%.*]] = insertelement <2 x i32> [[X]], i32 [[TMP1]], i64 0 224; CHECK-NEXT: ret <2 x i32> [[R]] 225; 226 %v = inttoptr <2 x i32> %x to <2 x ptr> 227 call void @use(<2 x ptr> %v) 228 %i = insertelement <2 x ptr> %v, ptr %p, i32 0 229 %r = ptrtoint <2 x ptr> %i to <2 x i32> 230 ret <2 x i32> %r 231} 232 233define <2 x i32> @insertelt_extra_use2(<2 x i32> %x, ptr %p) { 234; CHECK-LABEL: @insertelt_extra_use2( 235; CHECK-NEXT: [[V:%.*]] = inttoptr <2 x i32> [[X:%.*]] to <2 x ptr> 236; CHECK-NEXT: [[I:%.*]] = insertelement <2 x ptr> [[V]], ptr [[P:%.*]], i64 0 237; CHECK-NEXT: call void @use(<2 x ptr> [[I]]) 238; CHECK-NEXT: [[R:%.*]] = ptrtoint <2 x ptr> [[I]] to <2 x i32> 239; CHECK-NEXT: ret <2 x i32> [[R]] 240; 241 %v = inttoptr <2 x i32> %x to <2 x ptr> 242 %i = insertelement <2 x ptr> %v, ptr %p, i32 0 243 call void @use(<2 x ptr> %i) 244 %r = ptrtoint <2 x ptr> %i to <2 x i32> 245 ret <2 x i32> %r 246} 247 248define i32 @ptr_add_in_int(i32 %x, i32 %y) { 249; CHECK-LABEL: @ptr_add_in_int( 250; CHECK-NEXT: [[R:%.*]] = add i32 [[X:%.*]], [[Y:%.*]] 251; CHECK-NEXT: ret i32 [[R]] 252; 253 %ptr = inttoptr i32 %x to ptr 254 %p2 = getelementptr inbounds i8, ptr %ptr, i32 %y 255 %r = ptrtoint ptr %p2 to i32 256 ret i32 %r 257} 258 259define i32 @ptr_add_in_int_2(i32 %x, i32 %y) { 260; CHECK-LABEL: @ptr_add_in_int_2( 261; CHECK-NEXT: [[P2_IDX:%.*]] = shl nsw i32 [[Y:%.*]], 2 262; CHECK-NEXT: [[R:%.*]] = add i32 [[X:%.*]], [[P2_IDX]] 263; CHECK-NEXT: ret i32 [[R]] 264; 265 %ptr = inttoptr i32 %x to ptr 266 %p2 = getelementptr inbounds i32, ptr %ptr, i32 %y 267 %r = ptrtoint ptr %p2 to i32 268 ret i32 %r 269} 270 271define i32 @ptr_add_in_int_nneg(i32 %x, i32 %y) { 272; CHECK-LABEL: @ptr_add_in_int_nneg( 273; CHECK-NEXT: [[Z:%.*]] = call i32 @llvm.abs.i32(i32 [[Y:%.*]], i1 true) 274; CHECK-NEXT: [[R:%.*]] = add nuw i32 [[X:%.*]], [[Z]] 275; CHECK-NEXT: ret i32 [[R]] 276; 277 %z = call i32 @llvm.abs.i32(i32 %y, i1 true) 278 %ptr = inttoptr i32 %x to ptr 279 %p2 = getelementptr inbounds i8, ptr %ptr, i32 %z 280 %r = ptrtoint ptr %p2 to i32 281 ret i32 %r 282} 283 284define i64 @ptr_add_in_int_different_type_1(i32 %x, i32 %y) { 285; CHECK-LABEL: @ptr_add_in_int_different_type_1( 286; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[X:%.*]], [[Y:%.*]] 287; CHECK-NEXT: [[R:%.*]] = zext i32 [[TMP1]] to i64 288; CHECK-NEXT: ret i64 [[R]] 289; 290 %ptr = inttoptr i32 %x to ptr 291 %p2 = getelementptr i8, ptr %ptr, i32 %y 292 %r = ptrtoint ptr %p2 to i64 293 ret i64 %r 294} 295 296define i16 @ptr_add_in_int_different_type_2(i32 %x, i32 %y) { 297; CHECK-LABEL: @ptr_add_in_int_different_type_2( 298; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[X:%.*]], [[Y:%.*]] 299; CHECK-NEXT: [[R:%.*]] = trunc i32 [[TMP1]] to i16 300; CHECK-NEXT: ret i16 [[R]] 301; 302 %ptr = inttoptr i32 %x to ptr 303 %p2 = getelementptr i8, ptr %ptr, i32 %y 304 %r = ptrtoint ptr %p2 to i16 305 ret i16 %r 306} 307 308define i32 @ptr_add_in_int_different_type_3(i16 %x, i32 %y) { 309; CHECK-LABEL: @ptr_add_in_int_different_type_3( 310; CHECK-NEXT: [[TMP1:%.*]] = zext i16 [[X:%.*]] to i32 311; CHECK-NEXT: [[R:%.*]] = add i32 [[Y:%.*]], [[TMP1]] 312; CHECK-NEXT: ret i32 [[R]] 313; 314 %ptr = inttoptr i16 %x to ptr 315 %p2 = getelementptr i8, ptr %ptr, i32 %y 316 %r = ptrtoint ptr %p2 to i32 317 ret i32 %r 318} 319 320define i32 @ptr_add_in_int_different_type_4(i64 %x, i32 %y) { 321; CHECK-LABEL: @ptr_add_in_int_different_type_4( 322; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[X:%.*]] to i32 323; CHECK-NEXT: [[R:%.*]] = add i32 [[Y:%.*]], [[TMP1]] 324; CHECK-NEXT: ret i32 [[R]] 325; 326 %ptr = inttoptr i64 %x to ptr 327 %p2 = getelementptr i8, ptr %ptr, i32 %y 328 %r = ptrtoint ptr %p2 to i32 329 ret i32 %r 330} 331 332define i32 @ptr_add_in_int_not_inbounds(i32 %x, i32 %y) { 333; CHECK-LABEL: @ptr_add_in_int_not_inbounds( 334; CHECK-NEXT: [[Z:%.*]] = call i32 @llvm.abs.i32(i32 [[Y:%.*]], i1 true) 335; CHECK-NEXT: [[R:%.*]] = add i32 [[X:%.*]], [[Z]] 336; CHECK-NEXT: ret i32 [[R]] 337; 338 %z = call i32 @llvm.abs.i32(i32 %y, i1 true) 339 %ptr = inttoptr i32 %x to ptr 340 %p2 = getelementptr i8, ptr %ptr, i32 %z 341 %r = ptrtoint ptr %p2 to i32 342 ret i32 %r 343} 344 345define i32 @ptr_add_in_int_nuw(i32 %x, i32 %y) { 346; CHECK-LABEL: @ptr_add_in_int_nuw( 347; CHECK-NEXT: [[R:%.*]] = add nuw i32 [[X:%.*]], [[Y:%.*]] 348; CHECK-NEXT: ret i32 [[R]] 349; 350 %ptr = inttoptr i32 %x to ptr 351 %p2 = getelementptr nuw i8, ptr %ptr, i32 %y 352 %r = ptrtoint ptr %p2 to i32 353 ret i32 %r 354} 355 356define i32 @ptr_add_in_int_nusw(i32 %x, i32 %y) { 357; CHECK-LABEL: @ptr_add_in_int_nusw( 358; CHECK-NEXT: [[R:%.*]] = add i32 [[X:%.*]], [[Y:%.*]] 359; CHECK-NEXT: ret i32 [[R]] 360; 361 %ptr = inttoptr i32 %x to ptr 362 %p2 = getelementptr nusw i8, ptr %ptr, i32 %y 363 %r = ptrtoint ptr %p2 to i32 364 ret i32 %r 365} 366 367define i32 @ptr_add_in_int_nusw_nneg(i32 %x, i32 %y) { 368; CHECK-LABEL: @ptr_add_in_int_nusw_nneg( 369; CHECK-NEXT: [[NNEG:%.*]] = icmp sgt i32 [[Y:%.*]], -1 370; CHECK-NEXT: call void @llvm.assume(i1 [[NNEG]]) 371; CHECK-NEXT: [[R:%.*]] = add nuw i32 [[X:%.*]], [[Y]] 372; CHECK-NEXT: ret i32 [[R]] 373; 374 %nneg = icmp sge i32 %y, 0 375 call void @llvm.assume(i1 %nneg) 376 %ptr = inttoptr i32 %x to ptr 377 %p2 = getelementptr nusw i8, ptr %ptr, i32 %y 378 %r = ptrtoint ptr %p2 to i32 379 ret i32 %r 380} 381 382define i32 @ptr_add_in_int_const(i32 %x) { 383; CHECK-LABEL: @ptr_add_in_int_const( 384; CHECK-NEXT: [[R:%.*]] = add nuw i32 [[X:%.*]], 4096 385; CHECK-NEXT: ret i32 [[R]] 386; 387 %ptr = inttoptr i32 %x to ptr 388 %p2 = getelementptr inbounds i8, ptr %ptr, i32 4096 389 %r = ptrtoint ptr %p2 to i32 390 ret i32 %r 391} 392 393define i32 @ptr_add_in_int_const_negative(i32 %x) { 394; CHECK-LABEL: @ptr_add_in_int_const_negative( 395; CHECK-NEXT: [[R:%.*]] = add i32 [[X:%.*]], -4096 396; CHECK-NEXT: ret i32 [[R]] 397; 398 %ptr = inttoptr i32 %x to ptr 399 %p2 = getelementptr inbounds i8, ptr %ptr, i32 -4096 400 %r = ptrtoint ptr %p2 to i32 401 ret i32 %r 402} 403 404declare void @use_ptr(ptr) 405 406define i32 @ptr_add_in_int_extra_use1(i32 %x) { 407; CHECK-LABEL: @ptr_add_in_int_extra_use1( 408; CHECK-NEXT: [[PTR:%.*]] = inttoptr i32 [[X:%.*]] to ptr 409; CHECK-NEXT: call void @use_ptr(ptr [[PTR]]) 410; CHECK-NEXT: [[P2:%.*]] = getelementptr inbounds nuw i8, ptr [[PTR]], i32 4096 411; CHECK-NEXT: [[R:%.*]] = ptrtoint ptr [[P2]] to i32 412; CHECK-NEXT: ret i32 [[R]] 413; 414 %ptr = inttoptr i32 %x to ptr 415 call void @use_ptr(ptr %ptr) 416 %p2 = getelementptr inbounds i8, ptr %ptr, i32 4096 417 %r = ptrtoint ptr %p2 to i32 418 ret i32 %r 419} 420 421define i32 @ptr_add_in_int_extra_use2(i32 %x) { 422; CHECK-LABEL: @ptr_add_in_int_extra_use2( 423; CHECK-NEXT: [[PTR:%.*]] = inttoptr i32 [[X:%.*]] to ptr 424; CHECK-NEXT: [[P2:%.*]] = getelementptr inbounds nuw i8, ptr [[PTR]], i32 4096 425; CHECK-NEXT: call void @use_ptr(ptr nonnull [[P2]]) 426; CHECK-NEXT: [[R:%.*]] = ptrtoint ptr [[P2]] to i32 427; CHECK-NEXT: ret i32 [[R]] 428; 429 %ptr = inttoptr i32 %x to ptr 430 %p2 = getelementptr inbounds i8, ptr %ptr, i32 4096 431 call void @use_ptr(ptr %p2) 432 %r = ptrtoint ptr %p2 to i32 433 ret i32 %r 434} 435