1; RUN: opt < %s -basic-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s 2 3%struct.S = type { i32, [2 x i32], i32 } 4%struct.S2 = type { i32, [4 x i32], [4 x i32] } 5 6; CHECK: Function: t1 7; CHECK: NoAlias: i32* %gep1, i32* %gep2 8define void @t1(%struct.S* %s) { 9 %gep1 = getelementptr inbounds %struct.S, %struct.S* %s, i64 0, i32 1, i32 1 10 %gep2 = getelementptr inbounds %struct.S, %struct.S* %s, i64 0, i32 1, i32 0 11 ret void 12} 13 14; CHECK: Function: t2_fwd 15; CHECK: MayAlias: i32* %gep1, i32* %gep2 16define void @t2_fwd(%struct.S* %s, i32* %q) { 17 %in_array = load i32, i32* %q, !range !0 18 %gep1 = getelementptr inbounds %struct.S, %struct.S* %s, i64 0, i32 1, i32 %in_array 19 %gep2 = getelementptr inbounds %struct.S, %struct.S* %s, i64 0, i32 1, i32 0 20 ret void 21} 22 23; CHECK: Function: t2_rev 24; CHECK: MayAlias: i32* %gep1, i32* %gep2 25define void @t2_rev(%struct.S* %s, i32* %q) { 26 %in_array = load i32, i32* %q, !range !0 27 %gep1 = getelementptr inbounds %struct.S, %struct.S* %s, i64 0, i32 1, i32 0 28 %gep2 = getelementptr inbounds %struct.S, %struct.S* %s, i64 0, i32 1, i32 %in_array 29 ret void 30} 31 32; CHECK: Function: t3_fwd 33; CHECK: NoAlias: i32* %gep1, i32* %gep2 34define void @t3_fwd(%struct.S* %s, i32* %q) { 35 %knownzero = load i32, i32* %q, !range !1 36 %gep1 = getelementptr inbounds %struct.S, %struct.S* %s, i64 0, i32 1, i32 %knownzero 37 %gep2 = getelementptr inbounds %struct.S, %struct.S* %s, i64 0, i32 1, i32 1 38 ret void 39} 40 41; CHECK: Function: t3_rev 42; CHECK: NoAlias: i32* %gep1, i32* %gep2 43define void @t3_rev(%struct.S* %s, i32* %q) { 44 %knownzero = load i32, i32* %q, !range !1 45 %gep1 = getelementptr inbounds %struct.S, %struct.S* %s, i64 0, i32 1, i32 1 46 %gep2 = getelementptr inbounds %struct.S, %struct.S* %s, i64 0, i32 1, i32 %knownzero 47 ret void 48} 49 50; CHECK: Function: member_after 51; CHECK: NoAlias: i32* %gep1, i32* %gep2 52define void @member_after(%struct.S* %s, i32* %q) { 53 %in_array = load i32, i32* %q, !range !0 54 %gep1 = getelementptr inbounds %struct.S, %struct.S* %s, i64 0, i32 1, i32 %in_array 55 %gep2 = getelementptr inbounds %struct.S, %struct.S* %s, i64 0, i32 2 56 ret void 57} 58 59; CHECK: Function: member_after_rev 60; CHECK: NoAlias: i32* %gep1, i32* %gep2 61define void @member_after_rev(%struct.S* %s, i32* %q) { 62 %in_array = load i32, i32* %q, !range !0 63 %gep2 = getelementptr inbounds %struct.S, %struct.S* %s, i64 0, i32 2 64 %gep1 = getelementptr inbounds %struct.S, %struct.S* %s, i64 0, i32 1, i32 %in_array 65 ret void 66} 67 68; CHECK: Function: member_before 69; CHECK: NoAlias: i32* %gep1, i32* %gep2 70define void @member_before(%struct.S* %s, i32* %q) { 71 %in_array = load i32, i32* %q, !range !0 72 %gep1 = getelementptr inbounds %struct.S, %struct.S* %s, i64 0, i32 1, i32 %in_array 73 %gep2 = getelementptr inbounds %struct.S, %struct.S* %s, i64 0, i32 0 74 ret void 75} 76 77; CHECK: Function: member_before_rev 78; CHECK: NoAlias: i32* %gep1, i32* %gep2 79define void @member_before_rev(%struct.S* %s, i32* %q) { 80 %in_array = load i32, i32* %q, !range !0 81 %gep2 = getelementptr inbounds %struct.S, %struct.S* %s, i64 0, i32 0 82 %gep1 = getelementptr inbounds %struct.S, %struct.S* %s, i64 0, i32 1, i32 %in_array 83 ret void 84} 85 86; CHECK: Function: t5 87; CHECK-NEXT: MayAlias: %struct.S2* %s, i32* %q 88; CHECK-NEXT: MayAlias: %struct.S2* %s, i32* %gep1 89; CHECK-NEXT: MayAlias: i32* %gep1, i32* %q 90; CHECK-NEXT: PartialAlias (off 4): %struct.S2* %s, i32* %gep2 91; CHECK-NEXT: MayAlias: i32* %gep2, i32* %q 92; CHECK-NEXT: NoAlias: i32* %gep1, i32* %gep2 93define void @t5(%struct.S2* %s, i32* %q) { 94 %in_array = load i32, i32* %q, !range !3 95 %gep1 = getelementptr inbounds %struct.S2, %struct.S2* %s, i64 0, i32 2, i32 %in_array 96 %gep2 = getelementptr inbounds %struct.S2, %struct.S2* %s, i64 0, i32 1, i32 0 97 ret void 98} 99 100; CHECK: Function: t6 101; CHECK-NEXT: MayAlias: %struct.S2* %s, i32* %q 102; CHECK-NEXT: MayAlias: %struct.S2* %s, i32* %gep1 103; CHECK-NEXT: MayAlias: i32* %gep1, i32* %q 104; CHECK-NEXT: PartialAlias (off 16): %struct.S2* %s, i32* %gep2 105; CHECK-NEXT: MayAlias: i32* %gep2, i32* %q 106; CHECK-NEXT: MayAlias: i32* %gep1, i32* %gep2 107define void @t6(%struct.S2* %s, i32* %q) { 108 %in_array = load i32, i32* %q, !range !3 109 %gep1 = getelementptr inbounds %struct.S2, %struct.S2* %s, i64 0, i32 2, i32 %in_array 110 %gep2 = getelementptr inbounds %struct.S2, %struct.S2* %s, i64 0, i32 1, i32 3 111 ret void 112} 113 114; CHECK: Function: t7 115; CHECK-NEXT: MayAlias: %struct.S2* %s, i32* %q 116; CHECK-NEXT: MayAlias: %struct.S2* %s, i32* %gep1 117; CHECK-NEXT: MayAlias: i32* %gep1, i32* %q 118; CHECK-NEXT: PartialAlias (off 20): %struct.S2* %s, i32* %gep2 119; CHECK-NEXT: MayAlias: i32* %gep2, i32* %q 120; CHECK-NEXT: NoAlias: i32* %gep1, i32* %gep2 121define void @t7(%struct.S2* %s, i32* %q) { 122 %in_array = load i32, i32* %q, !range !4 123 %gep1 = getelementptr inbounds %struct.S2, %struct.S2* %s, i64 0, i32 2, i32 %in_array 124 %gep2 = getelementptr inbounds %struct.S2, %struct.S2* %s, i64 0, i32 2, i32 0 125 ret void 126} 127 128; CHECK: Function: t8 129; CHECK-NEXT: MayAlias: %struct.S2* %s, i32* %q 130; CHECK-NEXT: MayAlias: %struct.S2* %s, i32* %gep1 131; CHECK-NEXT: MayAlias: i32* %gep1, i32* %q 132; CHECK-NEXT: PartialAlias (off 24): %struct.S2* %s, i32* %gep2 133; CHECK-NEXT: MayAlias: i32* %gep2, i32* %q 134; CHECK-NEXT: MayAlias: i32* %gep1, i32* %gep2 135define void @t8(%struct.S2* %s, i32* %q) { 136 %in_array = load i32, i32* %q, !range !4 137 %gep1 = getelementptr inbounds %struct.S2, %struct.S2* %s, i64 0, i32 2, i32 %in_array 138 %gep2 = getelementptr inbounds %struct.S2, %struct.S2* %s, i64 0, i32 2, i32 1 139 ret void 140} 141 142; CHECK: Function: t9 143; CHECK-NEXT: MayAlias: %struct.S2* %s, i32* %q 144; CHECK-NEXT: MayAlias: %struct.S2* %s, i32* %gep1 145; CHECK-NEXT: MayAlias: i32* %gep1, i32* %q 146; CHECK-NEXT: PartialAlias (off 20): %struct.S2* %s, i32* %gep2 147; CHECK-NEXT: MayAlias: i32* %gep2, i32* %q 148; CHECK-NEXT: NoAlias: i32* %gep1, i32* %gep2 149define void @t9(%struct.S2* %s, i32* %q) { 150 %in_array = load i32, i32* %q, !range !5 151 %gep1 = getelementptr inbounds %struct.S2, %struct.S2* %s, i64 0, i32 1, i32 %in_array 152 %gep2 = getelementptr inbounds %struct.S2, %struct.S2* %s, i64 0, i32 2, i32 0 153 ret void 154} 155 156; CHECK: Function: t10 157; CHECK-NEXT: MayAlias: %struct.S2* %s, i32* %q 158; CHECK-NEXT: MayAlias: %struct.S2* %s, i32* %gep1 159; CHECK-NEXT: MayAlias: i32* %gep1, i32* %q 160; CHECK-NEXT: PartialAlias (off 4): %struct.S2* %s, i32* %gep2 161; CHECK-NEXT: MayAlias: i32* %gep2, i32* %q 162; CHECK-NEXT: MayAlias: i32* %gep1, i32* %gep2 163define void @t10(%struct.S2* %s, i32* %q) { 164 %in_array = load i32, i32* %q, !range !5 165 %gep1 = getelementptr inbounds %struct.S2, %struct.S2* %s, i64 0, i32 2, i32 %in_array 166 %gep2 = getelementptr inbounds %struct.S2, %struct.S2* %s, i64 0, i32 1, i32 0 167 ret void 168} 169 170; CHECK: Function: zeroext_index 171; CHECK-NEXT: MayAlias: [256 x i32]* %s, i8* %q 172; CHECK-NEXT: MayAlias: [256 x i32]* %s, i32* %gep 173; CHECK-NEXT: MayAlias: i32* %gep, i8* %q 174define void @zeroext_index([256 x i32]* %s, i8* %q) { 175 %a = load i8, i8* %q, !range !6 176 %in_array = zext i8 %a to i32 177 %gep = getelementptr inbounds [256 x i32], [256 x i32]* %s, i64 0, i32 %in_array 178 ret void 179} 180 181; CHECK-LABEL: Function: multiple 182; CHECK: MayAlias: i32* %p, i32* %p.01 183; CHECK: MayAlias: i32* %p, i32* %p.02 184; CHECK: MayAlias: i32* %p.01, i32* %p.02 185; CHECK: NoAlias: i32* %p.01, i32* %p.2 186; CHECK: MayAlias: i32* %p.02, i32* %p.2 187; CHECK: NoAlias: i32* %p.01, i32* %p.3 188; CHECK: NoAlias: i32* %p.02, i32* %p.3 189define void @multiple(i32* %p, i32* %o1_ptr, i32* %o2_ptr) { 190 %o1 = load i32, i32* %o1_ptr, !range !0 191 %o2 = load i32, i32* %o2_ptr, !range !0 192 %p.01 = getelementptr i32, i32* %p, i32 %o1 ; p + [0, 1] 193 %p.02 = getelementptr i32, i32* %p.01, i32 %o2 ; p + [0, 2] 194 %p.2 = getelementptr i32, i32* %p, i32 2 195 %p.3 = getelementptr i32, i32* %p, i32 3 196 ret void 197} 198 199; p.neg1 and p.o.1 don't alias, even though the addition o+1 may overflow. 200; While it makes INT_MIN a possible offset, offset -1 is not possible. 201; CHECK-LABEL: Function: benign_overflow 202; CHECK: MayAlias: i8* %p, i8* %p.o 203; CHECK: MayAlias: i8* %p.neg1, i8* %p.o 204; CHECK: MayAlias: i8* %p, i8* %p.o.1 205; CHECK: NoAlias: i8* %p.neg1, i8* %p.o.1 206; CHECK: NoAlias: i8* %p.o, i8* %p.o.1 207define void @benign_overflow(i8* %p, i64 %o) { 208 %c = icmp sge i64 %o, -1 209 call void @llvm.assume(i1 %c) 210 %p.neg1 = getelementptr i8, i8* %p, i64 -1 211 %p.o = getelementptr i8, i8* %p, i64 %o 212 %p.o.1 = getelementptr i8, i8* %p.o, i64 1 213 ret void 214} 215 216declare void @llvm.assume(i1) 217 218 219!0 = !{ i32 0, i32 2 } 220!1 = !{ i32 0, i32 1 } 221!2 = !{ i32 1, i32 2 } 222!3 = !{ i32 -2, i32 0 } 223!4 = !{ i32 1, i32 536870911 } 224!5 = !{ i32 -536870911, i32 4 } 225!6 = !{ i8 -2, i8 0 } 226