183 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes='require<loops>,instcombine' -S | FileCheck %s3target 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 indices6; and add inbounds keywords.7 8%struct.X = type { [3 x i32], [3 x i32] }9 10@Y = internal global [3 x %struct.X] zeroinitializer11 12define void @frob() {13; CHECK-LABEL: @frob(14; CHECK-NEXT: store i32 1, ptr @Y, align 415; CHECK-NEXT: store i32 1, ptr getelementptr inbounds nuw (i8, ptr @Y, i64 4), align 416; CHECK-NEXT: store i32 1, ptr getelementptr inbounds nuw (i8, ptr @Y, i64 8), align 417; CHECK-NEXT: store i32 1, ptr getelementptr inbounds nuw (i8, ptr @Y, i64 12), align 418; CHECK-NEXT: store i32 1, ptr getelementptr inbounds nuw (i8, ptr @Y, i64 16), align 419; CHECK-NEXT: store i32 1, ptr getelementptr inbounds nuw (i8, ptr @Y, i64 20), align 420; CHECK-NEXT: store i32 1, ptr getelementptr inbounds nuw (i8, ptr @Y, i64 24), align 421; CHECK-NEXT: store i32 1, ptr getelementptr inbounds nuw (i8, ptr @Y, i64 28), align 422; CHECK-NEXT: store i32 1, ptr getelementptr inbounds nuw (i8, ptr @Y, i64 32), align 423; CHECK-NEXT: store i32 1, ptr getelementptr inbounds nuw (i8, ptr @Y, i64 36), align 424; CHECK-NEXT: store i32 1, ptr getelementptr inbounds nuw (i8, ptr @Y, i64 40), align 425; CHECK-NEXT: store i32 1, ptr getelementptr inbounds nuw (i8, ptr @Y, i64 44), align 426; CHECK-NEXT: store i32 1, ptr getelementptr inbounds nuw (i8, ptr @Y, i64 48), align 427; CHECK-NEXT: store i32 1, ptr getelementptr inbounds nuw (i8, ptr @Y, i64 52), align 428; CHECK-NEXT: store i32 1, ptr getelementptr inbounds nuw (i8, ptr @Y, i64 56), align 829; CHECK-NEXT: store i32 1, ptr getelementptr inbounds nuw (i8, ptr @Y, i64 60), align 430; CHECK-NEXT: store i32 1, ptr getelementptr inbounds nuw (i8, ptr @Y, i64 64), align 831; CHECK-NEXT: store i32 1, ptr getelementptr inbounds nuw (i8, ptr @Y, i64 68), align 432; CHECK-NEXT: store i32 1, ptr getelementptr inbounds nuw (i8, ptr @Y, i64 72), align 833; CHECK-NEXT: store i32 1, ptr getelementptr (i8, ptr @Y, i64 144), align 834; CHECK-NEXT: store i32 1, ptr getelementptr (i8, ptr @Y, i64 76), align 835; CHECK-NEXT: ret void36;37 store i32 1, ptr @Y, align 438 store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 1), align 439 store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 2), align 440 store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 3), align 441 store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 4), align 442 store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 5), align 443 store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 6), align 444 store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 7), align 445 store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 8), align 446 store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 9), align 447 store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 10), align 448 store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 11), align 449 store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 12), align 450 store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 13), align 451 store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 14), align 852 store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 15), align 453 store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 16), align 854 store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 17), align 455 store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 18), align 856 store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 36), align 857 store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 19), align 858 ret void59}60 61 62; PR8883 - Constant fold exotic gep subtract63@X = global [1000 x i8] zeroinitializer, align 1664 65define i64 @test2() {66; CHECK-LABEL: @test2(67; CHECK-NEXT: entry:68; CHECK-NEXT: ret i64 100069;70entry:71 %A = bitcast ptr getelementptr inbounds ([1000 x i8], ptr @X, i64 1, i64 0) to ptr72 73 %B2 = ptrtoint ptr @X to i6474 %C = sub i64 0, %B275 %D = getelementptr i8, ptr %A, i64 %C76 %E = ptrtoint ptr %D to i6477 78 ret i64 %E79}80 81@X_as1 = addrspace(1) global [1000 x i8] zeroinitializer, align 1682 83define i16 @test2_as1() {84; CHECK-LABEL: @test2_as1(85; CHECK-NEXT: entry:86; CHECK-NEXT: ret i16 100087;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 i1693 %C = sub i16 0, %B294 %D = getelementptr i8, ptr addrspace(1) %A, i16 %C95 %E = ptrtoint ptr addrspace(1) %D to i1696 97 ret i16 %E98}99 100@g = external global i8101@g2 = external global i8102 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 i64111 %p.int.neg = sub i64 0, %p.int112 %p1 = getelementptr i8, ptr @g, i64 %p.int.neg113 ret ptr %p1114}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 i64122 %p.int.neg = sub i64 0, %p.int123 %p1 = getelementptr i8, ptr @g, i64 %p.int.neg124 %p2 = getelementptr i8, ptr %p1, i64 %addr125 ret ptr %p2126}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 i64135 %p.int.neg = sub i64 0, %p.int136 %p1 = getelementptr i8, ptr @g, i64 %addr137 %p2 = getelementptr i8, ptr %p1, i64 %p.int.neg138 ret ptr %p2139}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 i64152 %p.int.neg = sub i64 0, %p.int153 br label %loop154 155loop:156 %addr = call i64 @get.i64()157 %p1 = getelementptr i8, ptr @g, i64 %addr158 %p2 = getelementptr i8, ptr %p1, i64 %p.int.neg159 call void @use.ptr(ptr %p2)160 br label %loop161}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 i64168 %p.int.neg = sub i64 0, %p.int169 %p1 = getelementptr i8, ptr @g, i64 %p.int.neg170 ret ptr %p1171}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 i64178 %p.int.neg = sub i64 0, %p.int179 %p1 = getelementptr i8, ptr @g, i64 %p.int.neg180 %p1.int = ptrtoint ptr %p1 to i64181 ret i64 %p1.int182}183