1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instsimplify -S | FileCheck %s 3target datalayout = "p:32:32-p1:64:64" 4 5; This is a collection of tests checking whether we can prove pointers 6; derived from two allocas as inequal *via offset checks*. Note that 7; instcombine has alternate approaches (one cmp rule, and compare 8; bases of common offset) that also handles these, but with different 9; logic. 10 11; %a follows %b, derived equal 12define i1 @adjacent_alloca() { 13; CHECK-LABEL: @adjacent_alloca( 14; CHECK-NEXT: [[A:%.*]] = alloca i8, i32 4, align 1 15; CHECK-NEXT: [[B:%.*]] = alloca i8, i32 4, align 1 16; CHECK-NEXT: [[B_OFF:%.*]] = getelementptr i8, ptr [[B]], i64 4 17; CHECK-NEXT: [[RES:%.*]] = icmp ne ptr [[A]], [[B_OFF]] 18; CHECK-NEXT: ret i1 [[RES]] 19; 20 %a = alloca i8, i32 4 21 %b = alloca i8, i32 4 22 %b.off = getelementptr i8, ptr %b, i64 4 23 %res = icmp ne ptr %a, %b.off 24 ret i1 %res 25} 26 27; %b follows %a, derived equal 28define i1 @adjacent_alloca2() { 29; CHECK-LABEL: @adjacent_alloca2( 30; CHECK-NEXT: [[A:%.*]] = alloca i8, i32 4, align 1 31; CHECK-NEXT: [[B:%.*]] = alloca i8, i32 4, align 1 32; CHECK-NEXT: [[A_OFF:%.*]] = getelementptr i8, ptr [[A]], i64 4 33; CHECK-NEXT: [[RES:%.*]] = icmp ne ptr [[A_OFF]], [[B]] 34; CHECK-NEXT: ret i1 [[RES]] 35; 36 %a = alloca i8, i32 4 37 %b = alloca i8, i32 4 38 %a.off = getelementptr i8, ptr %a, i64 4 39 %res = icmp ne ptr %a.off, %b 40 ret i1 %res 41} 42 43; FIXME: Can't be equal 44define i1 @positive_non_equal_end() { 45; CHECK-LABEL: @positive_non_equal_end( 46; CHECK-NEXT: [[A:%.*]] = alloca i8, i32 4, align 1 47; CHECK-NEXT: [[B:%.*]] = alloca i8, i32 4, align 1 48; CHECK-NEXT: [[A_OFF:%.*]] = getelementptr i8, ptr [[A]], i64 4 49; CHECK-NEXT: [[B_OFF:%.*]] = getelementptr i8, ptr [[B]], i64 4 50; CHECK-NEXT: [[RES:%.*]] = icmp ne ptr [[A_OFF]], [[B_OFF]] 51; CHECK-NEXT: ret i1 [[RES]] 52; 53 %a = alloca i8, i32 4 54 %b = alloca i8, i32 4 55 %a.off = getelementptr i8, ptr %a, i64 4 56 %b.off = getelementptr i8, ptr %b, i64 4 57 %res = icmp ne ptr %a.off, %b.off 58 ret i1 %res 59} 60 61; %b follows %a, derived equal 62define i1 @positive_equal_past_end() { 63; CHECK-LABEL: @positive_equal_past_end( 64; CHECK-NEXT: [[A:%.*]] = alloca i8, i32 4, align 1 65; CHECK-NEXT: [[B:%.*]] = alloca i8, i32 4, align 1 66; CHECK-NEXT: [[A_OFF:%.*]] = getelementptr i8, ptr [[A]], i64 8 67; CHECK-NEXT: [[B_OFF:%.*]] = getelementptr i8, ptr [[B]], i64 12 68; CHECK-NEXT: [[RES:%.*]] = icmp ne ptr [[A_OFF]], [[B_OFF]] 69; CHECK-NEXT: ret i1 [[RES]] 70; 71 %a = alloca i8, i32 4 72 %b = alloca i8, i32 4 73 %a.off = getelementptr i8, ptr %a, i64 8 74 %b.off = getelementptr i8, ptr %b, i64 12 75 %res = icmp ne ptr %a.off, %b.off 76 ret i1 %res 77} 78 79define i1 @positive_non_equal() { 80; CHECK-LABEL: @positive_non_equal( 81; CHECK-NEXT: ret i1 true 82; 83 %a = alloca i8, i32 4 84 %b = alloca i8, i32 4 85 %a.off = getelementptr i8, ptr %a, i64 3 86 %b.off = getelementptr i8, ptr %b, i64 3 87 %res = icmp ne ptr %a.off, %b.off 88 ret i1 %res 89} 90 91; %a follows %b, derived equal 92define i1 @one_neg_equal1() { 93; CHECK-LABEL: @one_neg_equal1( 94; CHECK-NEXT: [[A:%.*]] = alloca i8, i32 4, align 1 95; CHECK-NEXT: [[B:%.*]] = alloca i8, i32 4, align 1 96; CHECK-NEXT: [[A_OFF:%.*]] = getelementptr i8, ptr [[A]], i64 -1 97; CHECK-NEXT: [[B_OFF:%.*]] = getelementptr i8, ptr [[B]], i64 3 98; CHECK-NEXT: [[RES:%.*]] = icmp ne ptr [[A_OFF]], [[B_OFF]] 99; CHECK-NEXT: ret i1 [[RES]] 100; 101 %a = alloca i8, i32 4 102 %b = alloca i8, i32 4 103 %a.off = getelementptr i8, ptr %a, i64 -1 104 %b.off = getelementptr i8, ptr %b, i64 3 105 %res = icmp ne ptr %a.off, %b.off 106 ret i1 %res 107} 108 109; %b follows %a, derived equal 110define i1 @one_neg_equal2() { 111; CHECK-LABEL: @one_neg_equal2( 112; CHECK-NEXT: [[A:%.*]] = alloca i8, i32 4, align 1 113; CHECK-NEXT: [[B:%.*]] = alloca i8, i32 4, align 1 114; CHECK-NEXT: [[A_OFF:%.*]] = getelementptr i8, ptr [[A]], i64 3 115; CHECK-NEXT: [[B_OFF:%.*]] = getelementptr i8, ptr [[B]], i64 -1 116; CHECK-NEXT: [[RES:%.*]] = icmp ne ptr [[A_OFF]], [[B_OFF]] 117; CHECK-NEXT: ret i1 [[RES]] 118; 119 %a = alloca i8, i32 4 120 %b = alloca i8, i32 4 121 %a.off = getelementptr i8, ptr %a, i64 3 122 %b.off = getelementptr i8, ptr %b, i64 -1 123 %res = icmp ne ptr %a.off, %b.off 124 ret i1 %res 125} 126 127; %b follows %a, derived equal 128define i1 @both_neg_equal() { 129; CHECK-LABEL: @both_neg_equal( 130; CHECK-NEXT: [[A:%.*]] = alloca i8, i32 4, align 1 131; CHECK-NEXT: [[B:%.*]] = alloca i8, i32 4, align 1 132; CHECK-NEXT: [[A_OFF:%.*]] = getelementptr i8, ptr [[A]], i64 -4 133; CHECK-NEXT: [[B_OFF:%.*]] = getelementptr i8, ptr [[B]], i64 -8 134; CHECK-NEXT: [[RES:%.*]] = icmp ne ptr [[A_OFF]], [[B_OFF]] 135; CHECK-NEXT: ret i1 [[RES]] 136; 137 %a = alloca i8, i32 4 138 %b = alloca i8, i32 4 139 %a.off = getelementptr i8, ptr %a, i64 -4 140 %b.off = getelementptr i8, ptr %b, i64 -8 141 %res = icmp ne ptr %a.off, %b.off 142 ret i1 %res 143} 144 145; FIXME: Can't be equal 146define i1 @mixed_offsets1() { 147; CHECK-LABEL: @mixed_offsets1( 148; CHECK-NEXT: [[A:%.*]] = alloca i8, i32 4, align 1 149; CHECK-NEXT: [[B:%.*]] = alloca i8, i32 4, align 1 150; CHECK-NEXT: [[A_OFF:%.*]] = getelementptr i8, ptr [[A]], i64 -1 151; CHECK-NEXT: [[B_OFF:%.*]] = getelementptr i8, ptr [[B]], i64 2 152; CHECK-NEXT: [[RES:%.*]] = icmp ne ptr [[A_OFF]], [[B_OFF]] 153; CHECK-NEXT: ret i1 [[RES]] 154; 155 %a = alloca i8, i32 4 156 %b = alloca i8, i32 4 157 %a.off = getelementptr i8, ptr %a, i64 -1 158 %b.off = getelementptr i8, ptr %b, i64 2 159 %res = icmp ne ptr %a.off, %b.off 160 ret i1 %res 161} 162 163; FIXME: Can't be equal 164define i1 @mixed_offsets2() { 165; CHECK-LABEL: @mixed_offsets2( 166; CHECK-NEXT: [[A:%.*]] = alloca i8, i32 4, align 1 167; CHECK-NEXT: [[B:%.*]] = alloca i8, i32 4, align 1 168; CHECK-NEXT: [[A_OFF:%.*]] = getelementptr i8, ptr [[A]], i64 1 169; CHECK-NEXT: [[B_OFF:%.*]] = getelementptr i8, ptr [[B]], i64 -2 170; CHECK-NEXT: [[RES:%.*]] = icmp ne ptr [[A_OFF]], [[B_OFF]] 171; CHECK-NEXT: ret i1 [[RES]] 172; 173 %a = alloca i8, i32 4 174 %b = alloca i8, i32 4 175 %a.off = getelementptr i8, ptr %a, i64 1 176 %b.off = getelementptr i8, ptr %b, i64 -2 177 %res = icmp ne ptr %a.off, %b.off 178 ret i1 %res 179} 180 181; FIXME: Can't be equal 182define i1 @negative_in_other() { 183; CHECK-LABEL: @negative_in_other( 184; CHECK-NEXT: [[A:%.*]] = alloca i8, i32 4, align 1 185; CHECK-NEXT: [[B:%.*]] = alloca i8, i32 4, align 1 186; CHECK-NEXT: [[A_OFF:%.*]] = getelementptr i8, ptr [[A]], i64 -3 187; CHECK-NEXT: [[B_OFF:%.*]] = getelementptr i8, ptr [[B]], i64 -2 188; CHECK-NEXT: [[RES:%.*]] = icmp ne ptr [[A_OFF]], [[B_OFF]] 189; CHECK-NEXT: ret i1 [[RES]] 190; 191 %a = alloca i8, i32 4 192 %b = alloca i8, i32 4 193 %a.off = getelementptr i8, ptr %a, i64 -3 194 %b.off = getelementptr i8, ptr %b, i64 -2 195 %res = icmp ne ptr %a.off, %b.off 196 ret i1 %res 197} 198 199 200attributes #0 = { null_pointer_is_valid } 201