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-m:m-p:40:64:64:32-i32:32-i16:16-i8:8-n32" 5 6%struct.B = type { double } 7%struct.A = type { %struct.B, i32, i32 } 8%struct.C = type { [7 x i8] } 9 10 11@Global = external global [10 x i8] 12 13; Test that two array indexing geps fold 14define ptr @test1(ptr %I) { 15; CHECK-LABEL: @test1( 16; CHECK-NEXT: [[B:%.*]] = getelementptr i8, ptr [[I:%.*]], i32 84 17; CHECK-NEXT: ret ptr [[B]] 18; 19 %A = getelementptr i32, ptr %I, i8 17 20 %B = getelementptr i32, ptr %A, i16 4 21 ret ptr %B 22} 23 24; Test that two getelementptr insts fold 25define ptr @test2(ptr %I) { 26; CHECK-LABEL: @test2( 27; CHECK-NEXT: [[A:%.*]] = getelementptr i8, ptr [[I:%.*]], i32 4 28; CHECK-NEXT: ret ptr [[A]] 29; 30 %A = getelementptr { i32 }, ptr %I, i32 1 31 ret ptr %A 32} 33 34define void @test3(i8 %B) { 35; This should be turned into a constexpr instead of being an instruction 36; CHECK-LABEL: @test3( 37; CHECK-NEXT: store i8 [[B:%.*]], ptr getelementptr inbounds nuw (i8, ptr @Global, i32 4), align 1 38; CHECK-NEXT: ret void 39; 40 %A = getelementptr [10 x i8], ptr @Global, i32 0, i32 4 41 store i8 %B, ptr %A 42 ret void 43} 44 45%as1_ptr_struct = type { ptr addrspace(1) } 46%as2_ptr_struct = type { ptr addrspace(2) } 47 48@global_as2 = addrspace(2) global i32 zeroinitializer 49@global_as1_as2_ptr = addrspace(1) global %as2_ptr_struct { ptr addrspace(2) @global_as2 } 50 51; This should be turned into a constexpr instead of being an instruction 52define void @test_evaluate_gep_nested_as_ptrs(ptr addrspace(2) %B) { 53; CHECK-LABEL: @test_evaluate_gep_nested_as_ptrs( 54; CHECK-NEXT: store ptr addrspace(2) [[B:%.*]], ptr addrspace(1) @global_as1_as2_ptr, align 8 55; CHECK-NEXT: ret void 56; 57 store ptr addrspace(2) %B, ptr addrspace(1) @global_as1_as2_ptr 58 ret void 59} 60 61@arst = addrspace(1) global [4 x ptr addrspace(2)] zeroinitializer 62 63define void @test_evaluate_gep_as_ptrs_array(ptr addrspace(2) %B) { 64; CHECK-LABEL: @test_evaluate_gep_as_ptrs_array( 65; CHECK-NEXT: store ptr addrspace(2) [[B:%.*]], ptr addrspace(1) getelementptr inbounds nuw (i8, ptr addrspace(1) @arst, i32 16), align 8 66; CHECK-NEXT: ret void 67; 68 69 %A = getelementptr [4 x ptr addrspace(2)], ptr addrspace(1) @arst, i16 0, i16 2 70 store ptr addrspace(2) %B, ptr addrspace(1) %A 71 ret void 72} 73 74define ptr @test4(ptr %I, i32 %C, i32 %D) { 75; CHECK-LABEL: @test4( 76; CHECK-NEXT: [[A:%.*]] = getelementptr i32, ptr [[I:%.*]], i32 [[C:%.*]] 77; CHECK-NEXT: [[B:%.*]] = getelementptr i32, ptr [[A]], i32 [[D:%.*]] 78; CHECK-NEXT: ret ptr [[B]] 79; 80 %A = getelementptr i32, ptr %I, i32 %C 81 %B = getelementptr i32, ptr %A, i32 %D 82 ret ptr %B 83} 84 85 86define i1 @test5(ptr %x, ptr %y) { 87; CHECK-LABEL: @test5( 88; CHECK-NEXT: [[TMP_4:%.*]] = icmp eq ptr [[X:%.*]], [[Y:%.*]] 89; CHECK-NEXT: ret i1 [[TMP_4]] 90; 91 %tmp.1 = getelementptr { i32, i32 }, ptr %x, i32 0, i32 1 92 %tmp.3 = getelementptr { i32, i32 }, ptr %y, i32 0, i32 1 93 ;; seteq x, y 94 %tmp.4 = icmp eq ptr %tmp.1, %tmp.3 95 ret i1 %tmp.4 96} 97 98%S = type { i32, [ 100 x i32] } 99 100define <2 x i1> @test6(<2 x i32> %X, <2 x ptr> %P) nounwind { 101; CHECK-LABEL: @test6( 102; CHECK-NEXT: [[C:%.*]] = icmp eq <2 x i32> [[X:%.*]], splat (i32 -1) 103; CHECK-NEXT: ret <2 x i1> [[C]] 104; 105 %A = getelementptr inbounds %S, <2 x ptr> %P, <2 x i32> zeroinitializer, <2 x i32> <i32 1, i32 1>, <2 x i32> %X 106 %B = getelementptr inbounds %S, <2 x ptr> %P, <2 x i32> <i32 0, i32 0>, <2 x i32> <i32 0, i32 0> 107 %C = icmp eq <2 x ptr> %A, %B 108 ret <2 x i1> %C 109} 110 111; Same as above, but indices scalarized. 112define <2 x i1> @test6b(<2 x i32> %X, <2 x ptr> %P) nounwind { 113; CHECK-LABEL: @test6b( 114; CHECK-NEXT: [[C:%.*]] = icmp eq <2 x i32> [[X:%.*]], splat (i32 -1) 115; CHECK-NEXT: ret <2 x i1> [[C]] 116; 117 %A = getelementptr inbounds %S, <2 x ptr> %P, i32 0, i32 1, <2 x i32> %X 118 %B = getelementptr inbounds %S, <2 x ptr> %P, i32 0, i32 0 119 %C = icmp eq <2 x ptr> %A, %B 120 ret <2 x i1> %C 121} 122 123@G = external global [3 x i8] 124define ptr @test7(i16 %Idx) { 125; CHECK-LABEL: @test7( 126; CHECK-NEXT: [[ZE_IDX:%.*]] = zext i16 [[IDX:%.*]] to i32 127; CHECK-NEXT: [[TMP:%.*]] = getelementptr i8, ptr @G, i32 [[ZE_IDX]] 128; CHECK-NEXT: ret ptr [[TMP]] 129; 130 %ZE_Idx = zext i16 %Idx to i32 131 %tmp = getelementptr i8, ptr @G, i32 %ZE_Idx 132 ret ptr %tmp 133} 134 135 136; Test folding of constantexpr geps into normal geps. 137@Array = external global [40 x i32] 138define ptr @test8(i32 %X) { 139; CHECK-LABEL: @test8( 140; CHECK-NEXT: [[A:%.*]] = getelementptr i32, ptr @Array, i32 [[X:%.*]] 141; CHECK-NEXT: ret ptr [[A]] 142; 143 %A = getelementptr i32, ptr @Array, i32 %X 144 ret ptr %A 145} 146 147define ptr @test9(ptr %base, i8 %ind) { 148; CHECK-LABEL: @test9( 149; CHECK-NEXT: [[TMP1:%.*]] = sext i8 [[IND:%.*]] to i32 150; CHECK-NEXT: [[RES:%.*]] = getelementptr i32, ptr [[BASE:%.*]], i32 [[TMP1]] 151; CHECK-NEXT: ret ptr [[RES]] 152; 153 %res = getelementptr i32, ptr %base, i8 %ind 154 ret ptr %res 155} 156 157define i32 @test10() { 158; CHECK-LABEL: @test10( 159; CHECK-NEXT: ret i32 8 160; 161 %A = getelementptr { i32, double }, ptr null, i32 0, i32 1 162 %B = ptrtoint ptr %A to i32 163 ret i32 %B 164} 165 166@X_as1 = addrspace(1) global [1000 x i8] zeroinitializer, align 16 167 168define i16 @constant_fold_custom_dl() { 169; CHECK-LABEL: @constant_fold_custom_dl( 170; CHECK-NEXT: entry: 171; CHECK-NEXT: ret i16 ptrtoint (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) getelementptr inbounds nuw (i8, ptr addrspace(1) @X_as1, i32 1000), i16 sub (i16 0, i16 ptrtoint (ptr addrspace(1) @X_as1 to i16))) to i16) 172; 173 174entry: 175 %A = bitcast ptr addrspace(1) getelementptr inbounds ([1000 x i8], ptr addrspace(1) @X_as1, i64 1, i64 0) to ptr addrspace(1) 176 177 %B2 = ptrtoint ptr addrspace(1) @X_as1 to i16 178 %C = sub i16 0, %B2 179 %D = getelementptr i8, ptr addrspace(1) %A, i16 %C 180 %E = ptrtoint ptr addrspace(1) %D to i16 181 182 ret i16 %E 183} 184 185define ptr @gep_too_large_type(ptr %p) { 186; CHECK-LABEL: @gep_too_large_type( 187; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i32 -4 188; CHECK-NEXT: ret ptr [[GEP]] 189; 190 %gep = getelementptr inbounds [4294967295 x i32], ptr %p, i32 1 191 ret ptr %gep 192} 193