1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes='require<loops>,instcombine' -S | FileCheck %s 3target datalayout = "E-p:64:64:64-p1:16:16:16-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64" 4 5; Constant folding should fix notionally out-of-bounds indices 6; and add inbounds keywords. 7 8%struct.X = type { [3 x i32], [3 x i32] } 9 10@Y = internal global [3 x %struct.X] zeroinitializer 11 12define void @frob() { 13; CHECK-LABEL: @frob( 14; CHECK-NEXT: store i32 1, ptr @Y, align 4 15; CHECK-NEXT: store i32 1, ptr getelementptr inbounds nuw (i8, ptr @Y, i64 4), align 4 16; CHECK-NEXT: store i32 1, ptr getelementptr inbounds nuw (i8, ptr @Y, i64 8), align 4 17; CHECK-NEXT: store i32 1, ptr getelementptr inbounds nuw (i8, ptr @Y, i64 12), align 4 18; CHECK-NEXT: store i32 1, ptr getelementptr inbounds nuw (i8, ptr @Y, i64 16), align 4 19; CHECK-NEXT: store i32 1, ptr getelementptr inbounds nuw (i8, ptr @Y, i64 20), align 4 20; CHECK-NEXT: store i32 1, ptr getelementptr inbounds nuw (i8, ptr @Y, i64 24), align 4 21; CHECK-NEXT: store i32 1, ptr getelementptr inbounds nuw (i8, ptr @Y, i64 28), align 4 22; CHECK-NEXT: store i32 1, ptr getelementptr inbounds nuw (i8, ptr @Y, i64 32), align 4 23; CHECK-NEXT: store i32 1, ptr getelementptr inbounds nuw (i8, ptr @Y, i64 36), align 4 24; CHECK-NEXT: store i32 1, ptr getelementptr inbounds nuw (i8, ptr @Y, i64 40), align 4 25; CHECK-NEXT: store i32 1, ptr getelementptr inbounds nuw (i8, ptr @Y, i64 44), align 4 26; CHECK-NEXT: store i32 1, ptr getelementptr inbounds nuw (i8, ptr @Y, i64 48), align 4 27; CHECK-NEXT: store i32 1, ptr getelementptr inbounds nuw (i8, ptr @Y, i64 52), align 4 28; CHECK-NEXT: store i32 1, ptr getelementptr inbounds nuw (i8, ptr @Y, i64 56), align 8 29; CHECK-NEXT: store i32 1, ptr getelementptr inbounds nuw (i8, ptr @Y, i64 60), align 4 30; CHECK-NEXT: store i32 1, ptr getelementptr inbounds nuw (i8, ptr @Y, i64 64), align 8 31; CHECK-NEXT: store i32 1, ptr getelementptr inbounds nuw (i8, ptr @Y, i64 68), align 4 32; CHECK-NEXT: store i32 1, ptr getelementptr inbounds nuw (i8, ptr @Y, i64 72), align 8 33; CHECK-NEXT: store i32 1, ptr getelementptr (i8, ptr @Y, i64 144), align 8 34; CHECK-NEXT: store i32 1, ptr getelementptr (i8, ptr @Y, i64 76), align 8 35; CHECK-NEXT: ret void 36; 37 store i32 1, ptr @Y, align 4 38 store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 1), align 4 39 store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 2), align 4 40 store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 3), align 4 41 store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 4), align 4 42 store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 5), align 4 43 store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 6), align 4 44 store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 7), align 4 45 store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 8), align 4 46 store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 9), align 4 47 store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 10), align 4 48 store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 11), align 4 49 store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 12), align 4 50 store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 13), align 4 51 store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 14), align 8 52 store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 15), align 4 53 store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 16), align 8 54 store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 17), align 4 55 store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 18), align 8 56 store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 36), align 8 57 store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 19), align 8 58 ret void 59} 60 61 62; PR8883 - Constant fold exotic gep subtract 63@X = global [1000 x i8] zeroinitializer, align 16 64 65define i64 @test2() { 66; CHECK-LABEL: @test2( 67; CHECK-NEXT: entry: 68; CHECK-NEXT: ret i64 1000 69; 70entry: 71 %A = bitcast ptr getelementptr inbounds ([1000 x i8], ptr @X, i64 1, i64 0) to ptr 72 73 %B2 = ptrtoint ptr @X to i64 74 %C = sub i64 0, %B2 75 %D = getelementptr i8, ptr %A, i64 %C 76 %E = ptrtoint ptr %D to i64 77 78 ret i64 %E 79} 80 81@X_as1 = addrspace(1) global [1000 x i8] zeroinitializer, align 16 82 83define i16 @test2_as1() { 84; CHECK-LABEL: @test2_as1( 85; CHECK-NEXT: entry: 86; CHECK-NEXT: ret i16 1000 87; 88 89entry: 90 %A = bitcast ptr addrspace(1) getelementptr inbounds ([1000 x i8], ptr addrspace(1) @X_as1, i64 1, i64 0) to ptr addrspace(1) 91 92 %B2 = ptrtoint ptr addrspace(1) @X_as1 to i16 93 %C = sub i16 0, %B2 94 %D = getelementptr i8, ptr addrspace(1) %A, i16 %C 95 %E = ptrtoint ptr addrspace(1) %D to i16 96 97 ret i16 %E 98} 99 100@g = external global i8 101@g2 = external global i8 102 103declare i64 @get.i64() 104declare void @use.ptr(ptr) 105 106define ptr @gep_sub_self() { 107; CHECK-LABEL: @gep_sub_self( 108; CHECK-NEXT: ret ptr getelementptr (i8, ptr @g, i64 sub (i64 0, i64 ptrtoint (ptr @g to i64))) 109; 110 %p.int = ptrtoint ptr @g to i64 111 %p.int.neg = sub i64 0, %p.int 112 %p1 = getelementptr i8, ptr @g, i64 %p.int.neg 113 ret ptr %p1 114} 115 116define ptr @gep_sub_self_plus_addr(i64 %addr) { 117; CHECK-LABEL: @gep_sub_self_plus_addr( 118; CHECK-NEXT: [[P2:%.*]] = getelementptr i8, ptr getelementptr (i8, ptr @g, i64 sub (i64 0, i64 ptrtoint (ptr @g to i64))), i64 [[ADDR:%.*]] 119; CHECK-NEXT: ret ptr [[P2]] 120; 121 %p.int = ptrtoint ptr @g to i64 122 %p.int.neg = sub i64 0, %p.int 123 %p1 = getelementptr i8, ptr @g, i64 %p.int.neg 124 %p2 = getelementptr i8, ptr %p1, i64 %addr 125 ret ptr %p2 126} 127 128define ptr @gep_plus_addr_sub_self(i64 %addr) { 129; CHECK-LABEL: @gep_plus_addr_sub_self( 130; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr @g, i64 [[ADDR:%.*]] 131; CHECK-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[P1]], i64 sub (i64 0, i64 ptrtoint (ptr @g to i64)) 132; CHECK-NEXT: ret ptr [[P2]] 133; 134 %p.int = ptrtoint ptr @g to i64 135 %p.int.neg = sub i64 0, %p.int 136 %p1 = getelementptr i8, ptr @g, i64 %addr 137 %p2 = getelementptr i8, ptr %p1, i64 %p.int.neg 138 ret ptr %p2 139} 140 141define ptr @gep_plus_addr_sub_self_in_loop() { 142; CHECK-LABEL: @gep_plus_addr_sub_self_in_loop( 143; CHECK-NEXT: br label [[LOOP:%.*]] 144; CHECK: loop: 145; CHECK-NEXT: [[ADDR:%.*]] = call i64 @get.i64() 146; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr @g, i64 [[ADDR]] 147; CHECK-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[P1]], i64 sub (i64 0, i64 ptrtoint (ptr @g to i64)) 148; CHECK-NEXT: call void @use.ptr(ptr [[P2]]) 149; CHECK-NEXT: br label [[LOOP]] 150; 151 %p.int = ptrtoint ptr @g to i64 152 %p.int.neg = sub i64 0, %p.int 153 br label %loop 154 155loop: 156 %addr = call i64 @get.i64() 157 %p1 = getelementptr i8, ptr @g, i64 %addr 158 %p2 = getelementptr i8, ptr %p1, i64 %p.int.neg 159 call void @use.ptr(ptr %p2) 160 br label %loop 161} 162 163define ptr @gep_sub_other() { 164; CHECK-LABEL: @gep_sub_other( 165; CHECK-NEXT: ret ptr getelementptr (i8, ptr @g, i64 sub (i64 0, i64 ptrtoint (ptr @g2 to i64))) 166; 167 %p.int = ptrtoint ptr @g2 to i64 168 %p.int.neg = sub i64 0, %p.int 169 %p1 = getelementptr i8, ptr @g, i64 %p.int.neg 170 ret ptr %p1 171} 172 173define i64 @gep_sub_other_to_int() { 174; CHECK-LABEL: @gep_sub_other_to_int( 175; CHECK-NEXT: ret i64 sub (i64 ptrtoint (ptr @g to i64), i64 ptrtoint (ptr @g2 to i64)) 176; 177 %p.int = ptrtoint ptr @g2 to i64 178 %p.int.neg = sub i64 0, %p.int 179 %p1 = getelementptr i8, ptr @g, i64 %p.int.neg 180 %p1.int = ptrtoint ptr %p1 to i64 181 ret i64 %p1.int 182} 183