1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -passes=instsimplify < %s | FileCheck %s 3; RUN: opt -S -passes=instsimplify -use-constant-int-for-fixed-length-splat < %s | FileCheck %s 4 5target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" 6 7%struct.A = type { [7 x i8] } 8 9@g = external global i8 10 11define ptr @test1(ptr %b, ptr %e) { 12; CHECK-LABEL: @test1( 13; CHECK-NEXT: [[E_PTR:%.*]] = ptrtoint ptr [[E:%.*]] to i64 14; CHECK-NEXT: [[B_PTR:%.*]] = ptrtoint ptr [[B:%.*]] to i64 15; CHECK-NEXT: [[SUB:%.*]] = sub i64 [[E_PTR]], [[B_PTR]] 16; CHECK-NEXT: [[SDIV:%.*]] = sdiv exact i64 [[SUB]], 7 17; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [[STRUCT_A:%.*]], ptr [[B]], i64 [[SDIV]] 18; CHECK-NEXT: ret ptr [[GEP]] 19; 20 %e_ptr = ptrtoint ptr %e to i64 21 %b_ptr = ptrtoint ptr %b to i64 22 %sub = sub i64 %e_ptr, %b_ptr 23 %sdiv = sdiv exact i64 %sub, 7 24 %gep = getelementptr inbounds %struct.A, ptr %b, i64 %sdiv 25 ret ptr %gep 26} 27 28define ptr @test2(ptr %b, ptr %e) { 29; CHECK-LABEL: @test2( 30; CHECK-NEXT: [[E_PTR:%.*]] = ptrtoint ptr [[E:%.*]] to i64 31; CHECK-NEXT: [[B_PTR:%.*]] = ptrtoint ptr [[B:%.*]] to i64 32; CHECK-NEXT: [[SUB:%.*]] = sub i64 [[E_PTR]], [[B_PTR]] 33; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr [[B]], i64 [[SUB]] 34; CHECK-NEXT: ret ptr [[GEP]] 35; 36 %e_ptr = ptrtoint ptr %e to i64 37 %b_ptr = ptrtoint ptr %b to i64 38 %sub = sub i64 %e_ptr, %b_ptr 39 %gep = getelementptr inbounds i8, ptr %b, i64 %sub 40 ret ptr %gep 41} 42 43define ptr @test3(ptr %b, ptr %e) { 44; CHECK-LABEL: @test3( 45; CHECK-NEXT: [[E_PTR:%.*]] = ptrtoint ptr [[E:%.*]] to i64 46; CHECK-NEXT: [[B_PTR:%.*]] = ptrtoint ptr [[B:%.*]] to i64 47; CHECK-NEXT: [[SUB:%.*]] = sub i64 [[E_PTR]], [[B_PTR]] 48; CHECK-NEXT: [[ASHR:%.*]] = ashr exact i64 [[SUB]], 3 49; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i64, ptr [[B]], i64 [[ASHR]] 50; CHECK-NEXT: ret ptr [[GEP]] 51; 52 %e_ptr = ptrtoint ptr %e to i64 53 %b_ptr = ptrtoint ptr %b to i64 54 %sub = sub i64 %e_ptr, %b_ptr 55 %ashr = ashr exact i64 %sub, 3 56 %gep = getelementptr inbounds i64, ptr %b, i64 %ashr 57 ret ptr %gep 58} 59 60; The following tests should not be folded to null, because this would 61; lose provenance of the base pointer %b. 62 63define ptr @test4(ptr %b) { 64; CHECK-LABEL: @test4( 65; CHECK-NEXT: [[B_PTR:%.*]] = ptrtoint ptr [[B:%.*]] to i64 66; CHECK-NEXT: [[SUB:%.*]] = sub i64 0, [[B_PTR]] 67; CHECK-NEXT: [[SDIV:%.*]] = sdiv exact i64 [[SUB]], 7 68; CHECK-NEXT: [[GEP:%.*]] = getelementptr [[STRUCT_A:%.*]], ptr [[B]], i64 [[SDIV]] 69; CHECK-NEXT: ret ptr [[GEP]] 70; 71 %b_ptr = ptrtoint ptr %b to i64 72 %sub = sub i64 0, %b_ptr 73 %sdiv = sdiv exact i64 %sub, 7 74 %gep = getelementptr %struct.A, ptr %b, i64 %sdiv 75 ret ptr %gep 76} 77 78define ptr @test4_inbounds(ptr %b) { 79; CHECK-LABEL: @test4_inbounds( 80; CHECK-NEXT: [[B_PTR:%.*]] = ptrtoint ptr [[B:%.*]] to i64 81; CHECK-NEXT: [[SUB:%.*]] = sub i64 0, [[B_PTR]] 82; CHECK-NEXT: [[SDIV:%.*]] = sdiv exact i64 [[SUB]], 7 83; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [[STRUCT_A:%.*]], ptr [[B]], i64 [[SDIV]] 84; CHECK-NEXT: ret ptr [[GEP]] 85; 86 %b_ptr = ptrtoint ptr %b to i64 87 %sub = sub i64 0, %b_ptr 88 %sdiv = sdiv exact i64 %sub, 7 89 %gep = getelementptr inbounds %struct.A, ptr %b, i64 %sdiv 90 ret ptr %gep 91} 92 93define ptr @test5(ptr %b) { 94; CHECK-LABEL: @test5( 95; CHECK-NEXT: [[B_PTR:%.*]] = ptrtoint ptr [[B:%.*]] to i64 96; CHECK-NEXT: [[SUB:%.*]] = sub i64 0, [[B_PTR]] 97; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[B]], i64 [[SUB]] 98; CHECK-NEXT: ret ptr [[GEP]] 99; 100 %b_ptr = ptrtoint ptr %b to i64 101 %sub = sub i64 0, %b_ptr 102 %gep = getelementptr i8, ptr %b, i64 %sub 103 ret ptr %gep 104} 105 106define ptr @test5_inbounds(ptr %b) { 107; CHECK-LABEL: @test5_inbounds( 108; CHECK-NEXT: [[B_PTR:%.*]] = ptrtoint ptr [[B:%.*]] to i64 109; CHECK-NEXT: [[SUB:%.*]] = sub i64 0, [[B_PTR]] 110; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr [[B]], i64 [[SUB]] 111; CHECK-NEXT: ret ptr [[GEP]] 112; 113 %b_ptr = ptrtoint ptr %b to i64 114 %sub = sub i64 0, %b_ptr 115 %gep = getelementptr inbounds i8, ptr %b, i64 %sub 116 ret ptr %gep 117} 118 119define ptr @test6(ptr %b) { 120; CHECK-LABEL: @test6( 121; CHECK-NEXT: [[B_PTR:%.*]] = ptrtoint ptr [[B:%.*]] to i64 122; CHECK-NEXT: [[SUB:%.*]] = sub i64 0, [[B_PTR]] 123; CHECK-NEXT: [[ASHR:%.*]] = ashr exact i64 [[SUB]], 3 124; CHECK-NEXT: [[GEP:%.*]] = getelementptr i64, ptr [[B]], i64 [[ASHR]] 125; CHECK-NEXT: ret ptr [[GEP]] 126; 127 %b_ptr = ptrtoint ptr %b to i64 128 %sub = sub i64 0, %b_ptr 129 %ashr = ashr exact i64 %sub, 3 130 %gep = getelementptr i64, ptr %b, i64 %ashr 131 ret ptr %gep 132} 133 134define ptr @test6_inbounds(ptr %b) { 135; CHECK-LABEL: @test6_inbounds( 136; CHECK-NEXT: [[B_PTR:%.*]] = ptrtoint ptr [[B:%.*]] to i64 137; CHECK-NEXT: [[SUB:%.*]] = sub i64 0, [[B_PTR]] 138; CHECK-NEXT: [[ASHR:%.*]] = ashr exact i64 [[SUB]], 3 139; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i64, ptr [[B]], i64 [[ASHR]] 140; CHECK-NEXT: ret ptr [[GEP]] 141; 142 %b_ptr = ptrtoint ptr %b to i64 143 %sub = sub i64 0, %b_ptr 144 %ashr = ashr exact i64 %sub, 3 145 %gep = getelementptr inbounds i64, ptr %b, i64 %ashr 146 ret ptr %gep 147} 148 149define ptr @test7(ptr %b, ptr %e) { 150; CHECK-LABEL: @test7( 151; CHECK-NEXT: [[E_PTR:%.*]] = ptrtoint ptr [[E:%.*]] to i64 152; CHECK-NEXT: [[B_PTR:%.*]] = ptrtoint ptr [[B:%.*]] to i64 153; CHECK-NEXT: [[SUB:%.*]] = sub i64 [[E_PTR]], [[B_PTR]] 154; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr [[B]], i64 [[SUB]] 155; CHECK-NEXT: ret ptr [[GEP]] 156; 157 %e_ptr = ptrtoint ptr %e to i64 158 %b_ptr = ptrtoint ptr %b to i64 159 %sub = sub i64 %e_ptr, %b_ptr 160 %gep = getelementptr inbounds i8, ptr %b, i64 %sub 161 ret ptr %gep 162} 163 164define ptr @undef_inbounds_var_idx(i64 %idx) { 165; CHECK-LABEL: @undef_inbounds_var_idx( 166; CHECK-NEXT: ret ptr undef 167; 168 %el = getelementptr inbounds i64, ptr undef, i64 %idx 169 ret ptr %el 170} 171 172define ptr @undef_no_inbounds_var_idx(i64 %idx) { 173; CHECK-LABEL: @undef_no_inbounds_var_idx( 174; CHECK-NEXT: ret ptr undef 175; 176 %el = getelementptr i64, ptr undef, i64 %idx 177 ret ptr %el 178} 179 180define <8 x ptr> @undef_vec1() { 181; CHECK-LABEL: @undef_vec1( 182; CHECK-NEXT: ret <8 x ptr> undef 183; 184 %el = getelementptr inbounds i64, ptr undef, <8 x i64> undef 185 ret <8 x ptr> %el 186} 187 188define <8 x ptr> @undef_vec2() { 189; CHECK-LABEL: @undef_vec2( 190; CHECK-NEXT: ret <8 x ptr> undef 191; 192 %el = getelementptr i64, <8 x ptr> undef, <8 x i64> undef 193 ret <8 x ptr> %el 194} 195 196; Check ConstantExpr::getGetElementPtr() using ElementCount for size queries - begin. 197 198; Constant ptr 199 200define ptr @ptr_idx_scalar() { 201; CHECK-LABEL: @ptr_idx_scalar( 202; CHECK-NEXT: ret ptr inttoptr (i64 4 to ptr) 203; 204 %gep = getelementptr <4 x i32>, ptr null, i64 0, i64 1 205 ret ptr %gep 206} 207 208define <2 x ptr> @ptr_idx_vector() { 209; CHECK-LABEL: @ptr_idx_vector( 210; CHECK-NEXT: ret <2 x ptr> getelementptr (i32, ptr null, <2 x i64> splat (i64 1)) 211; 212 %gep = getelementptr i32, ptr null, <2 x i64> <i64 1, i64 1> 213 ret <2 x ptr> %gep 214} 215 216define <4 x ptr> @ptr_idx_mix_scalar_vector(){ 217; CHECK-LABEL: @ptr_idx_mix_scalar_vector( 218; CHECK-NEXT: ret <4 x ptr> getelementptr ([42 x [3 x i32]], ptr null, <4 x i64> zeroinitializer, <4 x i64> <i64 0, i64 1, i64 2, i64 3>, <4 x i64> zeroinitializer) 219; 220 %gep = getelementptr [42 x [3 x i32]], ptr null, i64 0, <4 x i64> <i64 0, i64 1, i64 2, i64 3>, i64 0 221 ret <4 x ptr> %gep 222} 223 224; Constant vector 225 226define <4 x ptr> @vector_idx_scalar() { 227; CHECK-LABEL: @vector_idx_scalar( 228; CHECK-NEXT: ret <4 x ptr> getelementptr (i32, <4 x ptr> zeroinitializer, <4 x i64> splat (i64 1)) 229; 230 %gep = getelementptr i32, <4 x ptr> zeroinitializer, i64 1 231 ret <4 x ptr> %gep 232} 233 234define <4 x ptr> @vector_idx_vector() { 235; CHECK-LABEL: @vector_idx_vector( 236; CHECK-NEXT: ret <4 x ptr> getelementptr (i32, <4 x ptr> zeroinitializer, <4 x i64> splat (i64 1)) 237; 238 %gep = getelementptr i32, <4 x ptr> zeroinitializer, <4 x i64> <i64 1, i64 1, i64 1, i64 1> 239 ret <4 x ptr> %gep 240} 241 242%struct = type { double, float } 243define <4 x ptr> @vector_idx_mix_scalar_vector() { 244; CHECK-LABEL: @vector_idx_mix_scalar_vector( 245; CHECK-NEXT: ret <4 x ptr> getelementptr ([[STRUCT:%.*]], <4 x ptr> zeroinitializer, <4 x i64> zeroinitializer, i32 1) 246; 247 %gep = getelementptr %struct, <4 x ptr> zeroinitializer, i32 0, <4 x i32> <i32 1, i32 1, i32 1, i32 1> 248 ret <4 x ptr> %gep 249} 250 251; Constant scalable 252 253define <vscale x 4 x ptr> @scalable_idx_scalar() { 254; CHECK-LABEL: @scalable_idx_scalar( 255; CHECK-NEXT: ret <vscale x 4 x ptr> getelementptr (i32, <vscale x 4 x ptr> zeroinitializer, <vscale x 4 x i64> splat (i64 1)) 256; 257 %gep = getelementptr i32, <vscale x 4 x ptr> zeroinitializer, i64 1 258 ret <vscale x 4 x ptr> %gep 259} 260 261define <vscale x 4 x ptr> @scalable_vector_idx_mix_scalar_vector() { 262; CHECK-LABEL: @scalable_vector_idx_mix_scalar_vector( 263; CHECK-NEXT: ret <vscale x 4 x ptr> getelementptr ([[STRUCT:%.*]], <vscale x 4 x ptr> zeroinitializer, <vscale x 4 x i64> zeroinitializer, i32 1) 264; 265 %gep = getelementptr %struct, <vscale x 4 x ptr> zeroinitializer, i32 0, i32 1 266 ret <vscale x 4 x ptr> %gep 267} 268 269define <vscale x 2 x ptr> @ptr_idx_mix_scalar_scalable_vector() { 270; CHECK-LABEL: @ptr_idx_mix_scalar_scalable_vector( 271; CHECK-NEXT: ret <vscale x 2 x ptr> zeroinitializer 272; 273 %v = getelementptr [2 x i64], ptr null, i64 0, <vscale x 2 x i64> zeroinitializer 274 ret <vscale x 2 x ptr> %v 275} 276 277define ptr @constexpr_gep_nusw_nuw() { 278; CHECK-LABEL: @constexpr_gep_nusw_nuw( 279; CHECK-NEXT: ret ptr getelementptr nusw nuw (i8, ptr @g, i64 ptrtoint (ptr @g to i64)) 280; 281 %v = getelementptr nusw nuw i8, ptr @g, i64 ptrtoint (ptr @g to i64) 282 ret ptr %v 283} 284 285; Check ConstantExpr::getGetElementPtr() using ElementCount for size queries - end. 286 287define ptr @poison() { 288; CHECK-LABEL: @poison( 289; CHECK-NEXT: ret ptr poison 290; 291 %v = getelementptr i8, ptr poison, i64 1 292 ret ptr %v 293} 294 295define ptr @poison2(ptr %baseptr) { 296; CHECK-LABEL: @poison2( 297; CHECK-NEXT: ret ptr poison 298; 299 %v = getelementptr i8, ptr %baseptr, i64 poison 300 ret ptr %v 301} 302 303define ptr @D98611_1(ptr %c1, i64 %offset) { 304; CHECK-LABEL: @D98611_1( 305; CHECK-NEXT: [[C2:%.*]] = getelementptr inbounds i8, ptr [[C1:%.*]], i64 [[OFFSET:%.*]] 306; CHECK-NEXT: ret ptr [[C2]] 307; 308 %c2 = getelementptr inbounds i8, ptr %c1, i64 %offset 309 %ptrtoint1 = ptrtoint ptr %c1 to i64 310 %ptrtoint2 = ptrtoint ptr %c2 to i64 311 %sub = sub i64 %ptrtoint2, %ptrtoint1 312 %gep = getelementptr inbounds i8, ptr %c1, i64 %sub 313 ret ptr %gep 314} 315 316define ptr @D98611_2(ptr %c1, i64 %offset) { 317; CHECK-LABEL: @D98611_2( 318; CHECK-NEXT: [[C2:%.*]] = getelementptr inbounds [[STRUCT_A:%.*]], ptr [[C1:%.*]], i64 [[OFFSET:%.*]] 319; CHECK-NEXT: ret ptr [[C2]] 320; 321 %c2 = getelementptr inbounds %struct.A, ptr %c1, i64 %offset 322 %ptrtoint1 = ptrtoint ptr %c1 to i64 323 %ptrtoint2 = ptrtoint ptr %c2 to i64 324 %sub = sub i64 %ptrtoint2, %ptrtoint1 325 %sdiv = sdiv exact i64 %sub, 7 326 %gep = getelementptr inbounds %struct.A, ptr %c1, i64 %sdiv 327 ret ptr %gep 328} 329 330define ptr @D98611_3(ptr %c1, i64 %offset) { 331; CHECK-LABEL: @D98611_3( 332; CHECK-NEXT: [[C2:%.*]] = getelementptr inbounds i32, ptr [[C1:%.*]], i64 [[OFFSET:%.*]] 333; CHECK-NEXT: ret ptr [[C2]] 334; 335 %c2 = getelementptr inbounds i32, ptr %c1, i64 %offset 336 %ptrtoint1 = ptrtoint ptr %c1 to i64 337 %ptrtoint2 = ptrtoint ptr %c2 to i64 338 %sub = sub i64 %ptrtoint2, %ptrtoint1 339 %ashr = ashr exact i64 %sub, 2 340 %gep = getelementptr inbounds i32, ptr %c1, i64 %ashr 341 ret ptr %gep 342} 343 344define <8 x ptr> @gep_vector_index_op2_poison(ptr %ptr) { 345; CHECK-LABEL: @gep_vector_index_op2_poison( 346; CHECK-NEXT: ret <8 x ptr> poison 347; 348 %res = getelementptr inbounds [144 x i32], ptr %ptr, i64 0, <8 x i64> poison 349 ret <8 x ptr> %res 350} 351 352%t.1 = type { i32, [144 x i32] } 353 354define <8 x ptr> @gep_vector_index_op3_poison(ptr %ptr) { 355; CHECK-LABEL: @gep_vector_index_op3_poison( 356; CHECK-NEXT: ret <8 x ptr> poison 357; 358 %res = getelementptr inbounds %t.1, ptr %ptr, i64 0, i32 1, <8 x i64> poison 359 ret <8 x ptr> %res 360} 361 362%t.2 = type { i32, i32 } 363%t.3 = type { i32, [144 x %t.2 ] } 364 365define <8 x ptr> @gep_vector_index_op3_poison_constant_index_afterwards(ptr %ptr) { 366; CHECK-LABEL: @gep_vector_index_op3_poison_constant_index_afterwards( 367; CHECK-NEXT: ret <8 x ptr> poison 368; 369 %res = getelementptr inbounds %t.3, ptr %ptr, i64 0, i32 1, <8 x i64> poison, i32 1 370 ret <8 x ptr> %res 371} 372 373define i64 @gep_array_of_scalable_vectors_ptrdiff(ptr %ptr) { 374; CHECK-LABEL: @gep_array_of_scalable_vectors_ptrdiff( 375; CHECK-NEXT: [[C1:%.*]] = getelementptr inbounds [8 x <vscale x 4 x i32>], ptr [[PTR:%.*]], i64 4 376; CHECK-NEXT: [[C2:%.*]] = getelementptr inbounds [8 x <vscale x 4 x i32>], ptr [[PTR]], i64 6 377; CHECK-NEXT: [[C1_INT:%.*]] = ptrtoint ptr [[C1]] to i64 378; CHECK-NEXT: [[C2_INT:%.*]] = ptrtoint ptr [[C2]] to i64 379; CHECK-NEXT: [[DIFF:%.*]] = sub i64 [[C2_INT]], [[C1_INT]] 380; CHECK-NEXT: ret i64 [[DIFF]] 381; 382 %c1 = getelementptr inbounds [8 x <vscale x 4 x i32>], ptr %ptr, i64 4 383 %c2 = getelementptr inbounds [8 x <vscale x 4 x i32>], ptr %ptr, i64 6 384 %c1.int = ptrtoint ptr %c1 to i64 385 %c2.int = ptrtoint ptr %c2 to i64 386 %diff = sub i64 %c2.int, %c1.int 387 ret i64 %diff 388} 389