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