1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -instcombine < %s | FileCheck %s 3 4target datalayout = "e-p:64:64:64-p1:16:16:16-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" 5 6define i64 @test_inbounds([0 x i32]* %base, i64 %idx) { 7; CHECK-LABEL: @test_inbounds( 8; CHECK-NEXT: [[P2_IDX:%.*]] = shl nsw i64 [[IDX:%.*]], 2 9; CHECK-NEXT: ret i64 [[P2_IDX]] 10; 11 %p1 = getelementptr inbounds [0 x i32], [0 x i32]* %base, i64 0, i64 0 12 %p2 = getelementptr inbounds [0 x i32], [0 x i32]* %base, i64 0, i64 %idx 13 %i1 = ptrtoint i32* %p1 to i64 14 %i2 = ptrtoint i32* %p2 to i64 15 %d = sub i64 %i2, %i1 16 ret i64 %d 17} 18 19define i64 @test_partial_inbounds1([0 x i32]* %base, i64 %idx) { 20; CHECK-LABEL: @test_partial_inbounds1( 21; CHECK-NEXT: [[P2_IDX:%.*]] = shl i64 [[IDX:%.*]], 2 22; CHECK-NEXT: ret i64 [[P2_IDX]] 23; 24 %p1 = getelementptr inbounds [0 x i32], [0 x i32]* %base, i64 0, i64 0 25 %p2 = getelementptr [0 x i32], [0 x i32]* %base, i64 0, i64 %idx 26 %i1 = ptrtoint i32* %p1 to i64 27 %i2 = ptrtoint i32* %p2 to i64 28 %d = sub i64 %i2, %i1 29 ret i64 %d 30} 31 32define i64 @test_partial_inbounds2([0 x i32]* %base, i64 %idx) { 33; CHECK-LABEL: @test_partial_inbounds2( 34; CHECK-NEXT: [[P2_IDX:%.*]] = shl nsw i64 [[IDX:%.*]], 2 35; CHECK-NEXT: ret i64 [[P2_IDX]] 36; 37 %p1 = getelementptr [0 x i32], [0 x i32]* %base, i64 0, i64 0 38 %p2 = getelementptr inbounds [0 x i32], [0 x i32]* %base, i64 0, i64 %idx 39 %i1 = ptrtoint i32* %p1 to i64 40 %i2 = ptrtoint i32* %p2 to i64 41 %d = sub i64 %i2, %i1 42 ret i64 %d 43} 44 45define i64 @test_inbounds_nuw([0 x i32]* %base, i64 %idx) { 46; CHECK-LABEL: @test_inbounds_nuw( 47; CHECK-NEXT: [[P2_IDX:%.*]] = shl nuw nsw i64 [[IDX:%.*]], 2 48; CHECK-NEXT: ret i64 [[P2_IDX]] 49; 50 %p1 = getelementptr inbounds [0 x i32], [0 x i32]* %base, i64 0, i64 0 51 %p2 = getelementptr inbounds [0 x i32], [0 x i32]* %base, i64 0, i64 %idx 52 %i1 = ptrtoint i32* %p1 to i64 53 %i2 = ptrtoint i32* %p2 to i64 54 %d = sub nuw i64 %i2, %i1 55 ret i64 %d 56} 57 58define i64 @test_nuw([0 x i32]* %base, i64 %idx) { 59; CHECK-LABEL: @test_nuw( 60; CHECK-NEXT: [[P2_IDX:%.*]] = shl i64 [[IDX:%.*]], 2 61; CHECK-NEXT: ret i64 [[P2_IDX]] 62; 63 %p1 = getelementptr [0 x i32], [0 x i32]* %base, i64 0, i64 0 64 %p2 = getelementptr [0 x i32], [0 x i32]* %base, i64 0, i64 %idx 65 %i1 = ptrtoint i32* %p1 to i64 66 %i2 = ptrtoint i32* %p2 to i64 67 %d = sub nuw i64 %i2, %i1 68 ret i64 %d 69} 70 71define i32 @test_inbounds_nuw_trunc([0 x i32]* %base, i64 %idx) { 72; CHECK-LABEL: @test_inbounds_nuw_trunc( 73; CHECK-NEXT: [[IDX_TR:%.*]] = trunc i64 [[IDX:%.*]] to i32 74; CHECK-NEXT: [[TMP1:%.*]] = shl i32 [[IDX_TR]], 2 75; CHECK-NEXT: ret i32 [[TMP1]] 76; 77 %p1 = getelementptr inbounds [0 x i32], [0 x i32]* %base, i64 0, i64 0 78 %p2 = getelementptr inbounds [0 x i32], [0 x i32]* %base, i64 0, i64 %idx 79 %i1 = ptrtoint i32* %p1 to i64 80 %i2 = ptrtoint i32* %p2 to i64 81 %t1 = trunc i64 %i1 to i32 82 %t2 = trunc i64 %i2 to i32 83 %d = sub nuw i32 %t2, %t1 84 ret i32 %d 85} 86 87define i64 @test_inbounds_nuw_swapped([0 x i32]* %base, i64 %idx) { 88; CHECK-LABEL: @test_inbounds_nuw_swapped( 89; CHECK-NEXT: [[P2_IDX_NEG:%.*]] = mul i64 [[IDX:%.*]], -4 90; CHECK-NEXT: ret i64 [[P2_IDX_NEG]] 91; 92 %p1 = getelementptr inbounds [0 x i32], [0 x i32]* %base, i64 0, i64 0 93 %p2 = getelementptr inbounds [0 x i32], [0 x i32]* %base, i64 0, i64 %idx 94 %i1 = ptrtoint i32* %p2 to i64 95 %i2 = ptrtoint i32* %p1 to i64 96 %d = sub nuw i64 %i2, %i1 97 ret i64 %d 98} 99 100define i64 @test_inbounds1_nuw_swapped([0 x i32]* %base, i64 %idx) { 101; CHECK-LABEL: @test_inbounds1_nuw_swapped( 102; CHECK-NEXT: [[P2_IDX_NEG:%.*]] = mul i64 [[IDX:%.*]], -4 103; CHECK-NEXT: ret i64 [[P2_IDX_NEG]] 104; 105 %p1 = getelementptr inbounds [0 x i32], [0 x i32]* %base, i64 0, i64 0 106 %p2 = getelementptr [0 x i32], [0 x i32]* %base, i64 0, i64 %idx 107 %i1 = ptrtoint i32* %p2 to i64 108 %i2 = ptrtoint i32* %p1 to i64 109 %d = sub nuw i64 %i2, %i1 110 ret i64 %d 111} 112 113define i64 @test_inbounds2_nuw_swapped([0 x i32]* %base, i64 %idx) { 114; CHECK-LABEL: @test_inbounds2_nuw_swapped( 115; CHECK-NEXT: [[P2_IDX_NEG:%.*]] = mul i64 [[IDX:%.*]], -4 116; CHECK-NEXT: ret i64 [[P2_IDX_NEG]] 117; 118 %p1 = getelementptr [0 x i32], [0 x i32]* %base, i64 0, i64 0 119 %p2 = getelementptr inbounds [0 x i32], [0 x i32]* %base, i64 0, i64 %idx 120 %i1 = ptrtoint i32* %p2 to i64 121 %i2 = ptrtoint i32* %p1 to i64 122 %d = sub nuw i64 %i2, %i1 123 ret i64 %d 124} 125 126define i64 @test_inbounds_two_gep([0 x i32]* %base, i64 %idx, i64 %idx2) { 127; CHECK-LABEL: @test_inbounds_two_gep( 128; CHECK-NEXT: [[TMP1:%.*]] = sub nsw i64 [[IDX2:%.*]], [[IDX:%.*]] 129; CHECK-NEXT: [[GEPDIFF:%.*]] = shl nsw i64 [[TMP1]], 2 130; CHECK-NEXT: ret i64 [[GEPDIFF]] 131; 132 %p1 = getelementptr inbounds [0 x i32], [0 x i32]* %base, i64 0, i64 %idx 133 %p2 = getelementptr inbounds [0 x i32], [0 x i32]* %base, i64 0, i64 %idx2 134 %i1 = ptrtoint i32* %p1 to i64 135 %i2 = ptrtoint i32* %p2 to i64 136 %d = sub i64 %i2, %i1 137 ret i64 %d 138} 139 140define i64 @test_inbounds_nsw_two_gep([0 x i32]* %base, i64 %idx, i64 %idx2) { 141; CHECK-LABEL: @test_inbounds_nsw_two_gep( 142; CHECK-NEXT: [[TMP1:%.*]] = sub nsw i64 [[IDX2:%.*]], [[IDX:%.*]] 143; CHECK-NEXT: [[GEPDIFF:%.*]] = shl nsw i64 [[TMP1]], 2 144; CHECK-NEXT: ret i64 [[GEPDIFF]] 145; 146 %p1 = getelementptr inbounds [0 x i32], [0 x i32]* %base, i64 0, i64 %idx 147 %p2 = getelementptr inbounds [0 x i32], [0 x i32]* %base, i64 0, i64 %idx2 148 %i1 = ptrtoint i32* %p1 to i64 149 %i2 = ptrtoint i32* %p2 to i64 150 %d = sub nsw i64 %i2, %i1 151 ret i64 %d 152} 153 154define i64 @test_inbounds_nuw_two_gep([0 x i32]* %base, i64 %idx, i64 %idx2) { 155; CHECK-LABEL: @test_inbounds_nuw_two_gep( 156; CHECK-NEXT: [[TMP1:%.*]] = sub nsw i64 [[IDX2:%.*]], [[IDX:%.*]] 157; CHECK-NEXT: [[GEPDIFF:%.*]] = shl nsw i64 [[TMP1]], 2 158; CHECK-NEXT: ret i64 [[GEPDIFF]] 159; 160 %p1 = getelementptr inbounds [0 x i32], [0 x i32]* %base, i64 0, i64 %idx 161 %p2 = getelementptr inbounds [0 x i32], [0 x i32]* %base, i64 0, i64 %idx2 162 %i1 = ptrtoint i32* %p1 to i64 163 %i2 = ptrtoint i32* %p2 to i64 164 %d = sub nuw i64 %i2, %i1 165 ret i64 %d 166} 167 168define i64 @test_inbounds_nuw_multi_index([0 x [2 x i32]]* %base, i64 %idx, i64 %idx2) { 169; CHECK-LABEL: @test_inbounds_nuw_multi_index( 170; CHECK-NEXT: [[P2_IDX:%.*]] = shl nsw i64 [[IDX:%.*]], 3 171; CHECK-NEXT: [[P2_IDX1:%.*]] = shl nsw i64 [[IDX2:%.*]], 2 172; CHECK-NEXT: [[P2_OFFS:%.*]] = add nsw i64 [[P2_IDX]], [[P2_IDX1]] 173; CHECK-NEXT: ret i64 [[P2_OFFS]] 174; 175 %p1 = getelementptr inbounds [0 x [2 x i32]], [0 x [2 x i32]]* %base, i64 0, i64 0, i64 0 176 %p2 = getelementptr inbounds [0 x [2 x i32]], [0 x [2 x i32]]* %base, i64 0, i64 %idx, i64 %idx2 177 %i1 = ptrtoint i32* %p1 to i64 178 %i2 = ptrtoint i32* %p2 to i64 179 %d = sub nuw i64 %i2, %i1 180 ret i64 %d 181} 182 183; rdar://7362831 184define i32 @test23(i8* %P, i64 %A){ 185; CHECK-LABEL: @test23( 186; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[A:%.*]] to i32 187; CHECK-NEXT: ret i32 [[TMP1]] 188; 189 %B = getelementptr inbounds i8, i8* %P, i64 %A 190 %C = ptrtoint i8* %B to i64 191 %D = trunc i64 %C to i32 192 %E = ptrtoint i8* %P to i64 193 %F = trunc i64 %E to i32 194 %G = sub i32 %D, %F 195 ret i32 %G 196} 197 198define i8 @test23_as1(i8 addrspace(1)* %P, i16 %A) { 199; CHECK-LABEL: @test23_as1( 200; CHECK-NEXT: [[TMP1:%.*]] = trunc i16 [[A:%.*]] to i8 201; CHECK-NEXT: ret i8 [[TMP1]] 202; 203 %B = getelementptr inbounds i8, i8 addrspace(1)* %P, i16 %A 204 %C = ptrtoint i8 addrspace(1)* %B to i16 205 %D = trunc i16 %C to i8 206 %E = ptrtoint i8 addrspace(1)* %P to i16 207 %F = trunc i16 %E to i8 208 %G = sub i8 %D, %F 209 ret i8 %G 210} 211 212define i64 @test24(i8* %P, i64 %A){ 213; CHECK-LABEL: @test24( 214; CHECK-NEXT: ret i64 [[A:%.*]] 215; 216 %B = getelementptr inbounds i8, i8* %P, i64 %A 217 %C = ptrtoint i8* %B to i64 218 %E = ptrtoint i8* %P to i64 219 %G = sub i64 %C, %E 220 ret i64 %G 221} 222 223define i16 @test24_as1(i8 addrspace(1)* %P, i16 %A) { 224; CHECK-LABEL: @test24_as1( 225; CHECK-NEXT: ret i16 [[A:%.*]] 226; 227 %B = getelementptr inbounds i8, i8 addrspace(1)* %P, i16 %A 228 %C = ptrtoint i8 addrspace(1)* %B to i16 229 %E = ptrtoint i8 addrspace(1)* %P to i16 230 %G = sub i16 %C, %E 231 ret i16 %G 232} 233 234define i64 @test24a(i8* %P, i64 %A){ 235; CHECK-LABEL: @test24a( 236; CHECK-NEXT: [[DIFF_NEG:%.*]] = sub i64 0, [[A:%.*]] 237; CHECK-NEXT: ret i64 [[DIFF_NEG]] 238; 239 %B = getelementptr inbounds i8, i8* %P, i64 %A 240 %C = ptrtoint i8* %B to i64 241 %E = ptrtoint i8* %P to i64 242 %G = sub i64 %E, %C 243 ret i64 %G 244} 245 246define i16 @test24a_as1(i8 addrspace(1)* %P, i16 %A) { 247; CHECK-LABEL: @test24a_as1( 248; CHECK-NEXT: [[DIFF_NEG:%.*]] = sub i16 0, [[A:%.*]] 249; CHECK-NEXT: ret i16 [[DIFF_NEG]] 250; 251 %B = getelementptr inbounds i8, i8 addrspace(1)* %P, i16 %A 252 %C = ptrtoint i8 addrspace(1)* %B to i16 253 %E = ptrtoint i8 addrspace(1)* %P to i16 254 %G = sub i16 %E, %C 255 ret i16 %G 256} 257 258@Arr = external global [42 x i16] 259 260define i64 @test24b(i8* %P, i64 %A){ 261; CHECK-LABEL: @test24b( 262; CHECK-NEXT: [[B_IDX:%.*]] = shl nsw i64 [[A:%.*]], 1 263; CHECK-NEXT: ret i64 [[B_IDX]] 264; 265 %B = getelementptr inbounds [42 x i16], [42 x i16]* @Arr, i64 0, i64 %A 266 %C = ptrtoint i16* %B to i64 267 %G = sub i64 %C, ptrtoint ([42 x i16]* @Arr to i64) 268 ret i64 %G 269} 270 271define i64 @test25(i8* %P, i64 %A){ 272; CHECK-LABEL: @test25( 273; CHECK-NEXT: [[B_IDX:%.*]] = shl nsw i64 [[A:%.*]], 1 274; CHECK-NEXT: [[GEPDIFF:%.*]] = add nsw i64 [[B_IDX]], -84 275; CHECK-NEXT: ret i64 [[GEPDIFF]] 276; 277 %B = getelementptr inbounds [42 x i16], [42 x i16]* @Arr, i64 0, i64 %A 278 %C = ptrtoint i16* %B to i64 279 %G = sub i64 %C, ptrtoint (i16* getelementptr ([42 x i16], [42 x i16]* @Arr, i64 1, i64 0) to i64) 280 ret i64 %G 281} 282 283@Arr_as1 = external addrspace(1) global [42 x i16] 284 285define i16 @test25_as1(i8 addrspace(1)* %P, i64 %A) { 286; CHECK-LABEL: @test25_as1( 287; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[A:%.*]] to i16 288; CHECK-NEXT: [[B_IDX:%.*]] = shl nsw i16 [[TMP1]], 1 289; CHECK-NEXT: [[GEPDIFF:%.*]] = add nsw i16 [[B_IDX]], -84 290; CHECK-NEXT: ret i16 [[GEPDIFF]] 291; 292 %B = getelementptr inbounds [42 x i16], [42 x i16] addrspace(1)* @Arr_as1, i64 0, i64 %A 293 %C = ptrtoint i16 addrspace(1)* %B to i16 294 %G = sub i16 %C, ptrtoint (i16 addrspace(1)* getelementptr ([42 x i16], [42 x i16] addrspace(1)* @Arr_as1, i64 1, i64 0) to i16) 295 ret i16 %G 296} 297 298define i64 @test30(i8* %foo, i64 %i, i64 %j) { 299; CHECK-LABEL: @test30( 300; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nsw i64 [[I:%.*]], 2 301; CHECK-NEXT: [[GEPDIFF:%.*]] = sub nsw i64 [[GEP1_IDX]], [[J:%.*]] 302; CHECK-NEXT: ret i64 [[GEPDIFF]] 303; 304 %bit = bitcast i8* %foo to i32* 305 %gep1 = getelementptr inbounds i32, i32* %bit, i64 %i 306 %gep2 = getelementptr inbounds i8, i8* %foo, i64 %j 307 %cast1 = ptrtoint i32* %gep1 to i64 308 %cast2 = ptrtoint i8* %gep2 to i64 309 %sub = sub i64 %cast1, %cast2 310 ret i64 %sub 311} 312 313define i16 @test30_as1(i8 addrspace(1)* %foo, i16 %i, i16 %j) { 314; CHECK-LABEL: @test30_as1( 315; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nsw i16 [[I:%.*]], 2 316; CHECK-NEXT: [[GEPDIFF:%.*]] = sub nsw i16 [[GEP1_IDX]], [[J:%.*]] 317; CHECK-NEXT: ret i16 [[GEPDIFF]] 318; 319 %bit = bitcast i8 addrspace(1)* %foo to i32 addrspace(1)* 320 %gep1 = getelementptr inbounds i32, i32 addrspace(1)* %bit, i16 %i 321 %gep2 = getelementptr inbounds i8, i8 addrspace(1)* %foo, i16 %j 322 %cast1 = ptrtoint i32 addrspace(1)* %gep1 to i16 323 %cast2 = ptrtoint i8 addrspace(1)* %gep2 to i16 324 %sub = sub i16 %cast1, %cast2 325 ret i16 %sub 326} 327 328; Inbounds translates to 'nsw' on sub 329 330define i64 @gep_diff_both_inbounds(i8* %foo, i64 %i, i64 %j) { 331; CHECK-LABEL: @gep_diff_both_inbounds( 332; CHECK-NEXT: [[GEPDIFF:%.*]] = sub nsw i64 [[I:%.*]], [[J:%.*]] 333; CHECK-NEXT: ret i64 [[GEPDIFF]] 334; 335 %gep1 = getelementptr inbounds i8, i8* %foo, i64 %i 336 %gep2 = getelementptr inbounds i8, i8* %foo, i64 %j 337 %cast1 = ptrtoint i8* %gep1 to i64 338 %cast2 = ptrtoint i8* %gep2 to i64 339 %sub = sub i64 %cast1, %cast2 340 ret i64 %sub 341} 342 343; Negative test for 'nsw' - both geps must be inbounds 344 345define i64 @gep_diff_first_inbounds(i8* %foo, i64 %i, i64 %j) { 346; CHECK-LABEL: @gep_diff_first_inbounds( 347; CHECK-NEXT: [[GEPDIFF:%.*]] = sub i64 [[I:%.*]], [[J:%.*]] 348; CHECK-NEXT: ret i64 [[GEPDIFF]] 349; 350 %gep1 = getelementptr inbounds i8, i8* %foo, i64 %i 351 %gep2 = getelementptr i8, i8* %foo, i64 %j 352 %cast1 = ptrtoint i8* %gep1 to i64 353 %cast2 = ptrtoint i8* %gep2 to i64 354 %sub = sub i64 %cast1, %cast2 355 ret i64 %sub 356} 357 358; Negative test for 'nsw' - both geps must be inbounds 359 360define i64 @gep_diff_second_inbounds(i8* %foo, i64 %i, i64 %j) { 361; CHECK-LABEL: @gep_diff_second_inbounds( 362; CHECK-NEXT: [[GEPDIFF:%.*]] = sub i64 [[I:%.*]], [[J:%.*]] 363; CHECK-NEXT: ret i64 [[GEPDIFF]] 364; 365 %gep1 = getelementptr i8, i8* %foo, i64 %i 366 %gep2 = getelementptr inbounds i8, i8* %foo, i64 %j 367 %cast1 = ptrtoint i8* %gep1 to i64 368 %cast2 = ptrtoint i8* %gep2 to i64 369 %sub = sub i64 %cast1, %cast2 370 ret i64 %sub 371} 372