1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4target datalayout = "e-p:64:64-p1:16:16-p2:32:32:32-p3:64:64:64-f16:32" 5 6%intstruct = type { i32 } 7%pair = type { i32, i32 } 8%struct.B = type { double } 9%struct.A = type { %struct.B, i32, i32 } 10%struct.C = type { [7 x i8] } 11 12 13@Global = external global [10 x i8] 14@Global_as1 = external addrspace(1) global [10 x i8] 15 16declare void @use(ptr) 17declare void @use.i64(i64) 18 19; Test noop elimination 20define ptr @test1(ptr %I) { 21; CHECK-LABEL: @test1( 22; CHECK-NEXT: ret ptr [[I:%.*]] 23; 24 ret ptr %I 25} 26 27define ptr addrspace(1) @test1_as1(ptr addrspace(1) %I) { 28; CHECK-LABEL: @test1_as1( 29; CHECK-NEXT: ret ptr addrspace(1) [[I:%.*]] 30; 31 ret ptr addrspace(1) %I 32} 33 34; Test noop elimination 35define ptr @test2(ptr %I) { 36; CHECK-LABEL: @test2( 37; CHECK-NEXT: ret ptr [[I:%.*]] 38; 39 %A = getelementptr i32, ptr %I 40 ret ptr %A 41} 42 43; Test that two array indexing geps fold 44define ptr @test3(ptr %I) { 45; CHECK-LABEL: @test3( 46; CHECK-NEXT: [[B:%.*]] = getelementptr i8, ptr [[I:%.*]], i64 84 47; CHECK-NEXT: ret ptr [[B]] 48; 49 %A = getelementptr i32, ptr %I, i64 17 50 %B = getelementptr i32, ptr %A, i64 4 51 ret ptr %B 52} 53 54; Test that two getelementptr insts fold 55define ptr @test4(ptr %I) { 56; CHECK-LABEL: @test4( 57; CHECK-NEXT: [[A:%.*]] = getelementptr i8, ptr [[I:%.*]], i64 4 58; CHECK-NEXT: ret ptr [[A]] 59; 60 %A = getelementptr { i32 }, ptr %I, i64 1 61 ret ptr %A 62} 63 64define void @test5(i8 %B) { 65 ; This should be turned into a constexpr instead of being an instruction 66; CHECK-LABEL: @test5( 67; CHECK-NEXT: store i8 [[B:%.*]], ptr getelementptr inbounds nuw (i8, ptr @Global, i64 4), align 1 68; CHECK-NEXT: ret void 69; 70 %A = getelementptr [10 x i8], ptr @Global, i64 0, i64 4 71 store i8 %B, ptr %A 72 ret void 73} 74 75define void @test5_as1(i8 %B) { 76 ; This should be turned into a constexpr instead of being an instruction 77; CHECK-LABEL: @test5_as1( 78; CHECK-NEXT: store i8 [[B:%.*]], ptr addrspace(1) getelementptr inbounds nuw (i8, ptr addrspace(1) @Global_as1, i16 4), align 1 79; CHECK-NEXT: ret void 80; 81 %A = getelementptr [10 x i8], ptr addrspace(1) @Global_as1, i16 0, i16 4 82 store i8 %B, ptr addrspace(1) %A 83 ret void 84} 85 86%as1_ptr_struct = type { ptr addrspace(1) } 87%as2_ptr_struct = type { ptr addrspace(2) } 88 89@global_as2 = addrspace(2) global i32 zeroinitializer 90@global_as1_as2_ptr = addrspace(1) global %as2_ptr_struct { ptr addrspace(2) @global_as2 } 91 92; This should be turned into a constexpr instead of being an instruction 93define void @test_evaluate_gep_nested_as_ptrs(ptr addrspace(2) %B) { 94; CHECK-LABEL: @test_evaluate_gep_nested_as_ptrs( 95; CHECK-NEXT: store ptr addrspace(2) [[B:%.*]], ptr addrspace(1) @global_as1_as2_ptr, align 4 96; CHECK-NEXT: ret void 97; 98 store ptr addrspace(2) %B, ptr addrspace(1) @global_as1_as2_ptr 99 ret void 100} 101 102@arst = addrspace(1) global [4 x ptr addrspace(2)] zeroinitializer 103 104define void @test_evaluate_gep_as_ptrs_array(ptr addrspace(2) %B) { 105; CHECK-LABEL: @test_evaluate_gep_as_ptrs_array( 106; CHECK-NEXT: store ptr addrspace(2) [[B:%.*]], ptr addrspace(1) getelementptr inbounds nuw (i8, ptr addrspace(1) @arst, i16 8), align 4 107; CHECK-NEXT: ret void 108; 109 110 %A = getelementptr [4 x ptr addrspace(2)], ptr addrspace(1) @arst, i16 0, i16 2 111 store ptr addrspace(2) %B, ptr addrspace(1) %A 112 ret void 113} 114 115; This should be turned into a constexpr instead of being an instruction 116define void @test_overaligned_vec(i8 %B) { 117; CHECK-LABEL: @test_overaligned_vec( 118; CHECK-NEXT: store i8 [[B:%.*]], ptr getelementptr inbounds nuw (i8, ptr @Global, i64 2), align 1 119; CHECK-NEXT: ret void 120; 121 %A = getelementptr <2 x half>, ptr @Global, i64 0, i64 1 122 store i8 %B, ptr %A 123 ret void 124} 125 126define ptr @test7(ptr %I, i64 %C, i64 %D) { 127; CHECK-LABEL: @test7( 128; CHECK-NEXT: [[A:%.*]] = getelementptr i32, ptr [[I:%.*]], i64 [[C:%.*]] 129; CHECK-NEXT: [[B:%.*]] = getelementptr i32, ptr [[A]], i64 [[D:%.*]] 130; CHECK-NEXT: ret ptr [[B]] 131; 132 %A = getelementptr i32, ptr %I, i64 %C 133 %B = getelementptr i32, ptr %A, i64 %D 134 ret ptr %B 135} 136 137define ptr @test8(ptr %X) { 138 ;; Fold into the cast. 139; CHECK-LABEL: @test8( 140; CHECK-NEXT: ret ptr [[X:%.*]] 141; 142 ret ptr %X 143} 144 145define i32 @test9() { 146; CHECK-LABEL: @test9( 147; CHECK-NEXT: ret i32 8 148; 149 %A = getelementptr { i32, double }, ptr null, i32 0, i32 1 150 %B = ptrtoint ptr %A to i32 151 ret i32 %B 152} 153 154define i1 @test10(ptr %x, ptr %y) { 155; CHECK-LABEL: @test10( 156; CHECK-NEXT: [[T4:%.*]] = icmp eq ptr [[X:%.*]], [[Y:%.*]] 157; CHECK-NEXT: ret i1 [[T4]] 158; 159 %t1 = getelementptr { i32, i32 }, ptr %x, i32 0, i32 1 160 %t3 = getelementptr { i32, i32 }, ptr %y, i32 0, i32 1 161 %t4 = icmp eq ptr %t1, %t3 162 ret i1 %t4 163} 164 165define i1 @test10_addrspacecast(ptr %x, ptr addrspace(3) %y) { 166; CHECK-LABEL: @test10_addrspacecast( 167; CHECK-NEXT: [[T1:%.*]] = getelementptr i8, ptr [[X:%.*]], i64 4 168; CHECK-NEXT: [[T3:%.*]] = getelementptr i8, ptr addrspace(3) [[Y:%.*]], i64 4 169; CHECK-NEXT: [[T3_C:%.*]] = addrspacecast ptr addrspace(3) [[T3]] to ptr 170; CHECK-NEXT: [[T4:%.*]] = icmp eq ptr [[T1]], [[T3_C]] 171; CHECK-NEXT: ret i1 [[T4]] 172; 173 %t1 = getelementptr { i32, i32 }, ptr %x, i32 0, i32 1 174 %t3 = getelementptr { i32, i32 }, ptr addrspace(3) %y, i32 0, i32 1 175 %t3.c = addrspacecast ptr addrspace(3) %t3 to ptr 176 %t4 = icmp eq ptr %t1, %t3.c 177 ret i1 %t4 178} 179 180define i1 @test11(ptr %X) { 181; CHECK-LABEL: @test11( 182; CHECK-NEXT: [[Q:%.*]] = icmp eq ptr [[X:%.*]], null 183; CHECK-NEXT: ret i1 [[Q]] 184; 185 %P = getelementptr { i32, i32 }, ptr %X, i32 0, i32 0 186 %Q = icmp eq ptr %P, null 187 ret i1 %Q 188} 189 190 191; PR4748 192define i32 @test12(ptr %a) { 193; CHECK-LABEL: @test12( 194; CHECK-NEXT: entry: 195; CHECK-NEXT: [[G3:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 8 196; CHECK-NEXT: store i32 10, ptr [[G3]], align 4 197; CHECK-NEXT: ret i32 10 198; 199entry: 200 %g3 = getelementptr %struct.A, ptr %a, i32 0, i32 1 201 store i32 10, ptr %g3, align 4 202 203 204 205 %g5 = getelementptr %struct.A, ptr %a, i32 0, i32 1 206 %a_a = load i32, ptr %g5, align 4 207 ret i32 %a_a 208} 209 210 211; PR2235 212%S = type { i32, [ 100 x i32] } 213define i1 @test13(i64 %X, ptr %P) { 214; CHECK-LABEL: @test13( 215; CHECK-NEXT: [[C:%.*]] = icmp eq i64 [[X:%.*]], -1 216; CHECK-NEXT: ret i1 [[C]] 217; 218 %A = getelementptr inbounds %S, ptr %P, i32 0, i32 1, i64 %X 219 %C = icmp eq ptr %A, %P 220 ret i1 %C 221} 222 223define <2 x i1> @test13_vector(<2 x i64> %X, <2 x ptr> %P) nounwind { 224; CHECK-LABEL: @test13_vector( 225; CHECK-NEXT: [[C:%.*]] = icmp eq <2 x i64> [[X:%.*]], splat (i64 -1) 226; CHECK-NEXT: ret <2 x i1> [[C]] 227; 228 %A = getelementptr inbounds %S, <2 x ptr> %P, <2 x i64> zeroinitializer, <2 x i32> <i32 1, i32 1>, <2 x i64> %X 229 %B = getelementptr inbounds %S, <2 x ptr> %P, <2 x i64> <i64 0, i64 0>, <2 x i32> <i32 0, i32 0> 230 %C = icmp eq <2 x ptr> %A, %B 231 ret <2 x i1> %C 232} 233 234define <2 x i1> @test13_vector2(i64 %X, <2 x ptr> %P) nounwind { 235; CHECK-LABEL: @test13_vector2( 236; CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <2 x i64> poison, i64 [[X:%.*]], i64 0 237; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i64> [[DOTSPLATINSERT]], <i64 2, i64 0> 238; CHECK-NEXT: [[TMP2:%.*]] = icmp eq <2 x i64> [[TMP1]], <i64 -4, i64 poison> 239; CHECK-NEXT: [[C:%.*]] = shufflevector <2 x i1> [[TMP2]], <2 x i1> poison, <2 x i32> zeroinitializer 240; CHECK-NEXT: ret <2 x i1> [[C]] 241; 242 %A = getelementptr inbounds %S, <2 x ptr> %P, <2 x i64> zeroinitializer, <2 x i32> <i32 1, i32 1>, i64 %X 243 %B = getelementptr inbounds %S, <2 x ptr> %P, <2 x i64> <i64 0, i64 0>, <2 x i32> <i32 0, i32 0> 244 %C = icmp eq <2 x ptr> %A, %B 245 ret <2 x i1> %C 246} 247 248define <2 x i1> @test13_fixed_fixed(i64 %X, ptr %P, <2 x i64> %y) nounwind { 249; CHECK-LABEL: @test13_fixed_fixed( 250; CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <2 x i64> poison, i64 [[X:%.*]], i64 0 251; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i64> [[DOTSPLATINSERT]], <i64 3, i64 0> 252; CHECK-NEXT: [[A_IDX:%.*]] = shufflevector <2 x i64> [[TMP1]], <2 x i64> poison, <2 x i32> zeroinitializer 253; CHECK-NEXT: [[B_IDX:%.*]] = shl nsw <2 x i64> [[Y:%.*]], splat (i64 4) 254; CHECK-NEXT: [[C:%.*]] = icmp eq <2 x i64> [[A_IDX]], [[B_IDX]] 255; CHECK-NEXT: ret <2 x i1> [[C]] 256; 257 %A = getelementptr inbounds <2 x i64>, ptr %P, <2 x i64> zeroinitializer, i64 %X 258 %B = getelementptr inbounds <2 x i64>, ptr %P, <2 x i64> %y 259 %C = icmp eq <2 x ptr> %A, %B 260 ret <2 x i1> %C 261} 262 263define <2 x i1> @test13_fixed_scalable(i64 %X, ptr %P, <2 x i64> %y) nounwind { 264; CHECK-LABEL: @test13_fixed_scalable( 265; CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <2 x i64> poison, i64 [[X:%.*]], i64 0 266; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i64> [[DOTSPLATINSERT]], <i64 3, i64 0> 267; CHECK-NEXT: [[A_IDX:%.*]] = shufflevector <2 x i64> [[TMP1]], <2 x i64> poison, <2 x i32> zeroinitializer 268; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.vscale.i64() 269; CHECK-NEXT: [[TMP3:%.*]] = shl i64 [[TMP2]], 4 270; CHECK-NEXT: [[DOTSPLATINSERT1:%.*]] = insertelement <2 x i64> poison, i64 [[TMP3]], i64 0 271; CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <2 x i64> [[DOTSPLATINSERT1]], <2 x i64> poison, <2 x i32> zeroinitializer 272; CHECK-NEXT: [[B_IDX:%.*]] = mul nsw <2 x i64> [[Y:%.*]], [[DOTSPLAT]] 273; CHECK-NEXT: [[C:%.*]] = icmp eq <2 x i64> [[A_IDX]], [[B_IDX]] 274; CHECK-NEXT: ret <2 x i1> [[C]] 275; 276 %A = getelementptr inbounds <vscale x 2 x i64>, ptr %P, <2 x i64> zeroinitializer, i64 %X 277 %B = getelementptr inbounds <vscale x 2 x i64>, ptr %P, <2 x i64> %y 278 %C = icmp eq <2 x ptr> %A, %B 279 ret <2 x i1> %C 280} 281 282define <vscale x 2 x i1> @test13_scalable_scalable(i64 %X, ptr %P, <vscale x 2 x i64> %y) nounwind { 283; CHECK-LABEL: @test13_scalable_scalable( 284; CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <vscale x 2 x i64> poison, i64 [[X:%.*]], i64 0 285; CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <vscale x 2 x i64> [[DOTSPLATINSERT]], <vscale x 2 x i64> poison, <vscale x 2 x i32> zeroinitializer 286; CHECK-NEXT: [[A_IDX:%.*]] = shl nsw <vscale x 2 x i64> [[DOTSPLAT]], splat (i64 3) 287; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64() 288; CHECK-NEXT: [[TMP2:%.*]] = shl i64 [[TMP1]], 4 289; CHECK-NEXT: [[DOTSPLATINSERT1:%.*]] = insertelement <vscale x 2 x i64> poison, i64 [[TMP2]], i64 0 290; CHECK-NEXT: [[DOTSPLAT2:%.*]] = shufflevector <vscale x 2 x i64> [[DOTSPLATINSERT1]], <vscale x 2 x i64> poison, <vscale x 2 x i32> zeroinitializer 291; CHECK-NEXT: [[B_IDX:%.*]] = mul nsw <vscale x 2 x i64> [[Y:%.*]], [[DOTSPLAT2]] 292; CHECK-NEXT: [[C:%.*]] = icmp eq <vscale x 2 x i64> [[A_IDX]], [[B_IDX]] 293; CHECK-NEXT: ret <vscale x 2 x i1> [[C]] 294; 295 %A = getelementptr inbounds <vscale x 2 x i64>, ptr %P, <vscale x 2 x i64> zeroinitializer, i64 %X 296 %B = getelementptr inbounds <vscale x 2 x i64>, ptr %P, <vscale x 2 x i64> %y 297 %C = icmp eq <vscale x 2 x ptr> %A, %B 298 ret <vscale x 2 x i1> %C 299} 300 301; This is a test of icmp + shl nuw in disguise - 4611... is 0x3fff... 302define <2 x i1> @test13_vector3(i64 %X, <2 x ptr> %P) nounwind { 303; CHECK-LABEL: @test13_vector3( 304; CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <2 x i64> poison, i64 [[X:%.*]], i64 0 305; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i64> [[DOTSPLATINSERT]], <i64 2, i64 0> 306; CHECK-NEXT: [[TMP2:%.*]] = icmp eq <2 x i64> [[TMP1]], <i64 4, i64 poison> 307; CHECK-NEXT: [[C:%.*]] = shufflevector <2 x i1> [[TMP2]], <2 x i1> poison, <2 x i32> zeroinitializer 308; CHECK-NEXT: ret <2 x i1> [[C]] 309; 310 %A = getelementptr inbounds %S, <2 x ptr> %P, <2 x i64> zeroinitializer, <2 x i32> <i32 1, i32 1>, i64 %X 311 %B = getelementptr inbounds %S, <2 x ptr> %P, <2 x i64> <i64 0, i64 0>, <2 x i32> <i32 1, i32 1>, i64 1 312 %C = icmp eq <2 x ptr> %A, %B 313 ret <2 x i1> %C 314} 315 316define i1 @test13_as1(i16 %X, ptr addrspace(1) %P) { 317; CHECK-LABEL: @test13_as1( 318; CHECK-NEXT: [[C:%.*]] = icmp eq i16 [[X:%.*]], -1 319; CHECK-NEXT: ret i1 [[C]] 320; 321 %A = getelementptr inbounds %S, ptr addrspace(1) %P, i16 0, i32 1, i16 %X 322 %C = icmp eq ptr addrspace(1) %A, %P 323 ret i1 %C 324} 325 326define <2 x i1> @test13_vector_as1(<2 x i16> %X, <2 x ptr addrspace(1)> %P) { 327; CHECK-LABEL: @test13_vector_as1( 328; CHECK-NEXT: [[C:%.*]] = icmp eq <2 x i16> [[X:%.*]], splat (i16 -1) 329; CHECK-NEXT: ret <2 x i1> [[C]] 330; 331 %A = getelementptr inbounds %S, <2 x ptr addrspace(1)> %P, <2 x i16> <i16 0, i16 0>, <2 x i32> <i32 1, i32 1>, <2 x i16> %X 332 %B = getelementptr inbounds %S, <2 x ptr addrspace(1)> %P, <2 x i16> <i16 0, i16 0>, <2 x i32> <i32 0, i32 0> 333 %C = icmp eq <2 x ptr addrspace(1)> %A, %B 334 ret <2 x i1> %C 335} 336 337define i1 @test13_i32(i32 %X, ptr %P) { 338; CHECK-LABEL: @test13_i32( 339; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[X:%.*]], -1 340; CHECK-NEXT: ret i1 [[C]] 341; 342 %A = getelementptr inbounds %S, ptr %P, i32 0, i32 1, i32 %X 343 %C = icmp eq ptr %A, %P 344 ret i1 %C 345} 346 347define i1 @test13_i16(i16 %X, ptr %P) { 348; CHECK-LABEL: @test13_i16( 349; CHECK-NEXT: [[C:%.*]] = icmp eq i16 [[X:%.*]], -1 350; CHECK-NEXT: ret i1 [[C]] 351; 352 %A = getelementptr inbounds %S, ptr %P, i16 0, i32 1, i16 %X 353 %C = icmp eq ptr %A, %P 354 ret i1 %C 355} 356 357define i1 @test13_i128(i128 %X, ptr %P) { 358; CHECK-LABEL: @test13_i128( 359; CHECK-NEXT: [[TMP1:%.*]] = trunc i128 [[X:%.*]] to i64 360; CHECK-NEXT: [[C:%.*]] = icmp eq i64 [[TMP1]], -1 361; CHECK-NEXT: ret i1 [[C]] 362; 363 %A = getelementptr inbounds %S, ptr %P, i128 0, i32 1, i128 %X 364 %C = icmp eq ptr %A, %P 365 ret i1 %C 366} 367 368 369@G = external global [3 x i8] 370define ptr @test14(i32 %idx) { 371; CHECK-LABEL: @test14( 372; CHECK-NEXT: [[ZEXT:%.*]] = zext i32 [[IDX:%.*]] to i64 373; CHECK-NEXT: [[T:%.*]] = getelementptr i8, ptr @G, i64 [[ZEXT]] 374; CHECK-NEXT: ret ptr [[T]] 375; 376 %zext = zext i32 %idx to i64 377 %t = getelementptr i8, ptr @G, i64 %zext 378 ret ptr %t 379} 380 381 382; Test folding of constantexpr geps into normal geps. 383@Array = external global [40 x i32] 384define ptr @test15(i64 %X) { 385; CHECK-LABEL: @test15( 386; CHECK-NEXT: [[A:%.*]] = getelementptr i32, ptr @Array, i64 [[X:%.*]] 387; CHECK-NEXT: ret ptr [[A]] 388; 389 %A = getelementptr i32, ptr @Array, i64 %X 390 ret ptr %A 391} 392 393define ptr @test_index_canon(ptr %X, i32 %Idx) { 394; CHECK-LABEL: @test_index_canon( 395; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[IDX:%.*]] to i64 396; CHECK-NEXT: [[R:%.*]] = getelementptr i32, ptr [[X:%.*]], i64 [[TMP1]] 397; CHECK-NEXT: ret ptr [[R]] 398; 399 %R = getelementptr i32, ptr %X, i32 %Idx 400 ret ptr %R 401} 402 403define ptr @test_index_canon_inbounds(ptr %X, i32 %Idx) { 404; CHECK-LABEL: @test_index_canon_inbounds( 405; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[IDX:%.*]] to i64 406; CHECK-NEXT: [[R:%.*]] = getelementptr inbounds i32, ptr [[X:%.*]], i64 [[TMP1]] 407; CHECK-NEXT: ret ptr [[R]] 408; 409 %R = getelementptr inbounds i32, ptr %X, i32 %Idx 410 ret ptr %R 411} 412 413define ptr @test_index_canon_nusw_nuw(ptr %X, i32 %Idx) { 414; CHECK-LABEL: @test_index_canon_nusw_nuw( 415; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[IDX:%.*]] to i64 416; CHECK-NEXT: [[R:%.*]] = getelementptr nusw nuw i32, ptr [[X:%.*]], i64 [[TMP1]] 417; CHECK-NEXT: ret ptr [[R]] 418; 419 %R = getelementptr nusw nuw i32, ptr %X, i32 %Idx 420 ret ptr %R 421} 422 423define ptr @test_index_canon_const_expr_inbounds() { 424; CHECK-LABEL: @test_index_canon_const_expr_inbounds( 425; CHECK-NEXT: ret ptr getelementptr inbounds nuw (i8, ptr @Global, i64 123) 426; 427 ret ptr getelementptr inbounds (i8, ptr @Global, i32 123) 428} 429 430define ptr @test_index_canon_const_expr_nuw_nusw() { 431; CHECK-LABEL: @test_index_canon_const_expr_nuw_nusw( 432; CHECK-NEXT: ret ptr getelementptr nusw nuw (i8, ptr @Global, i64 123) 433; 434 ret ptr getelementptr nusw nuw (i8, ptr @Global, i32 123) 435} 436 437define ptr @test_const_gep_gep_nuw() { 438; CHECK-LABEL: @test_const_gep_gep_nuw( 439; CHECK-NEXT: ret ptr getelementptr nuw (i8, ptr @Global, i64 246) 440; 441 ret ptr getelementptr nuw (i8, ptr getelementptr nuw (i8, ptr @Global, i64 123), i64 123) 442} 443 444define ptr @test_const_gep_gep_nusw_no_overflow() { 445; CHECK-LABEL: @test_const_gep_gep_nusw_no_overflow( 446; CHECK-NEXT: ret ptr getelementptr nusw nuw (i8, ptr @Global, i64 246) 447; 448 ret ptr getelementptr nusw (i8, ptr getelementptr nusw (i8, ptr @Global, i64 123), i64 123) 449} 450 451define ptr @test_const_gep_gep_nusw_no_overflow_neg() { 452; CHECK-LABEL: @test_const_gep_gep_nusw_no_overflow_neg( 453; CHECK-NEXT: ret ptr getelementptr nusw (i8, ptr @Global, i64 -246) 454; 455 ret ptr getelementptr nusw (i8, ptr getelementptr nusw (i8, ptr @Global, i64 -123), i64 -123) 456} 457 458define ptr @test_const_gep_gep_nusw_overflow() { 459; CHECK-LABEL: @test_const_gep_gep_nusw_overflow( 460; CHECK-NEXT: ret ptr getelementptr (i8, ptr @Global, i64 -2) 461; 462 ret ptr getelementptr nusw (i8, ptr getelementptr nusw (i8, ptr @Global, i64 u0x7fffffffffffffff), i64 u0x7fffffffffffffff) 463} 464 465define i1 @test17(ptr %P, i32 %I, i32 %J) { 466; CHECK-LABEL: @test17( 467; CHECK-NEXT: [[C:%.*]] = icmp slt i32 [[I:%.*]], [[J:%.*]] 468; CHECK-NEXT: ret i1 [[C]] 469; 470 %X = getelementptr inbounds i16, ptr %P, i32 %I 471 %Y = getelementptr inbounds i16, ptr %P, i32 %J 472 %C = icmp ult ptr %X, %Y 473 ret i1 %C 474} 475 476define i1 @test18(ptr %P, i32 %I) { 477; CHECK-LABEL: @test18( 478; CHECK-NEXT: [[C:%.*]] = icmp slt i32 [[I:%.*]], 0 479; CHECK-NEXT: ret i1 [[C]] 480; 481 %X = getelementptr inbounds i16, ptr %P, i32 %I 482 %C = icmp ult ptr %X, %P 483 ret i1 %C 484} 485 486; Larger than the pointer size for a non-zero address space 487define i1 @test18_as1(ptr addrspace(1) %P, i32 %I) { 488; CHECK-LABEL: @test18_as1( 489; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[I:%.*]], 32768 490; CHECK-NEXT: [[C:%.*]] = icmp ne i32 [[TMP1]], 0 491; CHECK-NEXT: ret i1 [[C]] 492; 493 %X = getelementptr inbounds i16, ptr addrspace(1) %P, i32 %I 494 %C = icmp ult ptr addrspace(1) %X, %P 495 ret i1 %C 496} 497 498; Smaller than the pointer size for a non-zero address space 499define i1 @test18_as1_i32(ptr addrspace(1) %P, i32 %I) { 500; CHECK-LABEL: @test18_as1_i32( 501; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[I:%.*]], 32768 502; CHECK-NEXT: [[C:%.*]] = icmp ne i32 [[TMP1]], 0 503; CHECK-NEXT: ret i1 [[C]] 504; 505 %X = getelementptr inbounds i16, ptr addrspace(1) %P, i32 %I 506 %C = icmp ult ptr addrspace(1) %X, %P 507 ret i1 %C 508} 509 510; Smaller than pointer size 511define i1 @test18_i16(ptr %P, i16 %I) { 512; CHECK-LABEL: @test18_i16( 513; CHECK-NEXT: [[C:%.*]] = icmp slt i16 [[I:%.*]], 0 514; CHECK-NEXT: ret i1 [[C]] 515; 516 %X = getelementptr inbounds i16, ptr %P, i16 %I 517 %C = icmp ult ptr %X, %P 518 ret i1 %C 519} 520 521; Same as pointer size 522define i1 @test18_i64(ptr %P, i64 %I) { 523; CHECK-LABEL: @test18_i64( 524; CHECK-NEXT: [[C:%.*]] = icmp slt i64 [[I:%.*]], 0 525; CHECK-NEXT: ret i1 [[C]] 526; 527 %X = getelementptr inbounds i16, ptr %P, i64 %I 528 %C = icmp ult ptr %X, %P 529 ret i1 %C 530} 531 532; Larger than the pointer size 533define i1 @test18_i128(ptr %P, i128 %I) { 534; CHECK-LABEL: @test18_i128( 535; CHECK-NEXT: [[TMP1:%.*]] = and i128 [[I:%.*]], 9223372036854775808 536; CHECK-NEXT: [[C:%.*]] = icmp ne i128 [[TMP1]], 0 537; CHECK-NEXT: ret i1 [[C]] 538; 539 %X = getelementptr inbounds i16, ptr %P, i128 %I 540 %C = icmp ult ptr %X, %P 541 ret i1 %C 542} 543 544define i32 @test19(ptr %P, i32 %A, i32 %B) { 545; CHECK-LABEL: @test19( 546; CHECK-NEXT: [[T10:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] 547; CHECK-NEXT: [[T11:%.*]] = zext i1 [[T10]] to i32 548; CHECK-NEXT: ret i32 [[T11]] 549; 550 %t4 = getelementptr inbounds i32, ptr %P, i32 %A 551 %t9 = getelementptr inbounds i32, ptr %P, i32 %B 552 %t10 = icmp eq ptr %t4, %t9 553 %t11 = zext i1 %t10 to i32 554 ret i32 %t11 555} 556 557define i32 @test20(ptr %P, i32 %A, i32 %B) { 558; CHECK-LABEL: @test20( 559; CHECK-NEXT: [[T6:%.*]] = icmp eq i32 [[A:%.*]], 0 560; CHECK-NEXT: [[T7:%.*]] = zext i1 [[T6]] to i32 561; CHECK-NEXT: ret i32 [[T7]] 562; 563 %t4 = getelementptr inbounds i32, ptr %P, i32 %A 564 %t6 = icmp eq ptr %t4, %P 565 %t7 = zext i1 %t6 to i32 566 ret i32 %t7 567} 568 569define i32 @test20_as1(ptr addrspace(1) %P, i32 %A, i32 %B) { 570; CHECK-LABEL: @test20_as1( 571; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[A:%.*]] to i16 572; CHECK-NEXT: [[T6:%.*]] = icmp eq i16 [[TMP1]], 0 573; CHECK-NEXT: [[T7:%.*]] = zext i1 [[T6]] to i32 574; CHECK-NEXT: ret i32 [[T7]] 575; 576 %t4 = getelementptr inbounds i32, ptr addrspace(1) %P, i32 %A 577 %t6 = icmp eq ptr addrspace(1) %t4, %P 578 %t7 = zext i1 %t6 to i32 579 ret i32 %t7 580} 581 582 583define i32 @test21() { 584; CHECK-LABEL: @test21( 585; CHECK-NEXT: [[PBOB1:%.*]] = alloca [[INTSTRUCT:%.*]], align 8 586; CHECK-NEXT: [[RVAL:%.*]] = load i32, ptr [[PBOB1]], align 4 587; CHECK-NEXT: ret i32 [[RVAL]] 588; 589 %pbob1 = alloca %intstruct 590 %pbob2 = getelementptr %intstruct, ptr %pbob1 591 %rval = load i32, ptr %pbob2 592 ret i32 %rval 593} 594 595 596@A = global i32 1 ; <ptr> [#uses=1] 597@B = global i32 2 ; <ptr> [#uses=1] 598 599define i1 @test22() { 600; CHECK-LABEL: @test22( 601; CHECK-NEXT: [[C:%.*]] = icmp ult ptr getelementptr inbounds nuw (i8, ptr @A, i64 4), getelementptr (i8, ptr @B, i64 8) 602; CHECK-NEXT: ret i1 [[C]] 603; 604 %C = icmp ult ptr getelementptr (i32, ptr @A, i64 1), 605 getelementptr (i32, ptr @B, i64 2) 606 ret i1 %C 607} 608 609 610%X = type { [10 x i32], float } 611 612define i1 @test23() { 613; CHECK-LABEL: @test23( 614; CHECK-NEXT: ret i1 false 615; 616 %A = getelementptr %X, ptr null, i64 0, i32 0, i64 0 ; <ptr> [#uses=1] 617 %B = icmp ne ptr %A, null ; <i1> [#uses=1] 618 ret i1 %B 619} 620 621define void @test25() { 622; CHECK-LABEL: @test25( 623; CHECK-NEXT: entry: 624; CHECK-NEXT: unreachable 625; 626entry: 627 %t = getelementptr { i64, i64, i64, i64 }, ptr null, i32 0, i32 3 628 %t.upgrd.1 = load i64, ptr %t 629 %t8.ui = load i64, ptr null 630 %t8 = bitcast i64 %t8.ui to i64 631 %t9 = and i64 %t8, %t.upgrd.1 632 %sext = trunc i64 %t9 to i32 633 %t27.i = sext i32 %sext to i64 634 tail call void @foo25( i32 0, i64 %t27.i ) 635 unreachable 636} 637 638declare void @foo25(i32, i64) 639 640 641; PR1637 642define i1 @test26(ptr %arr) { 643; CHECK-LABEL: @test26( 644; CHECK-NEXT: ret i1 true 645; 646 %X = getelementptr i8, ptr %arr, i32 1 647 %Y = getelementptr i8, ptr %arr, i32 1 648 %test = icmp uge ptr %X, %Y 649 ret i1 %test 650} 651 652 %struct.__large_struct = type { [100 x i64] } 653 %struct.compat_siginfo = type { i32, i32, i32, { [29 x i32] } } 654 %struct.siginfo_t = type { i32, i32, i32, { { i32, i32, [0 x i8], %struct.sigval_t, i32 }, [88 x i8] } } 655 %struct.sigval_t = type { ptr } 656 657define i32 @test27(ptr %to, ptr %from) { 658; CHECK-LABEL: @test27( 659; CHECK-NEXT: entry: 660; CHECK-NEXT: [[FROM_ADDR:%.*]] = alloca ptr, align 8 661; CHECK-NEXT: [[T344:%.*]] = load ptr, ptr [[FROM_ADDR]], align 8 662; CHECK-NEXT: [[T348:%.*]] = getelementptr i8, ptr [[T344]], i64 24 663; CHECK-NEXT: [[T351:%.*]] = load i32, ptr [[T348]], align 8 664; CHECK-NEXT: [[T360:%.*]] = call i32 asm sideeffect "...", "=r,ir,*m,i,0,~{dirflag},~{fpsr},~{flags}"(i32 [[T351]], ptr elementtype([[STRUCT___LARGE_STRUCT:%.*]]) null, i32 -14, i32 0) #[[ATTR0:[0-9]+]] 665; CHECK-NEXT: unreachable 666; 667entry: 668 %from_addr = alloca ptr 669 %t344 = load ptr, ptr %from_addr, align 8 670 %t345 = getelementptr %struct.siginfo_t, ptr %t344, i32 0, i32 3 671 %t346 = getelementptr { { i32, i32, [0 x i8], %struct.sigval_t, i32 }, [88 x i8] }, ptr %t345, i32 0, i32 0 672 %t348 = getelementptr { i32, i32, %struct.sigval_t }, ptr %t346, i32 0, i32 2 673 %t351 = load i32, ptr %t348, align 8 674 %t360 = call i32 asm sideeffect "...", 675 "=r,ir,*m,i,0,~{dirflag},~{fpsr},~{flags}"( i32 %t351, ptr elementtype(%struct.__large_struct) null, i32 -14, i32 0 ) 676 unreachable 677} 678 679; PR1978 680 %struct.x = type <{ i8 }> 681@.str = internal constant [6 x i8] c"Main!\00" 682@.str1 = internal constant [12 x i8] c"destroy %p\0A\00" 683 684define i32 @test28() nounwind { 685; CHECK-LABEL: @test28( 686; CHECK-NEXT: entry: 687; CHECK-NEXT: [[ORIENTATIONS:%.*]] = alloca [1 x [1 x %struct.x]], align 8 688; CHECK-NEXT: [[T3:%.*]] = call i32 @puts(ptr noundef nonnull dereferenceable(1) @.str) #[[ATTR0]] 689; CHECK-NEXT: [[T45:%.*]] = getelementptr inbounds nuw i8, ptr [[ORIENTATIONS]], i64 1 690; CHECK-NEXT: br label [[BB10:%.*]] 691; CHECK: bb10: 692; CHECK-NEXT: [[INDVAR:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[BB10]] ] 693; CHECK-NEXT: [[T12_REC:%.*]] = xor i32 [[INDVAR]], -1 694; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[T12_REC]] to i64 695; CHECK-NEXT: [[T12:%.*]] = getelementptr inbounds [[STRUCT_X:%.*]], ptr [[T45]], i64 [[TMP0]] 696; CHECK-NEXT: [[T16:%.*]] = call i32 (ptr, ...) @printf(ptr noundef nonnull dereferenceable(1) @.str1, ptr nonnull [[T12]]) #[[ATTR0]] 697; CHECK-NEXT: [[T84:%.*]] = icmp eq ptr [[T12]], [[ORIENTATIONS]] 698; CHECK-NEXT: [[INDVAR_NEXT]] = add i32 [[INDVAR]], 1 699; CHECK-NEXT: br i1 [[T84]], label [[BB17:%.*]], label [[BB10]] 700; CHECK: bb17: 701; CHECK-NEXT: ret i32 0 702; 703entry: 704 %orientations = alloca [1 x [1 x %struct.x]] 705 %t3 = call i32 @puts( ptr @.str ) nounwind 706 %t45 = getelementptr inbounds [1 x [1 x %struct.x]], ptr %orientations, i32 1, i32 0, i32 0 707 br label %bb10 708 709bb10: 710 %indvar = phi i32 [ 0, %entry ], [ %indvar.next, %bb10 ] 711 %t.0.reg2mem.0.rec = mul i32 %indvar, -1 712 %t12.rec = add i32 %t.0.reg2mem.0.rec, -1 713 %t12 = getelementptr inbounds %struct.x, ptr %t45, i32 %t12.rec 714 %t16 = call i32 (ptr, ...) @printf( ptr nonnull dereferenceable(1) @.str1, ptr %t12 ) nounwind 715 %t84 = icmp eq ptr %t12, %orientations 716 %indvar.next = add i32 %indvar, 1 717 br i1 %t84, label %bb17, label %bb10 718 719bb17: 720 ret i32 0 721} 722 723declare i32 @puts(ptr) 724 725declare i32 @printf(ptr, ...) 726 727 728 729 730; rdar://6762290 731 %T = type <{ i64, i64, i64 }> 732define i32 @test29(ptr %start, i32 %X) nounwind { 733; CHECK-LABEL: @test29( 734; CHECK-NEXT: entry: 735; CHECK-NEXT: store i1 true, ptr poison, align 1 736; CHECK-NEXT: br i1 poison, label [[IF_THEN216:%.*]], label [[IF_END363:%.*]] 737; CHECK: if.then216: 738; CHECK-NEXT: ret i32 1 739; CHECK: if.end363: 740; CHECK-NEXT: ret i32 0 741; 742entry: 743 %t3 = load i64, ptr null 744 %add.ptr = getelementptr i8, ptr %start, i64 %t3 745 %t158 = load i32, ptr null 746 %add.ptr159 = getelementptr %T, ptr null, i32 %t158 747 %add.ptr212 = getelementptr i8, ptr %start, i32 %X 748 %cmp214 = icmp ugt ptr %add.ptr212, %add.ptr 749 br i1 %cmp214, label %if.then216, label %if.end363 750 751if.then216: 752 ret i32 1 753 754if.end363: 755 ret i32 0 756} 757 758 759; PR3694 760define i32 @test30(i32 %m, i32 %n) nounwind { 761; CHECK-LABEL: @test30( 762; CHECK-NEXT: entry: 763; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[N:%.*]] to i64 764; CHECK-NEXT: [[TMP1:%.*]] = alloca i32, i64 [[TMP0]], align 4 765; CHECK-NEXT: call void @test30f(ptr nonnull [[TMP1]]) #[[ATTR0]] 766; CHECK-NEXT: [[TMP2:%.*]] = sext i32 [[M:%.*]] to i64 767; CHECK-NEXT: [[TMP3:%.*]] = getelementptr [0 x i32], ptr [[TMP1]], i64 0, i64 [[TMP2]] 768; CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[TMP3]], align 4 769; CHECK-NEXT: ret i32 [[TMP4]] 770; 771entry: 772 %0 = alloca i32, i32 %n, align 4 773 call void @test30f(ptr %0) nounwind 774 %1 = getelementptr [0 x i32], ptr %0, i32 0, i32 %m 775 %2 = load i32, ptr %1, align 4 776 ret i32 %2 777} 778 779declare void @test30f(ptr) 780 781 782 783define i1 @test31(ptr %A) { 784; CHECK-LABEL: @test31( 785; CHECK-NEXT: ret i1 true 786; 787 %B = getelementptr i32, ptr %A, i32 1 788 %C = getelementptr i32, ptr %A, i64 1 789 %V = icmp eq ptr %B, %C 790 ret i1 %V 791} 792 793 794; PR1345 795define ptr @test32(ptr %v) { 796; CHECK-LABEL: @test32( 797; CHECK-NEXT: [[A:%.*]] = alloca [4 x ptr], align 16 798; CHECK-NEXT: store ptr null, ptr [[A]], align 8 799; CHECK-NEXT: [[D:%.*]] = getelementptr inbounds nuw i8, ptr [[A]], i64 8 800; CHECK-NEXT: store ptr [[V:%.*]], ptr [[D]], align 8 801; CHECK-NEXT: [[F:%.*]] = getelementptr inbounds nuw i8, ptr [[A]], i64 16 802; CHECK-NEXT: [[G:%.*]] = load ptr, ptr [[F]], align 8 803; CHECK-NEXT: ret ptr [[G]] 804; 805 %A = alloca [4 x ptr], align 16 806 store ptr null, ptr %A 807 %D = getelementptr { [16 x i8] }, ptr %A, i32 0, i32 0, i32 8 808 store ptr %v, ptr %D 809 %F = getelementptr [4 x ptr], ptr %A, i32 0, i32 2 810 %G = load ptr, ptr %F 811 ret ptr %G 812} 813 814; PR3290 815%struct.Key = type { { i32, i32 } } 816%struct.anon = type <{ i8, [3 x i8], i32 }> 817 818define ptr @test33(ptr %A) { 819; CHECK-LABEL: @test33( 820; CHECK-NEXT: [[C:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 4 821; CHECK-NEXT: ret ptr [[C]] 822; 823 %C = getelementptr %struct.anon, ptr %A, i32 0, i32 2 824 ret ptr %C 825} 826 827define ptr addrspace(1) @test33_as1(ptr addrspace(1) %A) { 828; CHECK-LABEL: @test33_as1( 829; CHECK-NEXT: [[C:%.*]] = getelementptr i8, ptr addrspace(1) [[A:%.*]], i16 4 830; CHECK-NEXT: ret ptr addrspace(1) [[C]] 831; 832 %C = getelementptr %struct.anon, ptr addrspace(1) %A, i32 0, i32 2 833 ret ptr addrspace(1) %C 834} 835 836define ptr addrspace(1) @test33_array_as1(ptr addrspace(1) %A) { 837; CHECK-LABEL: @test33_array_as1( 838; CHECK-NEXT: [[C:%.*]] = getelementptr i8, ptr addrspace(1) [[A:%.*]], i16 8 839; CHECK-NEXT: ret ptr addrspace(1) [[C]] 840; 841 %C = getelementptr [5 x i32], ptr addrspace(1) %A, i32 0, i32 2 842 ret ptr addrspace(1) %C 843} 844 845; Make sure the GEP indices use the right pointer sized integer 846define ptr addrspace(1) @test33_array_struct_as1(ptr addrspace(1) %A) { 847; CHECK-LABEL: @test33_array_struct_as1( 848; CHECK-NEXT: [[C:%.*]] = getelementptr i8, ptr addrspace(1) [[A:%.*]], i16 8 849; CHECK-NEXT: ret ptr addrspace(1) [[C]] 850; 851 %C = getelementptr [20 x i32], ptr addrspace(1) %A, i32 0, i32 2 852 ret ptr addrspace(1) %C 853} 854 855define ptr addrspace(1) @test33_addrspacecast(ptr %A) { 856; CHECK-LABEL: @test33_addrspacecast( 857; CHECK-NEXT: [[B:%.*]] = addrspacecast ptr [[A:%.*]] to ptr addrspace(1) 858; CHECK-NEXT: [[C:%.*]] = getelementptr i8, ptr addrspace(1) [[B]], i16 4 859; CHECK-NEXT: ret ptr addrspace(1) [[C]] 860; 861 %B = addrspacecast ptr %A to ptr addrspace(1) 862 %C = getelementptr %struct.anon, ptr addrspace(1) %B, i32 0, i32 2 863 ret ptr addrspace(1) %C 864} 865 866 %T2 = type { ptr, i8 } 867define ptr @test34(ptr %Val, i64 %V) nounwind { 868; CHECK-LABEL: @test34( 869; CHECK-NEXT: entry: 870; CHECK-NEXT: [[C_CAST:%.*]] = inttoptr i64 [[V:%.*]] to ptr 871; CHECK-NEXT: ret ptr [[C_CAST]] 872; 873entry: 874 %A = alloca %T2, align 8 875 876 store i64 %V, ptr %A 877 %C = load ptr, ptr %A, align 8 878 ret ptr %C 879} 880 881%t0 = type { ptr, [19 x i8] } 882%t1 = type { ptr, [0 x i8] } 883 884@array = external global [11 x i8] 885 886@s = external global %t0 887@"\01LC8" = external constant [17 x i8] 888 889; Instcombine should be able to fold this getelementptr. 890 891define i32 @test35() nounwind { 892; CHECK-LABEL: @test35( 893; CHECK-NEXT: [[TMP1:%.*]] = call i32 (ptr, ...) @printf(ptr noundef nonnull dereferenceable(1) @"\01LC8", ptr nonnull getelementptr inbounds nuw (i8, ptr @s, i64 8)) #[[ATTR0]] 894; CHECK-NEXT: ret i32 0 895; 896 call i32 (ptr, ...) @printf(ptr @"\01LC8", 897 ptr getelementptr (%t1, ptr @s, i32 0, i32 1, i32 0)) nounwind 898 ret i32 0 899} 900 901; Don't treat signed offsets as unsigned. 902define ptr @test36() nounwind { 903; CHECK-LABEL: @test36( 904; CHECK-NEXT: ret ptr getelementptr (i8, ptr @array, i64 -1) 905; 906 ret ptr getelementptr ([11 x i8], ptr @array, i32 0, i64 -1) 907} 908 909; Instcombine shouldn't assume that gep(A,0,1) != gep(A,1,0). 910@A37 = external constant [1 x i8] 911define i1 @test37() nounwind { 912; CHECK-LABEL: @test37( 913; CHECK-NEXT: ret i1 true 914; 915 %t = icmp eq ptr getelementptr ([1 x i8], ptr @A37, i64 0, i64 1), 916 getelementptr ([1 x i8], ptr @A37, i64 1, i64 0) 917 ret i1 %t 918} 919 920; Test index promotion 921define ptr @test38(ptr %I, i32 %n) { 922; CHECK-LABEL: @test38( 923; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[N:%.*]] to i64 924; CHECK-NEXT: [[A:%.*]] = getelementptr i32, ptr [[I:%.*]], i64 [[TMP1]] 925; CHECK-NEXT: ret ptr [[A]] 926; 927 %A = getelementptr i32, ptr %I, i32 %n 928 ret ptr %A 929} 930 931; Test that we don't duplicate work when the second gep is a "bitcast". 932%pr10322_t = type { ptr } 933declare void @pr10322_f2(ptr) 934declare void @pr10322_f3(ptr) 935define void @pr10322_f1(ptr %foo) { 936; CHECK-LABEL: @pr10322_f1( 937; CHECK-NEXT: entry: 938; CHECK-NEXT: [[ARRAYIDX8:%.*]] = getelementptr inbounds nuw i8, ptr [[FOO:%.*]], i64 16 939; CHECK-NEXT: call void @pr10322_f2(ptr nonnull [[ARRAYIDX8]]) #[[ATTR0]] 940; CHECK-NEXT: call void @pr10322_f3(ptr nonnull [[ARRAYIDX8]]) #[[ATTR0]] 941; CHECK-NEXT: ret void 942; 943entry: 944 %arrayidx8 = getelementptr inbounds %pr10322_t, ptr %foo, i64 2 945 call void @pr10322_f2(ptr %arrayidx8) nounwind 946 call void @pr10322_f3(ptr %arrayidx8) nounwind 947 ret void 948 949} 950 951; Test that we combine the last two geps in this sequence, before we 952; would wait for gep1 and gep2 to be combined and never combine 2 and 3. 953%three_gep_t = type {i32} 954%three_gep_t2 = type {%three_gep_t} 955 956define void @three_gep_f(ptr %x) { 957; CHECK-LABEL: @three_gep_f( 958; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i8, ptr [[X:%.*]], i64 8 959; CHECK-NEXT: call void @three_gep_h(ptr [[GEP1]]) 960; CHECK-NEXT: call void @three_gep_g(ptr [[GEP1]]) 961; CHECK-NEXT: ret void 962; 963 %gep1 = getelementptr %three_gep_t2, ptr %x, i64 2 964 call void @three_gep_h(ptr %gep1) 965 call void @three_gep_g(ptr %gep1) 966 967 ret void 968} 969 970declare void @three_gep_g(ptr) 971declare void @three_gep_h(ptr) 972 973%struct.ham = type { i32, ptr, ptr, ptr } 974%struct.zot = type { i64, i8 } 975 976define void @test39(ptr %arg, i8 %arg1) nounwind { 977; CHECK-LABEL: @test39( 978; CHECK-NEXT: [[T:%.*]] = getelementptr inbounds nuw i8, ptr [[ARG:%.*]], i64 16 979; CHECK-NEXT: [[T2:%.*]] = load ptr, ptr [[T]], align 8 980; CHECK-NEXT: [[T4:%.*]] = getelementptr inbounds i8, ptr [[T2]], i64 -8 981; CHECK-NEXT: store i8 [[ARG1:%.*]], ptr [[T4]], align 8 982; CHECK-NEXT: ret void 983; 984 %t = getelementptr inbounds %struct.ham, ptr %arg, i64 0, i32 2 985 %t2 = load ptr, ptr %t, align 8 986 %t4 = getelementptr inbounds i8, ptr %t2, i64 -8 987 store i8 %arg1, ptr %t4, align 8 988 ret void 989 990} 991 992define i1 @pr16483(ptr %a, ptr %b) { 993; CHECK-LABEL: @pr16483( 994; CHECK-NEXT: [[CMP:%.*]] = icmp ult ptr [[A:%.*]], [[B:%.*]] 995; CHECK-NEXT: ret i1 [[CMP]] 996; 997 %cmp = icmp ult ptr %a, %b 998 ret i1 %cmp 999 1000} 1001 1002define i8 @test_gep_bitcast_as1(ptr addrspace(1) %arr, i16 %N) { 1003; CHECK-LABEL: @test_gep_bitcast_as1( 1004; CHECK-NEXT: [[V:%.*]] = shl i16 [[N:%.*]], 2 1005; CHECK-NEXT: [[T:%.*]] = getelementptr i8, ptr addrspace(1) [[ARR:%.*]], i16 [[V]] 1006; CHECK-NEXT: [[X:%.*]] = load i8, ptr addrspace(1) [[T]], align 1 1007; CHECK-NEXT: ret i8 [[X]] 1008; 1009 %V = mul i16 %N, 4 1010 %t = getelementptr i8, ptr addrspace(1) %arr, i16 %V 1011 %x = load i8, ptr addrspace(1) %t 1012 ret i8 %x 1013} 1014 1015; The element size of the array matches the element size of the pointer 1016define i64 @test_gep_bitcast_array_same_size_element(ptr %arr, i64 %N) { 1017; CHECK-LABEL: @test_gep_bitcast_array_same_size_element( 1018; CHECK-NEXT: [[T_IDX:%.*]] = shl i64 [[N:%.*]], 6 1019; CHECK-NEXT: [[T:%.*]] = getelementptr i8, ptr [[ARR:%.*]], i64 [[T_IDX]] 1020; CHECK-NEXT: [[X:%.*]] = load i64, ptr [[T]], align 4 1021; CHECK-NEXT: ret i64 [[X]] 1022; 1023 %V = mul i64 %N, 8 1024 %t = getelementptr i64, ptr %arr, i64 %V 1025 %x = load i64, ptr %t 1026 ret i64 %x 1027} 1028 1029; gep should be done in the original address space. 1030define i64 @test_gep_bitcast_array_same_size_element_addrspacecast(ptr %arr, i64 %N) { 1031; CHECK-LABEL: @test_gep_bitcast_array_same_size_element_addrspacecast( 1032; CHECK-NEXT: [[CAST:%.*]] = addrspacecast ptr [[ARR:%.*]] to ptr addrspace(3) 1033; CHECK-NEXT: [[T_IDX:%.*]] = shl i64 [[N:%.*]], 6 1034; CHECK-NEXT: [[T:%.*]] = getelementptr i8, ptr addrspace(3) [[CAST]], i64 [[T_IDX]] 1035; CHECK-NEXT: [[X:%.*]] = load i64, ptr addrspace(3) [[T]], align 4 1036; CHECK-NEXT: ret i64 [[X]] 1037; 1038 %cast = addrspacecast ptr %arr to ptr addrspace(3) 1039 %V = mul i64 %N, 8 1040 %t = getelementptr i64, ptr addrspace(3) %cast, i64 %V 1041 %x = load i64, ptr addrspace(3) %t 1042 ret i64 %x 1043} 1044 1045; The element size of the array is different the element size of the pointer 1046define i8 @test_gep_bitcast_array_different_size_element(ptr %arr, i64 %N) { 1047; CHECK-LABEL: @test_gep_bitcast_array_different_size_element( 1048; CHECK-NEXT: [[V:%.*]] = shl i64 [[N:%.*]], 3 1049; CHECK-NEXT: [[T:%.*]] = getelementptr i8, ptr [[ARR:%.*]], i64 [[V]] 1050; CHECK-NEXT: [[X:%.*]] = load i8, ptr [[T]], align 1 1051; CHECK-NEXT: ret i8 [[X]] 1052; 1053 %V = mul i64 %N, 8 1054 %t = getelementptr i8, ptr %arr, i64 %V 1055 %x = load i8, ptr %t 1056 ret i8 %x 1057} 1058 1059define i64 @test_gep_bitcast_array_same_size_element_as1(ptr addrspace(1) %arr, i16 %N) { 1060; CHECK-LABEL: @test_gep_bitcast_array_same_size_element_as1( 1061; CHECK-NEXT: [[T_IDX:%.*]] = shl i16 [[N:%.*]], 6 1062; CHECK-NEXT: [[T:%.*]] = getelementptr i8, ptr addrspace(1) [[ARR:%.*]], i16 [[T_IDX]] 1063; CHECK-NEXT: [[X:%.*]] = load i64, ptr addrspace(1) [[T]], align 4 1064; CHECK-NEXT: ret i64 [[X]] 1065; 1066 %V = mul i16 %N, 8 1067 %t = getelementptr i64, ptr addrspace(1) %arr, i16 %V 1068 %x = load i64, ptr addrspace(1) %t 1069 ret i64 %x 1070} 1071 1072define i8 @test_gep_bitcast_array_different_size_element_as1(ptr addrspace(1) %arr, i16 %N) { 1073; CHECK-LABEL: @test_gep_bitcast_array_different_size_element_as1( 1074; CHECK-NEXT: [[V:%.*]] = shl i16 [[N:%.*]], 3 1075; CHECK-NEXT: [[T:%.*]] = getelementptr i8, ptr addrspace(1) [[ARR:%.*]], i16 [[V]] 1076; CHECK-NEXT: [[X:%.*]] = load i8, ptr addrspace(1) [[T]], align 1 1077; CHECK-NEXT: ret i8 [[X]] 1078; 1079 %V = mul i16 %N, 8 1080 %t = getelementptr i8, ptr addrspace(1) %arr, i16 %V 1081 %x = load i8, ptr addrspace(1) %t 1082 ret i8 %x 1083} 1084 1085define i64 @test40() { 1086; CHECK-LABEL: @test40( 1087; CHECK-NEXT: ret i64 8 1088; 1089 %array = alloca [3 x i32], align 4 1090 %gep = getelementptr inbounds [3 x i32], ptr %array, i64 0, i64 2 1091 %p = ptrtoint ptr %array to i64 1092 %np = sub i64 0, %p 1093 %gep2 = getelementptr i8, ptr %gep, i64 %np 1094 %ret = ptrtoint ptr %gep2 to i64 1095 ret i64 %ret 1096 1097} 1098 1099define i16 @test41(ptr addrspace(1) %array) { 1100; CHECK-LABEL: @test41( 1101; CHECK-NEXT: ret i16 8 1102; 1103 %gep = getelementptr inbounds [3 x i32], ptr addrspace(1) %array, i16 0, i16 2 1104 %p = ptrtoint ptr addrspace(1) %array to i16 1105 %np = sub i16 0, %p 1106 %gep2 = getelementptr i8, ptr addrspace(1) %gep, i16 %np 1107 %ret = ptrtoint ptr addrspace(1) %gep2 to i16 1108 ret i16 %ret 1109 1110} 1111 1112define ptr @test42i(ptr %c1, ptr %c2) { 1113; CHECK-LABEL: @test42i( 1114; CHECK-NEXT: [[PTRTOINT:%.*]] = ptrtoint ptr [[C1:%.*]] to i64 1115; CHECK-NEXT: [[SUB:%.*]] = sub i64 0, [[PTRTOINT]] 1116; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr [[C2:%.*]], i64 [[SUB]] 1117; CHECK-NEXT: ret ptr [[GEP]] 1118; 1119 %ptrtoint = ptrtoint ptr %c1 to i64 1120 %sub = sub i64 0, %ptrtoint 1121 %gep = getelementptr inbounds i8, ptr %c2, i64 %sub 1122 ret ptr %gep 1123 1124} 1125 1126define ptr @test42(ptr %c1, ptr %c2) { 1127; CHECK-LABEL: @test42( 1128; CHECK-NEXT: [[PTRTOINT:%.*]] = ptrtoint ptr [[C1:%.*]] to i64 1129; CHECK-NEXT: [[SUB:%.*]] = sub i64 0, [[PTRTOINT]] 1130; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[C2:%.*]], i64 [[SUB]] 1131; CHECK-NEXT: ret ptr [[GEP]] 1132; 1133 %ptrtoint = ptrtoint ptr %c1 to i64 1134 %sub = sub i64 0, %ptrtoint 1135 %gep = getelementptr i8, ptr %c2, i64 %sub 1136 ret ptr %gep 1137 1138} 1139 1140define ptr @test43i(ptr %c1, ptr %c2) { 1141; CHECK-LABEL: @test43i( 1142; CHECK-NEXT: [[PTRTOINT:%.*]] = ptrtoint ptr [[C1:%.*]] to i64 1143; CHECK-NEXT: [[SUB:%.*]] = sub i64 0, [[PTRTOINT]] 1144; CHECK-NEXT: [[SHR:%.*]] = ashr i64 [[SUB]], 1 1145; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i16, ptr [[C2:%.*]], i64 [[SHR]] 1146; CHECK-NEXT: ret ptr [[GEP]] 1147; 1148 %ptrtoint = ptrtoint ptr %c1 to i64 1149 %sub = sub i64 0, %ptrtoint 1150 %shr = ashr i64 %sub, 1 1151 %gep = getelementptr inbounds i16, ptr %c2, i64 %shr 1152 ret ptr %gep 1153 1154} 1155 1156define ptr @test44i(ptr %c1, ptr %c2) { 1157; CHECK-LABEL: @test44i( 1158; CHECK-NEXT: [[PTRTOINT:%.*]] = ptrtoint ptr [[C1:%.*]] to i64 1159; CHECK-NEXT: [[SUB:%.*]] = sub i64 0, [[PTRTOINT]] 1160; CHECK-NEXT: [[SHR:%.*]] = sdiv i64 [[SUB]], 7 1161; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [[STRUCT_C:%.*]], ptr [[C2:%.*]], i64 [[SHR]] 1162; CHECK-NEXT: ret ptr [[GEP]] 1163; 1164 %ptrtoint = ptrtoint ptr %c1 to i64 1165 %sub = sub i64 0, %ptrtoint 1166 %shr = sdiv i64 %sub, 7 1167 %gep = getelementptr inbounds %struct.C, ptr %c2, i64 %shr 1168 ret ptr %gep 1169 1170} 1171 1172define ptr @test45(ptr %c1, ptr %c2) { 1173; CHECK-LABEL: @test45( 1174; CHECK-NEXT: [[PTRTOINT1:%.*]] = ptrtoint ptr [[C1:%.*]] to i64 1175; CHECK-NEXT: [[PTRTOINT2:%.*]] = ptrtoint ptr [[C2:%.*]] to i64 1176; CHECK-NEXT: [[SUB:%.*]] = sub i64 [[PTRTOINT2]], [[PTRTOINT1]] 1177; CHECK-NEXT: [[SHR:%.*]] = sdiv i64 [[SUB]], 7 1178; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [[STRUCT_C:%.*]], ptr [[C1]], i64 [[SHR]] 1179; CHECK-NEXT: ret ptr [[GEP]] 1180; 1181 %ptrtoint1 = ptrtoint ptr %c1 to i64 1182 %ptrtoint2 = ptrtoint ptr %c2 to i64 1183 %sub = sub i64 %ptrtoint2, %ptrtoint1 ; C2 - C1 1184 %shr = sdiv i64 %sub, 7 1185 %gep = getelementptr inbounds %struct.C, ptr %c1, i64 %shr ; C1 + (C2 - C1) 1186 ret ptr %gep 1187} 1188 1189define ptr @test46(ptr %c1, ptr %c2, i64 %N) { 1190; CHECK-LABEL: @test46( 1191; CHECK-NEXT: [[PTRTOINT:%.*]] = ptrtoint ptr [[C1:%.*]] to i64 1192; CHECK-NEXT: [[SUB:%.*]] = sub i64 0, [[PTRTOINT]] 1193; CHECK-NEXT: [[SDIV:%.*]] = sdiv i64 [[SUB]], [[N:%.*]] 1194; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [[STRUCT_C:%.*]], ptr [[C2:%.*]], i64 [[SDIV]] 1195; CHECK-NEXT: ret ptr [[GEP]] 1196; 1197 %ptrtoint = ptrtoint ptr %c1 to i64 1198 %sub = sub i64 0, %ptrtoint 1199 %sdiv = sdiv i64 %sub, %N 1200 %gep = getelementptr inbounds %struct.C, ptr %c2, i64 %sdiv 1201 ret ptr %gep 1202 1203} 1204 1205define ptr @test47(ptr %I, i64 %C, i64 %D) { 1206; CHECK-LABEL: @test47( 1207; CHECK-NEXT: [[B:%.*]] = getelementptr i32, ptr [[I:%.*]], i64 [[D:%.*]] 1208; CHECK-NEXT: ret ptr [[B]] 1209; 1210 %sub = sub i64 %D, %C 1211 %A = getelementptr i32, ptr %I, i64 %C 1212 %B = getelementptr i32, ptr %A, i64 %sub 1213 ret ptr %B 1214} 1215 1216define ptr @test48(ptr %I, i64 %C, i64 %D) { 1217; CHECK-LABEL: @test48( 1218; CHECK-NEXT: [[B:%.*]] = getelementptr i32, ptr [[I:%.*]], i64 [[D:%.*]] 1219; CHECK-NEXT: ret ptr [[B]] 1220; 1221 %sub = sub i64 %D, %C 1222 %A = getelementptr i32, ptr %I, i64 %sub 1223 %B = getelementptr i32, ptr %A, i64 %C 1224 ret ptr %B 1225} 1226 1227define ptr @test49(ptr %I, i64 %C) { 1228; CHECK-LABEL: @test49( 1229; CHECK-NEXT: [[B:%.*]] = getelementptr i8, ptr [[I:%.*]], i64 -4 1230; CHECK-NEXT: ret ptr [[B]] 1231; 1232 %notC = xor i64 -1, %C 1233 %A = getelementptr i32, ptr %I, i64 %C 1234 %B = getelementptr i32, ptr %A, i64 %notC 1235 ret ptr %B 1236} 1237 1238define ptr addrspace(1) @ascast_0_gep(ptr %p) nounwind { 1239; CHECK-LABEL: @ascast_0_gep( 1240; CHECK-NEXT: [[X:%.*]] = addrspacecast ptr [[P:%.*]] to ptr addrspace(1) 1241; CHECK-NEXT: ret ptr addrspace(1) [[X]] 1242; 1243 %x = addrspacecast ptr %p to ptr addrspace(1) 1244 ret ptr addrspace(1) %x 1245} 1246 1247; Do not merge the GEP and the addrspacecast, because it would undo the 1248; addrspacecast canonicalization. 1249define ptr addrspace(1) @ascast_0_0_gep(ptr %p) nounwind { 1250; CHECK-LABEL: @ascast_0_0_gep( 1251; CHECK-NEXT: [[X:%.*]] = addrspacecast ptr [[P:%.*]] to ptr addrspace(1) 1252; CHECK-NEXT: ret ptr addrspace(1) [[X]] 1253; 1254 %x = addrspacecast ptr %p to ptr addrspace(1) 1255 ret ptr addrspace(1) %x 1256} 1257 1258define <2 x ptr> @PR32414(ptr %ptr) { 1259; CHECK-LABEL: @PR32414( 1260; CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i32, ptr [[PTR:%.*]], <2 x i64> <i64 0, i64 1> 1261; CHECK-NEXT: ret <2 x ptr> [[T1]] 1262; 1263 %t1 = getelementptr inbounds i32, ptr %ptr, <2 x i64> <i64 0, i64 1> 1264 ret <2 x ptr> %t1 1265} 1266 1267define ptr @test_bitcast_nzgep(ptr %base, i64 %idx) { 1268; CHECK-LABEL: @test_bitcast_nzgep( 1269; CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds i32, ptr [[BASE:%.*]], i64 [[IDX:%.*]] 1270; CHECK-NEXT: ret ptr [[PTR]] 1271; 1272 %ptr = getelementptr inbounds i32, ptr %base, i64 %idx 1273 ret ptr %ptr 1274} 1275 1276define ptr @test_zgep_nzgep(ptr %base, i64 %idx) { 1277; CHECK-LABEL: @test_zgep_nzgep( 1278; CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds i32, ptr [[BASE:%.*]], i64 [[IDX:%.*]] 1279; CHECK-NEXT: ret ptr [[PTR]] 1280; 1281 %ptr = getelementptr inbounds i32, ptr %base, i64 %idx 1282 ret ptr %ptr 1283} 1284 1285define ptr @test_nzgep_zgep(ptr %base, i64 %idx) { 1286; CHECK-LABEL: @test_nzgep_zgep( 1287; CHECK-NEXT: [[BASE2:%.*]] = getelementptr inbounds [1 x i32], ptr [[BASE:%.*]], i64 [[IDX:%.*]] 1288; CHECK-NEXT: ret ptr [[BASE2]] 1289; 1290 %base2 = getelementptr inbounds [1 x i32], ptr %base, i64 %idx 1291 ret ptr %base2 1292} 1293 1294define ptr @test_gep_inbounds_of_gep(ptr %base) { 1295; CHECK-LABEL: @test_gep_inbounds_of_gep( 1296; CHECK-NEXT: [[PTR2:%.*]] = getelementptr i8, ptr [[BASE:%.*]], i64 32 1297; CHECK-NEXT: ret ptr [[PTR2]] 1298; 1299 %ptr1 = getelementptr i32, ptr %base, i64 4 1300 %ptr2 = getelementptr inbounds i32, ptr %ptr1, i64 4 1301 ret ptr %ptr2 1302} 1303 1304%struct.f = type { i32 } 1305 1306@g0 = internal unnamed_addr constant %struct.f zeroinitializer, align 4 1307@g1 = internal unnamed_addr constant %struct.f { i32 -1 }, align 4 1308 1309define ptr @PR45084(i1 %cond) { 1310; CHECK-LABEL: @PR45084( 1311; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], ptr @g0, ptr @g1, !prof [[PROF0:![0-9]+]] 1312; CHECK-NEXT: ret ptr [[SEL]] 1313; 1314 %sel = select i1 %cond, ptr @g0, ptr @g1, !prof !0 1315 ret ptr %sel 1316} 1317 1318define ptr @PR45084_extra_use(i1 %cond, ptr %p) { 1319; CHECK-LABEL: @PR45084_extra_use( 1320; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], ptr @g0, ptr @g1 1321; CHECK-NEXT: store ptr [[SEL]], ptr [[P:%.*]], align 8 1322; CHECK-NEXT: ret ptr [[SEL]] 1323; 1324 %sel = select i1 %cond, ptr @g0, ptr @g1 1325 store ptr %sel, ptr %p 1326 ret ptr %sel 1327} 1328 1329define ptr @gep_null_inbounds(i64 %idx) { 1330; CHECK-LABEL: @gep_null_inbounds( 1331; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr null, i64 [[IDX:%.*]] 1332; CHECK-NEXT: ret ptr [[GEP]] 1333; 1334 %gep = getelementptr inbounds i8, ptr null, i64 %idx 1335 ret ptr %gep 1336} 1337 1338define ptr @gep_null_not_inbounds(i64 %idx) { 1339; CHECK-LABEL: @gep_null_not_inbounds( 1340; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr null, i64 [[IDX:%.*]] 1341; CHECK-NEXT: ret ptr [[GEP]] 1342; 1343 %gep = getelementptr i8, ptr null, i64 %idx 1344 ret ptr %gep 1345} 1346 1347define ptr @gep_null_defined(i64 %idx) null_pointer_is_valid { 1348; CHECK-LABEL: @gep_null_defined( 1349; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr null, i64 [[IDX:%.*]] 1350; CHECK-NEXT: ret ptr [[GEP]] 1351; 1352 %gep = getelementptr inbounds i8, ptr null, i64 %idx 1353 ret ptr %gep 1354} 1355 1356define ptr @gep_null_inbounds_different_type(i64 %idx1, i64 %idx2) { 1357; CHECK-LABEL: @gep_null_inbounds_different_type( 1358; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [0 x i8], ptr null, i64 0, i64 [[IDX2:%.*]] 1359; CHECK-NEXT: ret ptr [[GEP]] 1360; 1361 %gep = getelementptr inbounds [0 x i8], ptr null, i64 %idx1, i64 %idx2 1362 ret ptr %gep 1363} 1364 1365define ptr @D98588(ptr %c1, i64 %offset) { 1366; CHECK-LABEL: @D98588( 1367; CHECK-NEXT: [[C2_NEXT_IDX:%.*]] = shl nsw i64 [[OFFSET:%.*]], 3 1368; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr [[C1:%.*]], i64 [[C2_NEXT_IDX]] 1369; CHECK-NEXT: ret ptr [[GEP]] 1370; 1371 %c2_next = getelementptr inbounds i64, ptr %c1, i64 %offset 1372 %ptrtoint1 = ptrtoint ptr %c1 to i64 1373 %ptrtoint2 = ptrtoint ptr %c2_next to i64 1374 %sub = sub i64 %ptrtoint2, %ptrtoint1 ; C2 - C1 1375 %gep = getelementptr inbounds i8, ptr %c1, i64 %sub ; C1 + (C2 - C1) 1376 ret ptr %gep 1377} 1378 1379declare noalias ptr @malloc(i64) nounwind allockind("alloc,uninitialized") allocsize(0) 1380 1381define i32 @test_gep_bitcast_malloc(ptr %a) { 1382; CHECK-LABEL: @test_gep_bitcast_malloc( 1383; CHECK-NEXT: entry: 1384; CHECK-NEXT: [[CALL:%.*]] = call noalias dereferenceable_or_null(16) ptr @malloc(i64 16) 1385; CHECK-NEXT: [[G3:%.*]] = getelementptr i8, ptr [[CALL]], i64 12 1386; CHECK-NEXT: [[A_C:%.*]] = load i32, ptr [[G3]], align 4 1387; CHECK-NEXT: ret i32 [[A_C]] 1388; 1389entry: 1390 %call = call noalias ptr @malloc(i64 16) #2 1391 %g3 = getelementptr %struct.A, ptr %call, i32 0, i32 2 1392 %a_c = load i32, ptr %g3, align 4 1393 ret i32 %a_c 1394} 1395 1396define ptr @gep_of_gep_multiuse_const_and_const(ptr %p, i64 %idx) { 1397; CHECK-LABEL: @gep_of_gep_multiuse_const_and_const( 1398; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 8 1399; CHECK-NEXT: call void @use(ptr [[GEP1]]) 1400; CHECK-NEXT: [[GEP2:%.*]] = getelementptr i8, ptr [[P]], i64 12 1401; CHECK-NEXT: ret ptr [[GEP2]] 1402; 1403 %gep1 = getelementptr { i32, i32 }, ptr %p, i64 1 1404 call void @use(ptr %gep1) 1405 %gep2 = getelementptr { i32, i32 }, ptr %gep1, i64 0, i32 1 1406 ret ptr %gep2 1407} 1408 1409define ptr @gep_of_gep_multiuse_var_and_const(ptr %p, i64 %idx) { 1410; CHECK-LABEL: @gep_of_gep_multiuse_var_and_const( 1411; CHECK-NEXT: [[GEP1:%.*]] = getelementptr { i32, i32 }, ptr [[P:%.*]], i64 [[IDX:%.*]] 1412; CHECK-NEXT: call void @use(ptr [[GEP1]]) 1413; CHECK-NEXT: [[GEP2:%.*]] = getelementptr i8, ptr [[GEP1]], i64 4 1414; CHECK-NEXT: ret ptr [[GEP2]] 1415; 1416 %gep1 = getelementptr { i32, i32 }, ptr %p, i64 %idx 1417 call void @use(ptr %gep1) 1418 %gep2 = getelementptr { i32, i32 }, ptr %gep1, i64 0, i32 1 1419 ret ptr %gep2 1420} 1421 1422define ptr @gep_of_gep_multiuse_var_and_var(ptr %p, i64 %idx, i64 %idx2) { 1423; CHECK-LABEL: @gep_of_gep_multiuse_var_and_var( 1424; CHECK-NEXT: [[GEP1:%.*]] = getelementptr [4 x i32], ptr [[P:%.*]], i64 [[IDX:%.*]] 1425; CHECK-NEXT: call void @use(ptr [[GEP1]]) 1426; CHECK-NEXT: [[GEP2:%.*]] = getelementptr [4 x i32], ptr [[P]], i64 [[IDX]], i64 [[IDX2:%.*]] 1427; CHECK-NEXT: ret ptr [[GEP2]] 1428; 1429 %gep1 = getelementptr [4 x i32], ptr %p, i64 %idx 1430 call void @use(ptr %gep1) 1431 %gep2 = getelementptr [4 x i32], ptr %gep1, i64 0, i64 %idx2 1432 ret ptr %gep2 1433} 1434 1435@g_i32_di = global i32 0 1436@g_i32_e = external global i32 1437@g_i32_ew = extern_weak global i32 1438@g_0xi8_e = external global [0 x i8] 1439 1440define ptr @const_gep_global_di_i8_smaller() { 1441; CHECK-LABEL: @const_gep_global_di_i8_smaller( 1442; CHECK-NEXT: ret ptr getelementptr inbounds nuw (i8, ptr @g_i32_di, i64 3) 1443; 1444 ret ptr getelementptr (i8, ptr @g_i32_di, i64 3) 1445} 1446 1447define ptr @const_gep_global_di_i8_exact() { 1448; CHECK-LABEL: @const_gep_global_di_i8_exact( 1449; CHECK-NEXT: ret ptr getelementptr inbounds nuw (i8, ptr @g_i32_di, i64 4) 1450; 1451 ret ptr getelementptr (i8, ptr @g_i32_di, i64 4) 1452} 1453 1454define ptr @const_gep_global_di_i8_larger() { 1455; CHECK-LABEL: @const_gep_global_di_i8_larger( 1456; CHECK-NEXT: ret ptr getelementptr (i8, ptr @g_i32_di, i64 5) 1457; 1458 ret ptr getelementptr (i8, ptr @g_i32_di, i64 5) 1459} 1460 1461define ptr @const_gep_global_di_i64_larger() { 1462; CHECK-LABEL: @const_gep_global_di_i64_larger( 1463; CHECK-NEXT: ret ptr getelementptr (i8, ptr @g_i32_di, i64 8) 1464; 1465 ret ptr getelementptr (i64, ptr @g_i32_di, i64 1) 1466} 1467 1468define ptr @const_gep_global_e_smaller() { 1469; CHECK-LABEL: @const_gep_global_e_smaller( 1470; CHECK-NEXT: ret ptr getelementptr inbounds nuw (i8, ptr @g_i32_e, i64 3) 1471; 1472 ret ptr getelementptr (i8, ptr @g_i32_e, i64 3) 1473} 1474 1475define ptr @const_gep_global_e_exact() { 1476; CHECK-LABEL: @const_gep_global_e_exact( 1477; CHECK-NEXT: ret ptr getelementptr inbounds nuw (i8, ptr @g_i32_e, i64 4) 1478; 1479 ret ptr getelementptr (i8, ptr @g_i32_e, i64 4) 1480} 1481 1482define ptr @const_gep_global_e_larger() { 1483; CHECK-LABEL: @const_gep_global_e_larger( 1484; CHECK-NEXT: ret ptr getelementptr (i8, ptr @g_i32_e, i64 5) 1485; 1486 ret ptr getelementptr (i8, ptr @g_i32_e, i64 5) 1487} 1488 1489define ptr @const_gep_global_ew_smaller() { 1490; CHECK-LABEL: @const_gep_global_ew_smaller( 1491; CHECK-NEXT: ret ptr getelementptr (i8, ptr @g_i32_ew, i64 3) 1492; 1493 ret ptr getelementptr (i8, ptr @g_i32_ew, i64 3) 1494} 1495 1496define ptr @const_gep_global_ew_exact() { 1497; CHECK-LABEL: @const_gep_global_ew_exact( 1498; CHECK-NEXT: ret ptr getelementptr (i8, ptr @g_i32_ew, i64 4) 1499; 1500 ret ptr getelementptr (i8, ptr @g_i32_ew, i64 4) 1501} 1502 1503define ptr @const_gep_global_ew_larger() { 1504; CHECK-LABEL: @const_gep_global_ew_larger( 1505; CHECK-NEXT: ret ptr getelementptr (i8, ptr @g_i32_ew, i64 5) 1506; 1507 ret ptr getelementptr (i8, ptr @g_i32_ew, i64 5) 1508} 1509 1510define ptr @const_gep_0xi8_global() { 1511; CHECK-LABEL: @const_gep_0xi8_global( 1512; CHECK-NEXT: ret ptr getelementptr (i8, ptr @g_0xi8_e, i64 10) 1513; 1514 ret ptr getelementptr ([0 x i8], ptr @g_0xi8_e, i64 0, i64 10) 1515} 1516 1517define ptr @const_gep_chain(ptr %p, i64 %a) { 1518; CHECK-LABEL: @const_gep_chain( 1519; CHECK-NEXT: [[P1:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i64 [[A:%.*]] 1520; CHECK-NEXT: [[P4:%.*]] = getelementptr inbounds nuw i8, ptr [[P1]], i64 6 1521; CHECK-NEXT: ret ptr [[P4]] 1522; 1523 %p1 = getelementptr inbounds i8, ptr %p, i64 %a 1524 %p2 = getelementptr inbounds i8, ptr %p1, i64 1 1525 %p3 = getelementptr inbounds i8, ptr %p2, i64 2 1526 %p4 = getelementptr inbounds i8, ptr %p3, i64 3 1527 ret ptr %p4 1528} 1529 1530define ptr @gep_sdiv(ptr %p, i64 %off) { 1531; CHECK-LABEL: @gep_sdiv( 1532; CHECK-NEXT: [[PTR:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[OFF:%.*]] 1533; CHECK-NEXT: ret ptr [[PTR]] 1534; 1535 %index = sdiv exact i64 %off, 7 1536 %ptr = getelementptr %struct.C, ptr %p, i64 %index 1537 ret ptr %ptr 1538} 1539 1540define ptr @gep_udiv(ptr %p, i64 %off) { 1541; CHECK-LABEL: @gep_udiv( 1542; CHECK-NEXT: [[PTR:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[OFF:%.*]] 1543; CHECK-NEXT: ret ptr [[PTR]] 1544; 1545 %index = udiv exact i64 %off, 7 1546 %ptr = getelementptr %struct.C, ptr %p, i64 %index 1547 ret ptr %ptr 1548} 1549 1550define <2 x ptr> @gep_sdiv_vec(<2 x ptr> %p, <2 x i64> %off) { 1551; CHECK-LABEL: @gep_sdiv_vec( 1552; CHECK-NEXT: [[PTR:%.*]] = getelementptr i8, <2 x ptr> [[P:%.*]], <2 x i64> [[OFF:%.*]] 1553; CHECK-NEXT: ret <2 x ptr> [[PTR]] 1554; 1555 %index = sdiv exact <2 x i64> %off, <i64 7, i64 7> 1556 %ptr = getelementptr %struct.C, <2 x ptr> %p, <2 x i64> %index 1557 ret <2 x ptr> %ptr 1558} 1559 1560define ptr @gep_sdiv_inbounds(ptr %p, i64 %off) { 1561; CHECK-LABEL: @gep_sdiv_inbounds( 1562; CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i64 [[OFF:%.*]] 1563; CHECK-NEXT: ret ptr [[PTR]] 1564; 1565 %index = sdiv exact i64 %off, 7 1566 %ptr = getelementptr inbounds %struct.C, ptr %p, i64 %index 1567 ret ptr %ptr 1568} 1569 1570define ptr @gep_sdiv_nuw(ptr %p, i64 %off) { 1571; CHECK-LABEL: @gep_sdiv_nuw( 1572; CHECK-NEXT: [[PTR:%.*]] = getelementptr nuw i8, ptr [[P:%.*]], i64 [[OFF:%.*]] 1573; CHECK-NEXT: ret ptr [[PTR]] 1574; 1575 %index = sdiv exact i64 %off, 7 1576 %ptr = getelementptr nuw %struct.C, ptr %p, i64 %index 1577 ret ptr %ptr 1578} 1579 1580define ptr @gep_ashr(ptr %p, i64 %off) { 1581; CHECK-LABEL: @gep_ashr( 1582; CHECK-NEXT: [[PTR:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[OFF:%.*]] 1583; CHECK-NEXT: ret ptr [[PTR]] 1584; 1585 %index = ashr exact i64 %off, 2 1586 %ptr = getelementptr i32, ptr %p, i64 %index 1587 ret ptr %ptr 1588} 1589 1590define ptr @gep_lshr(ptr %p, i64 %off) { 1591; CHECK-LABEL: @gep_lshr( 1592; CHECK-NEXT: [[PTR:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[OFF:%.*]] 1593; CHECK-NEXT: ret ptr [[PTR]] 1594; 1595 %index = lshr exact i64 %off, 2 1596 %ptr = getelementptr i32, ptr %p, i64 %index 1597 ret ptr %ptr 1598} 1599 1600; Negative tests 1601 1602define ptr @gep_i8(ptr %p, i64 %off) { 1603; CHECK-LABEL: @gep_i8( 1604; CHECK-NEXT: [[PTR:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[OFF:%.*]] 1605; CHECK-NEXT: ret ptr [[PTR]] 1606; 1607 %ptr = getelementptr i8, ptr %p, i64 %off 1608 ret ptr %ptr 1609} 1610 1611define ptr @gep_sdiv_mismatched_size(ptr %p, i64 %off) { 1612; CHECK-LABEL: @gep_sdiv_mismatched_size( 1613; CHECK-NEXT: [[INDEX:%.*]] = sdiv exact i64 [[OFF:%.*]], 20 1614; CHECK-NEXT: [[PTR:%.*]] = getelementptr [[STRUCT_C:%.*]], ptr [[P:%.*]], i64 [[INDEX]] 1615; CHECK-NEXT: ret ptr [[PTR]] 1616; 1617 %index = sdiv exact i64 %off, 20 1618 %ptr = getelementptr %struct.C, ptr %p, i64 %index 1619 ret ptr %ptr 1620} 1621 1622define ptr @gep_udiv_mismatched_size(ptr %p, i64 %off) { 1623; CHECK-LABEL: @gep_udiv_mismatched_size( 1624; CHECK-NEXT: [[INDEX:%.*]] = udiv exact i64 [[OFF:%.*]], 20 1625; CHECK-NEXT: [[PTR:%.*]] = getelementptr [[STRUCT_C:%.*]], ptr [[P:%.*]], i64 [[INDEX]] 1626; CHECK-NEXT: ret ptr [[PTR]] 1627; 1628 %index = udiv exact i64 %off, 20 1629 %ptr = getelementptr %struct.C, ptr %p, i64 %index 1630 ret ptr %ptr 1631} 1632 1633define ptr @gep_sdiv_without_exact(ptr %p, i64 %off) { 1634; CHECK-LABEL: @gep_sdiv_without_exact( 1635; CHECK-NEXT: [[INDEX:%.*]] = sdiv i64 [[OFF:%.*]], 7 1636; CHECK-NEXT: [[PTR:%.*]] = getelementptr [[STRUCT_C:%.*]], ptr [[P:%.*]], i64 [[INDEX]] 1637; CHECK-NEXT: ret ptr [[PTR]] 1638; 1639 %index = sdiv i64 %off, 7 1640 %ptr = getelementptr %struct.C, ptr %p, i64 %index 1641 ret ptr %ptr 1642} 1643 1644define ptr @gep_udiv_without_exact(ptr %p, i64 %off) { 1645; CHECK-LABEL: @gep_udiv_without_exact( 1646; CHECK-NEXT: [[INDEX:%.*]] = udiv i64 [[OFF:%.*]], 7 1647; CHECK-NEXT: [[PTR:%.*]] = getelementptr [[STRUCT_C:%.*]], ptr [[P:%.*]], i64 [[INDEX]] 1648; CHECK-NEXT: ret ptr [[PTR]] 1649; 1650 %index = udiv i64 %off, 7 1651 %ptr = getelementptr %struct.C, ptr %p, i64 %index 1652 ret ptr %ptr 1653} 1654 1655define ptr @gep_ashr_without_exact(ptr %p, i64 %off) { 1656; CHECK-LABEL: @gep_ashr_without_exact( 1657; CHECK-NEXT: [[INDEX:%.*]] = ashr i64 [[OFF:%.*]], 2 1658; CHECK-NEXT: [[PTR:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[INDEX]] 1659; CHECK-NEXT: ret ptr [[PTR]] 1660; 1661 %index = ashr i64 %off, 2 1662 %ptr = getelementptr i32, ptr %p, i64 %index 1663 ret ptr %ptr 1664} 1665 1666define ptr @gep_lshr_without_exact(ptr %p, i64 %off) { 1667; CHECK-LABEL: @gep_lshr_without_exact( 1668; CHECK-NEXT: [[INDEX:%.*]] = lshr i64 [[OFF:%.*]], 2 1669; CHECK-NEXT: [[PTR:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[INDEX]] 1670; CHECK-NEXT: ret ptr [[PTR]] 1671; 1672 %index = lshr i64 %off, 2 1673 %ptr = getelementptr i32, ptr %p, i64 %index 1674 ret ptr %ptr 1675} 1676 1677define i1 @test_only_used_by_icmp(ptr %a, ptr %b, ptr %c) { 1678; CHECK-LABEL: @test_only_used_by_icmp( 1679; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[B:%.*]], [[C:%.*]] 1680; CHECK-NEXT: ret i1 [[CMP]] 1681; 1682 %pa = ptrtoint ptr %a to i64 1683 %pb = ptrtoint ptr %b to i64 1684 %sub = sub i64 %pb, %pa 1685 %gep = getelementptr i8, ptr %a, i64 %sub 1686 %cmp = icmp eq ptr %gep, %c 1687 ret i1 %cmp 1688} 1689 1690define i64 @test_only_used_by_ptrtoint(ptr %a, ptr %b) { 1691; CHECK-LABEL: @test_only_used_by_ptrtoint( 1692; CHECK-NEXT: [[VAL:%.*]] = ptrtoint ptr [[B:%.*]] to i64 1693; CHECK-NEXT: ret i64 [[VAL]] 1694; 1695 %pa = ptrtoint ptr %a to i64 1696 %pb = ptrtoint ptr %b to i64 1697 %sub = sub i64 %pb, %pa 1698 %gep = getelementptr i8, ptr %a, i64 %sub 1699 %val = ptrtoint ptr %gep to i64 1700 ret i64 %val 1701} 1702 1703define i64 @test_used_by_both(ptr %a, ptr %b, ptr %c) { 1704; CHECK-LABEL: @test_used_by_both( 1705; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[B:%.*]], [[C:%.*]] 1706; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 1707; CHECK: if.then: 1708; CHECK-NEXT: [[VAL:%.*]] = ptrtoint ptr [[B]] to i64 1709; CHECK-NEXT: ret i64 [[VAL]] 1710; CHECK: if.else: 1711; CHECK-NEXT: ret i64 0 1712; 1713 %pa = ptrtoint ptr %a to i64 1714 %pb = ptrtoint ptr %b to i64 1715 %sub = sub i64 %pb, %pa 1716 %gep = getelementptr i8, ptr %a, i64 %sub 1717 %cmp = icmp eq ptr %gep, %c 1718 br i1 %cmp, label %if.then, label %if.else 1719if.then: 1720 %val = ptrtoint ptr %gep to i64 1721 ret i64 %val 1722if.else: 1723 ret i64 0 1724} 1725 1726; Negative tests 1727 1728define i64 @test_used_by_both_invalid(ptr %a, ptr %b, ptr %c) { 1729; CHECK-LABEL: @test_used_by_both_invalid( 1730; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[B:%.*]], [[C:%.*]] 1731; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 1732; CHECK: if.then: 1733; CHECK-NEXT: [[PB:%.*]] = ptrtoint ptr [[B]] to i64 1734; CHECK-NEXT: [[PA:%.*]] = ptrtoint ptr [[A:%.*]] to i64 1735; CHECK-NEXT: [[SUB:%.*]] = sub i64 [[PB]], [[PA]] 1736; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[A]], i64 [[SUB]] 1737; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[GEP]], align 8 1738; CHECK-NEXT: ret i64 [[VAL]] 1739; CHECK: if.else: 1740; CHECK-NEXT: ret i64 0 1741; 1742 %pa = ptrtoint ptr %a to i64 1743 %pb = ptrtoint ptr %b to i64 1744 %sub = sub i64 %pb, %pa 1745 %gep = getelementptr i8, ptr %a, i64 %sub 1746 %cmp = icmp eq ptr %gep, %c 1747 br i1 %cmp, label %if.then, label %if.else 1748if.then: 1749 %val = load i64, ptr %gep, align 8 1750 ret i64 %val 1751if.else: 1752 ret i64 0 1753} 1754 1755 1756@g = external global i8 1757 1758define ptr @constexpr_gep_of_gep_with_narrow_type() { 1759; CHECK-LABEL: @constexpr_gep_of_gep_with_narrow_type( 1760; CHECK-NEXT: ret ptr getelementptr (i8, ptr @g, i64 254) 1761; 1762 ret ptr getelementptr (i8, ptr getelementptr (i8, ptr @g, i8 127), i8 127) 1763} 1764 1765define ptr @gep_to_i8_nusw_nuw(ptr %p) { 1766; CHECK-LABEL: @gep_to_i8_nusw_nuw( 1767; CHECK-NEXT: [[GEP:%.*]] = getelementptr nusw nuw i8, ptr [[P:%.*]], i64 4 1768; CHECK-NEXT: ret ptr [[GEP]] 1769; 1770 %gep = getelementptr nusw nuw i32, ptr %p, i64 1 1771 ret ptr %gep 1772} 1773 1774define ptr @gep_sel_const(i1 %c) { 1775; CHECK-LABEL: @gep_sel_const( 1776; CHECK-NEXT: [[GEP:%.*]] = select i1 [[C:%.*]], ptr getelementptr (i8, ptr @A, i64 5), ptr getelementptr (i8, ptr @B, i64 5) 1777; CHECK-NEXT: ret ptr [[GEP]] 1778; 1779 %sel = select i1 %c, ptr @A, ptr @B 1780 %gep = getelementptr i8, ptr %sel, i64 5 1781 ret ptr %gep 1782} 1783 1784define ptr @gep_sel_const_nuw(i1 %c) { 1785; CHECK-LABEL: @gep_sel_const_nuw( 1786; CHECK-NEXT: [[GEP:%.*]] = select i1 [[C:%.*]], ptr getelementptr nuw (i8, ptr @A, i64 5), ptr getelementptr nuw (i8, ptr @B, i64 5) 1787; CHECK-NEXT: ret ptr [[GEP]] 1788; 1789 %sel = select i1 %c, ptr @A, ptr @B 1790 %gep = getelementptr nuw i8, ptr %sel, i64 5 1791 ret ptr %gep 1792} 1793 1794define ptr @gep_of_udiv(ptr %p, i64 %x) { 1795; CHECK-LABEL: @gep_of_udiv( 1796; CHECK-NEXT: [[TMP1:%.*]] = udiv exact i64 [[X:%.*]], 3 1797; CHECK-NEXT: [[R:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[TMP1]] 1798; CHECK-NEXT: ret ptr [[R]] 1799; 1800 %idx = udiv exact i64 %x, 12 1801 %r = getelementptr i32, ptr %p, i64 %idx 1802 ret ptr %r 1803} 1804 1805define ptr @gep_of_udiv_fail_not_divisible(ptr %p, i64 %x) { 1806; CHECK-LABEL: @gep_of_udiv_fail_not_divisible( 1807; CHECK-NEXT: [[IDX:%.*]] = udiv exact i64 [[X:%.*]], 13 1808; CHECK-NEXT: [[R:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[IDX]] 1809; CHECK-NEXT: ret ptr [[R]] 1810; 1811 %idx = udiv exact i64 %x, 13 1812 %r = getelementptr i32, ptr %p, i64 %idx 1813 ret ptr %r 1814} 1815 1816 1817define ptr @gep_of_sdiv(ptr %p, i64 %x) { 1818; CHECK-LABEL: @gep_of_sdiv( 1819; CHECK-NEXT: [[TMP1:%.*]] = sdiv exact i64 [[X:%.*]], -9 1820; CHECK-NEXT: [[R:%.*]] = getelementptr nusw nuw i8, ptr [[P:%.*]], i64 [[TMP1]] 1821; CHECK-NEXT: ret ptr [[R]] 1822; 1823 %idx = sdiv exact i64 %x, -36 1824 %r = getelementptr nusw nuw i32, ptr %p, i64 %idx 1825 ret ptr %r 1826} 1827 1828 1829define ptr @gep_of_sdiv_fail_not_divisible(ptr %p, i64 %x) { 1830; CHECK-LABEL: @gep_of_sdiv_fail_not_divisible( 1831; CHECK-NEXT: [[IDX:%.*]] = sdiv exact i64 [[X:%.*]], -35 1832; CHECK-NEXT: [[R:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[IDX]] 1833; CHECK-NEXT: ret ptr [[R]] 1834; 1835 %idx = sdiv exact i64 %x, -35 1836 %r = getelementptr i32, ptr %p, i64 %idx 1837 ret ptr %r 1838} 1839 1840define ptr @gep_of_sdiv_fail_ub(ptr %p, i64 %x) { 1841; CHECK-LABEL: @gep_of_sdiv_fail_ub( 1842; CHECK-NEXT: [[IDX:%.*]] = sdiv i64 [[X:%.*]], -4 1843; CHECK-NEXT: [[R:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[IDX]] 1844; CHECK-NEXT: ret ptr [[R]] 1845; 1846 %idx = sdiv i64 %x, -4 1847 %r = getelementptr i32, ptr %p, i64 %idx 1848 ret ptr %r 1849} 1850 1851define ptr @gep_of_lshr(ptr %p, i64 %x) { 1852; CHECK-LABEL: @gep_of_lshr( 1853; CHECK-NEXT: [[TMP1:%.*]] = lshr exact i64 [[X:%.*]], 1 1854; CHECK-NEXT: [[R:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[TMP1]] 1855; CHECK-NEXT: ret ptr [[R]] 1856; 1857 %idx = lshr exact i64 %x, 3 1858 %r = getelementptr i32, ptr %p, i64 %idx 1859 ret ptr %r 1860} 1861 1862define ptr @gep_of_ashr(ptr %p, i64 %x) { 1863; CHECK-LABEL: @gep_of_ashr( 1864; CHECK-NEXT: [[TMP1:%.*]] = ashr exact i64 [[X:%.*]], 1 1865; CHECK-NEXT: [[R:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i64 [[TMP1]] 1866; CHECK-NEXT: ret ptr [[R]] 1867; 1868 %idx = ashr exact i64 %x, 3 1869 %r = getelementptr inbounds i32, ptr %p, i64 %idx 1870 ret ptr %r 1871} 1872 1873define ptr @gep_of_ashr_fail_multiuse(ptr %p, i64 %x) { 1874; CHECK-LABEL: @gep_of_ashr_fail_multiuse( 1875; CHECK-NEXT: [[IDX:%.*]] = ashr exact i64 [[X:%.*]], 3 1876; CHECK-NEXT: call void @use.i64(i64 [[IDX]]) 1877; CHECK-NEXT: [[R:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 [[IDX]] 1878; CHECK-NEXT: ret ptr [[R]] 1879; 1880 %idx = ashr exact i64 %x, 3 1881 call void @use.i64(i64 %idx) 1882 %r = getelementptr inbounds i32, ptr %p, i64 %idx 1883 ret ptr %r 1884} 1885 1886define ptr @gep_of_lshr_fail_missing_exact(ptr %p, i64 %x) { 1887; CHECK-LABEL: @gep_of_lshr_fail_missing_exact( 1888; CHECK-NEXT: [[IDX:%.*]] = lshr i64 [[X:%.*]], 3 1889; CHECK-NEXT: [[R:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[IDX]] 1890; CHECK-NEXT: ret ptr [[R]] 1891; 1892 %idx = lshr i64 %x, 3 1893 %r = getelementptr i32, ptr %p, i64 %idx 1894 ret ptr %r 1895} 1896 1897define ptr @gep_of_ashr_fail_not_divisible(ptr %p, i64 %x) { 1898; CHECK-LABEL: @gep_of_ashr_fail_not_divisible( 1899; CHECK-NEXT: [[IDX:%.*]] = ashr exact i64 [[X:%.*]], 1 1900; CHECK-NEXT: [[R:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[IDX]] 1901; CHECK-NEXT: ret ptr [[R]] 1902; 1903 %idx = ashr exact i64 %x, 1 1904 %r = getelementptr i32, ptr %p, i64 %idx 1905 ret ptr %r 1906} 1907 1908define ptr @gep_merge_not_nuw(ptr %p, i64 %idx) { 1909; CHECK-LABEL: @gep_merge_not_nuw( 1910; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i64 -1 1911; CHECK-NEXT: ret ptr [[GEP]] 1912; 1913 %idx.neg = sub i64 0, %idx 1914 %add = add i64 %idx, -1 1915 %gep1 = getelementptr inbounds i8, ptr %p, i64 %idx.neg 1916 %gep = getelementptr inbounds nuw i8, ptr %gep1, i64 %add 1917 ret ptr %gep 1918} 1919 1920define ptr @gep_merge_nuw(ptr %p, i64 %x, i64 %y) { 1921; CHECK-LABEL: @gep_merge_nuw( 1922; CHECK-NEXT: [[GEP:%.*]] = getelementptr nuw i8, ptr [[P:%.*]], i64 [[Y:%.*]] 1923; CHECK-NEXT: ret ptr [[GEP]] 1924; 1925 %sub = sub i64 %y, %x 1926 %gep1 = getelementptr nuw i8, ptr %p, i64 %x 1927 %gep = getelementptr nuw i8, ptr %gep1, i64 %sub 1928 ret ptr %gep 1929} 1930 1931define ptr @gep_merge_nuw_only_one1(ptr %p, i64 %x, i64 %y) { 1932; CHECK-LABEL: @gep_merge_nuw_only_one1( 1933; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[Y:%.*]] 1934; CHECK-NEXT: ret ptr [[GEP]] 1935; 1936 %sub = sub i64 %y, %x 1937 %gep1 = getelementptr i8, ptr %p, i64 %x 1938 %gep = getelementptr nuw i8, ptr %gep1, i64 %sub 1939 ret ptr %gep 1940} 1941 1942define ptr @gep_merge_nuw_only_one2(ptr %p, i64 %x, i64 %y) { 1943; CHECK-LABEL: @gep_merge_nuw_only_one2( 1944; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[Y:%.*]] 1945; CHECK-NEXT: ret ptr [[GEP]] 1946; 1947 %sub = sub i64 %y, %x 1948 %gep1 = getelementptr nuw i8, ptr %p, i64 %x 1949 %gep = getelementptr i8, ptr %gep1, i64 %sub 1950 ret ptr %gep 1951} 1952 1953; Cannot preserve nusw, unless we know that the addition x + (y-x) 1954; does not overflow. 1955define ptr @gep_merge_nusw(ptr %p, i64 %x, i64 %y) { 1956; CHECK-LABEL: @gep_merge_nusw( 1957; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[Y:%.*]] 1958; CHECK-NEXT: ret ptr [[GEP]] 1959; 1960 %sub = sub i64 %y, %x 1961 %gep1 = getelementptr nusw i8, ptr %p, i64 %x 1962 %gep = getelementptr nusw i8, ptr %gep1, i64 %sub 1963 ret ptr %gep 1964} 1965 1966define ptr @gep_merge_nuw_add_zero(ptr %p, i64 %idx, i64 %idx2) { 1967; CHECK-LABEL: @gep_merge_nuw_add_zero( 1968; CHECK-NEXT: [[GEP:%.*]] = getelementptr nuw [2 x i32], ptr [[P:%.*]], i64 [[IDX:%.*]], i64 [[IDX2:%.*]] 1969; CHECK-NEXT: ret ptr [[GEP]] 1970; 1971 %gep1 = getelementptr nuw [2 x i32], ptr %p, i64 %idx 1972 %gep = getelementptr nuw [2 x i32], ptr %gep1, i64 0, i64 %idx2 1973 ret ptr %gep 1974} 1975 1976; Cannot preserve nusw, even if the merge only involves an add with a zero 1977; index. This is because the whole offset calculation is required to be nsw 1978; after the merge. 1979define ptr @gep_merge_nusw_add_zero(ptr %p, i64 %idx, i64 %idx2) { 1980; CHECK-LABEL: @gep_merge_nusw_add_zero( 1981; CHECK-NEXT: [[GEP:%.*]] = getelementptr [2 x i32], ptr [[P:%.*]], i64 [[IDX:%.*]], i64 [[IDX2:%.*]] 1982; CHECK-NEXT: ret ptr [[GEP]] 1983; 1984 %gep1 = getelementptr nusw [2 x i32], ptr %p, i64 %idx 1985 %gep = getelementptr nusw [2 x i32], ptr %gep1, i64 0, i64 %idx2 1986 ret ptr %gep 1987} 1988 1989define ptr @gep_merge_nuw_const(ptr %p, i64 %idx, i64 %idx2) { 1990; CHECK-LABEL: @gep_merge_nuw_const( 1991; CHECK-NEXT: [[GEP:%.*]] = getelementptr nuw [2 x i32], ptr [[P:%.*]], i64 [[IDX:%.*]], i64 1 1992; CHECK-NEXT: ret ptr [[GEP]] 1993; 1994 %gep1 = getelementptr nuw [2 x i32], ptr %p, i64 %idx 1995 %gep = getelementptr nuw i8, ptr %gep1, i64 4 1996 ret ptr %gep 1997} 1998 1999define ptr @gep_merge_nuw_const_neg(ptr %p, i64 %idx, i64 %idx2) { 2000; CHECK-LABEL: @gep_merge_nuw_const_neg( 2001; CHECK-NEXT: [[GEP1:%.*]] = getelementptr nuw [2 x i32], ptr [[P:%.*]], i64 [[IDX:%.*]] 2002; CHECK-NEXT: [[GEP:%.*]] = getelementptr nuw i8, ptr [[GEP1]], i64 -4 2003; CHECK-NEXT: ret ptr [[GEP]] 2004; 2005 %gep1 = getelementptr nuw [2 x i32], ptr %p, i64 %idx 2006 %gep = getelementptr nuw i8, ptr %gep1, i64 -4 2007 ret ptr %gep 2008} 2009 2010; Cannot preserve nusw, because we don't know that the new offset calculation 2011; does not overflow. 2012define ptr @gep_merge_nusw_const(ptr %p, i64 %idx, i64 %idx2) { 2013; CHECK-LABEL: @gep_merge_nusw_const( 2014; CHECK-NEXT: [[GEP:%.*]] = getelementptr [2 x i32], ptr [[P:%.*]], i64 [[IDX:%.*]], i64 1 2015; CHECK-NEXT: ret ptr [[GEP]] 2016; 2017 %gep1 = getelementptr nusw [2 x i32], ptr %p, i64 %idx 2018 %gep = getelementptr nusw i8, ptr %gep1, i64 4 2019 ret ptr %gep 2020} 2021 2022 2023!0 = !{!"branch_weights", i32 2, i32 10} 2024