1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes=instcombine -S < %s | FileCheck %s 3 4target datalayout = "e-m:e-p:64:64:64-i64:64-f80:128-n8:16:32:64-S128-ni:1" 5 6@X = constant i32 42 ; <ptr> [#uses=2] 7@X2 = constant i32 47 ; <ptr> [#uses=1] 8@Y = constant [2 x { i32, float }] [ { i32, float } { i32 12, float 1.000000e+00 }, { i32, float } { i32 37, float 0x3FF3B2FEC0000000 } ] ; <ptr> [#uses=2] 9@Z = constant [2 x { i32, float }] zeroinitializer ; <ptr> [#uses=1] 10 11@GLOBAL = internal constant [4 x i32] zeroinitializer 12 13 14define i32 @test1() { 15; CHECK-LABEL: @test1( 16; CHECK-NEXT: ret i32 42 17; 18 %B = load i32, ptr @X ; <i32> [#uses=1] 19 ret i32 %B 20} 21 22define float @test2() { 23; CHECK-LABEL: @test2( 24; CHECK-NEXT: ret float 0x3FF3B2FEC0000000 25; 26 %A = getelementptr [2 x { i32, float }], ptr @Y, i64 0, i64 1, i32 1 ; <ptr> [#uses=1] 27 %B = load float, ptr %A ; <float> [#uses=1] 28 ret float %B 29} 30 31define i32 @test3() { 32; CHECK-LABEL: @test3( 33; CHECK-NEXT: ret i32 12 34; 35 %A = getelementptr [2 x { i32, float }], ptr @Y, i64 0, i64 0, i32 0 ; <ptr> [#uses=1] 36 %B = load i32, ptr %A ; <i32> [#uses=1] 37 ret i32 %B 38} 39 40define i32 @test4() { 41; CHECK-LABEL: @test4( 42; CHECK-NEXT: ret i32 0 43; 44 %A = getelementptr [2 x { i32, float }], ptr @Z, i64 0, i64 1, i32 0 ; <ptr> [#uses=1] 45 %B = load i32, ptr %A ; <i32> [#uses=1] 46 ret i32 %B 47} 48 49define i32 @test5(i1 %C) { 50; CHECK-LABEL: @test5( 51; CHECK-NEXT: [[Z:%.*]] = select i1 [[C:%.*]], i32 42, i32 47 52; CHECK-NEXT: ret i32 [[Z]] 53; 54 %Y = select i1 %C, ptr @X, ptr @X2 ; <ptr> [#uses=1] 55 %Z = load i32, ptr %Y ; <i32> [#uses=1] 56 ret i32 %Z 57} 58 59; FIXME: Constants should be allowed for this optimization. 60define i32 @test5_asan(i1 %C) sanitize_address { 61; CHECK-LABEL: @test5_asan( 62; CHECK-NEXT: [[Y:%.*]] = select i1 [[C:%.*]], ptr @X, ptr @X2 63; CHECK-NEXT: [[Z:%.*]] = load i32, ptr [[Y]], align 4 64; CHECK-NEXT: ret i32 [[Z]] 65; 66 %Y = select i1 %C, ptr @X, ptr @X2 ; <ptr> [#uses=1] 67 %Z = load i32, ptr %Y ; <i32> [#uses=1] 68 ret i32 %Z 69} 70 71define i32 @load_gep_null_inbounds(i64 %X) { 72; CHECK-LABEL: @load_gep_null_inbounds( 73; CHECK-NEXT: store i1 true, ptr poison, align 1 74; CHECK-NEXT: ret i32 poison 75; 76 %V = getelementptr inbounds i32, ptr null, i64 %X 77 %R = load i32, ptr %V 78 ret i32 %R 79} 80 81define i32 @load_gep_null_not_inbounds(i64 %X) { 82; CHECK-LABEL: @load_gep_null_not_inbounds( 83; CHECK-NEXT: store i1 true, ptr poison, align 1 84; CHECK-NEXT: ret i32 poison 85; 86 %V = getelementptr i32, ptr null, i64 %X 87 %R = load i32, ptr %V 88 ret i32 %R 89} 90 91define i32 @test7_no_null_opt(i32 %X) #0 { 92; CHECK-LABEL: @test7_no_null_opt( 93; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[X:%.*]] to i64 94; CHECK-NEXT: [[V:%.*]] = getelementptr i32, ptr null, i64 [[TMP1]] 95; CHECK-NEXT: [[R:%.*]] = load i32, ptr [[V]], align 4 96; CHECK-NEXT: ret i32 [[R]] 97; 98 %V = getelementptr i32, ptr null, i32 %X ; <ptr> [#uses=1] 99 %R = load i32, ptr %V ; <i32> [#uses=1] 100 ret i32 %R 101} 102attributes #0 = { null_pointer_is_valid } 103 104define i32 @test8(ptr %P) { 105; CHECK-LABEL: @test8( 106; CHECK-NEXT: store i32 1, ptr [[P:%.*]], align 4 107; CHECK-NEXT: ret i32 1 108; 109 store i32 1, ptr %P 110 %X = load i32, ptr %P ; <i32> [#uses=1] 111 ret i32 %X 112} 113 114define i32 @test9(ptr %P) { 115; CHECK-LABEL: @test9( 116; CHECK-NEXT: ret i32 0 117; 118 %X = load i32, ptr %P ; <i32> [#uses=1] 119 %Y = load i32, ptr %P ; <i32> [#uses=1] 120 %Z = sub i32 %X, %Y ; <i32> [#uses=1] 121 ret i32 %Z 122} 123 124define i32 @test10(i1 %C.upgrd.1, ptr %P, ptr %Q) { 125; CHECK-LABEL: @test10( 126; CHECK-NEXT: br i1 [[C_UPGRD_1:%.*]], label [[T:%.*]], label [[F:%.*]] 127; CHECK: T: 128; CHECK-NEXT: store i32 1, ptr [[Q:%.*]], align 4 129; CHECK-NEXT: br label [[C:%.*]] 130; CHECK: F: 131; CHECK-NEXT: br label [[C]] 132; CHECK: C: 133; CHECK-NEXT: store i32 0, ptr [[P:%.*]], align 4 134; CHECK-NEXT: ret i32 0 135; 136 br i1 %C.upgrd.1, label %T, label %F 137T: ; preds = %0 138 store i32 1, ptr %Q 139 store i32 0, ptr %P 140 br label %C 141F: ; preds = %0 142 store i32 0, ptr %P 143 br label %C 144C: ; preds = %F, %T 145 %V = load i32, ptr %P ; <i32> [#uses=1] 146 ret i32 %V 147} 148 149define double @test11(ptr %p) { 150; CHECK-LABEL: @test11( 151; CHECK-NEXT: [[T0:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 8 152; CHECK-NEXT: store double 2.000000e+00, ptr [[T0]], align 8 153; CHECK-NEXT: ret double 2.000000e+00 154; 155 %t0 = getelementptr double, ptr %p, i32 1 156 store double 2.0, ptr %t0 157 %t1 = getelementptr double, ptr %p, i32 1 158 %x = load double, ptr %t1 159 ret double %x 160} 161 162define i32 @test12(ptr %P) { 163; CHECK-LABEL: @test12( 164; CHECK-NEXT: ret i32 123 165; 166 %A = alloca i32 167 store i32 123, ptr %A 168 ; Cast the result of the load not the source 169 %V = load i32, ptr %A 170 ret i32 %V 171} 172 173define <16 x i8> @test13(<2 x i64> %x) { 174; CHECK-LABEL: @test13( 175; CHECK-NEXT: ret <16 x i8> zeroinitializer 176; 177 %tmp = load <16 x i8>, ptr @GLOBAL 178 ret <16 x i8> %tmp 179} 180 181; This test must not have the store of %x forwarded to the load -- there is an 182; intervening store if %y. However, the intervening store occurs with a different 183; type and size and to a different pointer value. This is ensuring that none of 184; those confuse the analysis into thinking that the second store does not alias 185; the first. 186 187define i8 @test14(i8 %x, i32 %y) { 188; CHECK-LABEL: @test14( 189; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 190; CHECK-NEXT: store i8 [[X:%.*]], ptr [[A]], align 1 191; CHECK-NEXT: store i32 [[Y:%.*]], ptr [[A]], align 4 192; CHECK-NEXT: [[R:%.*]] = load i8, ptr [[A]], align 1 193; CHECK-NEXT: ret i8 [[R]] 194; 195 %a = alloca i32 196 store i8 %x, ptr %a 197 store i32 %y, ptr %a 198 %r = load i8, ptr %a 199 ret i8 %r 200} 201 202@test15_global = external global i32 203 204; Same test as @test14 essentially, but using a global instead of an alloca. 205 206define i8 @test15(i8 %x, i32 %y) { 207; CHECK-LABEL: @test15( 208; CHECK-NEXT: store i8 [[X:%.*]], ptr @test15_global, align 1 209; CHECK-NEXT: store i32 [[Y:%.*]], ptr @test15_global, align 4 210; CHECK-NEXT: [[R:%.*]] = load i8, ptr @test15_global, align 1 211; CHECK-NEXT: ret i8 [[R]] 212; 213 store i8 %x, ptr @test15_global 214 store i32 %y, ptr @test15_global 215 %r = load i8, ptr @test15_global 216 ret i8 %r 217} 218 219; Check that we canonicalize loads which are only stored to use integer types 220; when there is a valid integer type. 221 222define void @test16(ptr %x, ptr %a, ptr %b, ptr %c) { 223; CHECK-LABEL: @test16( 224; CHECK-NEXT: entry: 225; CHECK-NEXT: [[X1:%.*]] = load float, ptr [[X:%.*]], align 4 226; CHECK-NEXT: store float [[X1]], ptr [[A:%.*]], align 4 227; CHECK-NEXT: store float [[X1]], ptr [[B:%.*]], align 4 228; CHECK-NEXT: [[X2:%.*]] = load float, ptr [[X]], align 4 229; CHECK-NEXT: store float [[X2]], ptr [[B]], align 4 230; CHECK-NEXT: store float [[X2]], ptr [[C:%.*]], align 4 231; CHECK-NEXT: ret void 232; 233entry: 234 235 %x1 = load float, ptr %x 236 store float %x1, ptr %a 237 store float %x1, ptr %b 238 239 %x2 = load float, ptr %x 240 store float %x2, ptr %b 241 %x2.cast = bitcast float %x2 to i32 242 store i32 %x2.cast, ptr %c 243 244 ret void 245} 246 247define void @test16-vect(ptr %x, ptr %a, ptr %b, ptr %c) { 248; CHECK-LABEL: @test16-vect( 249; CHECK-NEXT: entry: 250; CHECK-NEXT: [[X1:%.*]] = load <4 x i8>, ptr [[X:%.*]], align 4 251; CHECK-NEXT: store <4 x i8> [[X1]], ptr [[A:%.*]], align 4 252; CHECK-NEXT: store <4 x i8> [[X1]], ptr [[B:%.*]], align 4 253; CHECK-NEXT: [[X2:%.*]] = load <4 x i8>, ptr [[X]], align 4 254; CHECK-NEXT: store <4 x i8> [[X2]], ptr [[B]], align 4 255; CHECK-NEXT: store <4 x i8> [[X2]], ptr [[C:%.*]], align 4 256; CHECK-NEXT: ret void 257; 258entry: 259 260 %x1 = load <4 x i8>, ptr %x 261 store <4 x i8> %x1, ptr %a 262 store <4 x i8> %x1, ptr %b 263 264 %x2 = load <4 x i8>, ptr %x 265 store <4 x i8> %x2, ptr %b 266 %x2.cast = bitcast <4 x i8> %x2 to i32 267 store i32 %x2.cast, ptr %c 268 269 ret void 270} 271 272 273; Check that in cases similar to @test16 we don't try to rewrite a load when 274; its only use is a store but it is used as the pointer to that store rather 275; than the value. 276 277define void @test17(ptr %x, i8 %y) { 278; CHECK-LABEL: @test17( 279; CHECK-NEXT: entry: 280; CHECK-NEXT: [[X_LOAD:%.*]] = load ptr, ptr [[X:%.*]], align 8 281; CHECK-NEXT: store i8 [[Y:%.*]], ptr [[X_LOAD]], align 1 282; CHECK-NEXT: ret void 283; 284entry: 285 %x.load = load ptr, ptr %x 286 store i8 %y, ptr %x.load 287 288 ret void 289} 290 291; Check that we don't try change the type of the load by inserting a bitcast 292; generating invalid IR. 293%swift.error = type opaque 294declare void @useSwiftError(ptr swifterror) 295 296define void @test18(ptr swifterror %err) { 297; CHECK-LABEL: @test18( 298; CHECK-NEXT: entry: 299; CHECK-NEXT: [[SWIFTERROR:%.*]] = alloca swifterror ptr, align 8 300; CHECK-NEXT: store ptr null, ptr [[SWIFTERROR]], align 8 301; CHECK-NEXT: call void @useSwiftError(ptr nonnull swifterror [[SWIFTERROR]]) 302; CHECK-NEXT: [[ERR_RES:%.*]] = load ptr, ptr [[SWIFTERROR]], align 8 303; CHECK-NEXT: store ptr [[ERR_RES]], ptr [[ERR:%.*]], align 8 304; CHECK-NEXT: ret void 305; 306entry: 307 %swifterror = alloca swifterror ptr, align 8 308 store ptr null, ptr %swifterror, align 8 309 call void @useSwiftError(ptr nonnull swifterror %swifterror) 310 %err.res = load ptr, ptr %swifterror, align 8 311 store ptr %err.res, ptr %err, align 8 312 ret void 313} 314 315; Make sure we preseve the type of the store to a swifterror pointer. 316 317declare void @initi8(ptr) 318define void @test19(ptr swifterror %err) { 319; CHECK-LABEL: @test19( 320; CHECK-NEXT: entry: 321; CHECK-NEXT: [[TMP:%.*]] = alloca ptr, align 8 322; CHECK-NEXT: call void @initi8(ptr nonnull [[TMP]]) 323; CHECK-NEXT: [[ERR_RES:%.*]] = load ptr, ptr [[TMP]], align 8 324; CHECK-NEXT: store ptr [[ERR_RES]], ptr [[ERR:%.*]], align 8 325; CHECK-NEXT: ret void 326; 327entry: 328 %tmp = alloca ptr, align 8 329 call void @initi8(ptr %tmp) 330 %err.res = load ptr, ptr %tmp, align 8 331 store ptr %err.res, ptr %err, align 8 332 ret void 333} 334 335; Make sure we don't canonicalize accesses to scalable vectors. 336define void @test20(ptr %x, ptr %y) { 337; CHECK-LABEL: @test20( 338; CHECK-NEXT: [[X_LOAD:%.*]] = load <vscale x 4 x i8>, ptr [[X:%.*]], align 1 339; CHECK-NEXT: store <vscale x 4 x i8> [[X_LOAD]], ptr [[Y:%.*]], align 1 340; CHECK-NEXT: ret void 341; 342 %x.load = load <vscale x 4 x i8>, ptr %x, align 1 343 store <vscale x 4 x i8> %x.load, ptr %y, align 1 344 ret void 345} 346 347 348; Check that non-integral pointers are not coverted using inttoptr 349 350declare void @use(ptr) 351declare void @use.p1(ptr addrspace(1)) 352 353define i64 @test21(ptr %P) { 354; CHECK-LABEL: @test21( 355; CHECK-NEXT: [[X:%.*]] = load i64, ptr [[P:%.*]], align 8 356; CHECK-NEXT: [[Y_CAST:%.*]] = inttoptr i64 [[X]] to ptr 357; CHECK-NEXT: call void @use(ptr [[Y_CAST]]) 358; CHECK-NEXT: ret i64 [[X]] 359; 360 %X = load i64, ptr %P 361 %Y = load ptr, ptr %P 362 call void @use(ptr %Y) 363 ret i64 %X 364} 365 366define i64 @test22(ptr %P) { 367; CHECK-LABEL: @test22( 368; CHECK-NEXT: [[X:%.*]] = load i64, ptr [[P:%.*]], align 8 369; CHECK-NEXT: [[Y:%.*]] = load ptr addrspace(1), ptr [[P]], align 8 370; CHECK-NEXT: call void @use.p1(ptr addrspace(1) [[Y]]) 371; CHECK-NEXT: ret i64 [[X]] 372; 373 %X = load i64, ptr %P 374 %Y = load ptr addrspace(1), ptr %P 375 call void @use.p1(ptr addrspace(1) %Y) 376 ret i64 %X 377} 378 379declare void @use.v2.p0(<2 x ptr>) 380declare void @use.v2.p1(<2 x ptr addrspace(1)>) 381 382define <2 x i64> @test23(ptr %P) { 383; CHECK-LABEL: @test23( 384; CHECK-NEXT: [[X:%.*]] = load <2 x i64>, ptr [[P:%.*]], align 16 385; CHECK-NEXT: [[Y:%.*]] = load <2 x ptr>, ptr [[P]], align 16 386; CHECK-NEXT: call void @use.v2.p0(<2 x ptr> [[Y]]) 387; CHECK-NEXT: ret <2 x i64> [[X]] 388; 389 %X = load <2 x i64>, ptr %P 390 %Y = load <2 x ptr>, ptr %P 391 call void @use.v2.p0(<2 x ptr> %Y) 392 ret <2 x i64> %X 393} 394 395define <2 x i64> @test24(ptr %P) { 396; CHECK-LABEL: @test24( 397; CHECK-NEXT: [[X:%.*]] = load <2 x i64>, ptr [[P:%.*]], align 16 398; CHECK-NEXT: [[Y:%.*]] = load <2 x ptr addrspace(1)>, ptr [[P]], align 16 399; CHECK-NEXT: call void @use.v2.p1(<2 x ptr addrspace(1)> [[Y]]) 400; CHECK-NEXT: ret <2 x i64> [[X]] 401; 402 %X = load <2 x i64>, ptr %P 403 %Y = load <2 x ptr addrspace(1)>, ptr %P 404 call void @use.v2.p1(<2 x ptr addrspace(1)> %Y) 405 ret <2 x i64> %X 406} 407 408define i16 @load_from_zero_with_dynamic_offset(i64 %idx) { 409; CHECK-LABEL: @load_from_zero_with_dynamic_offset( 410; CHECK-NEXT: ret i16 0 411; 412 %gep = getelementptr i16, ptr @GLOBAL, i64 %idx 413 %v = load i16, ptr %gep 414 ret i16 %v 415} 416 417declare ptr @llvm.strip.invariant.group.p0(ptr %p) 418 419define i32 @load_via_strip_invariant_group() { 420; CHECK-LABEL: @load_via_strip_invariant_group( 421; CHECK-NEXT: ret i32 37 422; 423 %a = call ptr @llvm.strip.invariant.group.p0(ptr @Y) 424 %b = getelementptr i8, ptr %a, i64 8 425 %d = load i32, ptr %b 426 ret i32 %d 427} 428 429; TODO: For non-byte-sized vectors, current implementation assumes there is 430; padding to the next byte boundary between elements. 431@foo = constant <2 x i4> <i4 u0x1, i4 u0x2>, align 8 432 433define i4 @test_vector_load_i4_non_byte_sized() { 434; CHECK-LABEL: @test_vector_load_i4_non_byte_sized( 435; CHECK-NEXT: [[RES0:%.*]] = load i4, ptr @foo, align 1 436; CHECK-NEXT: ret i4 [[RES0]] 437; 438 %ptr0 = getelementptr i8, ptr @foo, i64 0 439 %res0 = load i4, ptr %ptr0, align 1 440 ret i4 %res0 441} 442