llvm.org GIT mirror llvm / 37d8ade
[BasicAA] Fix the handling of sext and zext in the analysis of GEPs. Hopefully this will end the GEPs saga! This commit reverts r245394, i.e., it reapplies r221876 while incorporating the fixes from D11847. r221876 was not reapplied alone because it was not safe and D11847 was not applied alone because it needs r221876 to produce correct results. This should fix PR24596. Original commit message for r221876: Let's try this again... This reverts r219432, plus a bug fix. Description of the bug in r219432 (by Nick): The bug was using AllPositive to break out of the loop; if the loop break condition i != e is changed to i != e && AllPositive then the test_modulo_analysis_with_global test I've added will fail as the Modulo will be calculated incorrectly (as the last loop iteration is skipped, so Modulo isn't updated with its Scale). Nick also adds this comment: ComputeSignBit is safe to use in loops as it takes into account phi nodes, and the == EK_ZeroEx check is safe in loops as, no matter how the variable changes between iterations, zero-extensions will always guarantee a zero sign bit. The isValueEqualInPotentialCycles check is therefore definitely not needed as all the variable analysis holds no matter how the variables change between loop iterations. And this patch also adds another enhancement to GetLinearExpression - basically to convert ConstantInts to Offsets (see test_const_eval and test_const_eval_scaled for the situations this improves). Original commit message: This reverts r218944, which reverted r218714, plus a bug fix. Description of the bug in r218714 (by Nick): The original patch forgot to check if the Scale in VariableGEPIndex flipped the sign of the variable. The BasicAA pass iterates over the instructions in the order they appear in the function, and so BasicAliasAnalysis::aliasGEP is called with the variable it first comes across as parameter GEP1. Adding a %reorder label puts the definition of %a after %b so aliasGEP is called with %b as the first parameter and %a as the second. aliasGEP later calculates that %a == %b + 1 - %idxprom where %idxprom >= 0 (if %a was passed as the first parameter it would calculate %b == %a - 1 + %idxprom where %idxprom >= 0) - ignoring that %idxprom is scaled by -1 here lead the patch to incorrectly conclude that %a > %b. Revised patch by Nick White, thanks! Thanks to Lang to isolating the bug. Slightly modified by me to add an early exit from the loop and avoid unnecessary, but expensive, function calls. Original commit message: Two related things: 1. Fixes a bug when calculating the offset in GetLinearExpression. The code previously used zext to extend the offset, so negative offsets were converted to large positive ones. 2. Enhance aliasGEP to deduce that, if the difference between two GEP allocations is positive and all the variables that govern the offset are also positive (i.e. the offset is strictly after the higher base pointer), then locations that fit in the gap between the two base pointers are NoAlias. Patch by Nick White! Message from D11847: Un-revert of r241981 and fix for PR23626. The 'Or' case of GetLinearExpression delegates to 'Add' if possible, and if not it returns an Opaque value. Unfortunately the Scale and Offsets weren't being set (and so defaulted to 0) - and a scale of zero effectively removes the variable from the GEP instruction. This meant that BasicAA would return MustAliases when it should have been returning PartialAliases (and PR23626 was an example of the GVN pass using an incorrect MustAlias to merge loads from what should have been different pointers). Differential Revision: http://reviews.llvm.org/D11847 Patch by Nick White <n.j.white@gmail.com>! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@246502 91177308-0d34-0410-b5e6-96231b3b80d8 Quentin Colombet 4 years ago
7 changed file(s) with 710 addition(s) and 60 deletion(s). Raw diff Collapse all Expand all
108108 }
109109
110110 private:
111 enum ExtensionKind { EK_NotExtended, EK_SignExt, EK_ZeroExt };
112
111 // A linear transformation of a Value; this class represents ZExt(SExt(V,
112 // SExtBits), ZExtBits) * Scale + Offset.
113113 struct VariableGEPIndex {
114
115 // An opaque Value - we can't decompose this further.
114116 const Value *V;
115 ExtensionKind Extension;
117
118 // We need to track what extensions we've done as we consider the same Value
119 // with different extensions as different variables in a GEP's linear
120 // expression;
121 // e.g.: if V == -1, then sext(x) != zext(x).
122 unsigned ZExtBits;
123 unsigned SExtBits;
124
116125 int64_t Scale;
117126
118127 bool operator==(const VariableGEPIndex &Other) const {
119 return V == Other.V && Extension == Other.Extension &&
120 Scale == Other.Scale;
128 return V == Other.V && ZExtBits == Other.ZExtBits &&
129 SExtBits == Other.SExtBits && Scale == Other.Scale;
121130 }
122131
123132 bool operator!=(const VariableGEPIndex &Other) const {
149158 /// Tracks instructions visited by pointsToConstantMemory.
150159 SmallPtrSet Visited;
151160
152 static Value *GetLinearExpression(Value *V, APInt &Scale, APInt &Offset,
153 ExtensionKind &Extension,
154 const DataLayout &DL, unsigned Depth,
155 AssumptionCache *AC, DominatorTree *DT);
161 static const Value *
162 GetLinearExpression(const Value *V, APInt &Scale, APInt &Offset,
163 unsigned &ZExtBits, unsigned &SExtBits,
164 const DataLayout &DL, unsigned Depth, AssumptionCache *AC,
165 DominatorTree *DT, bool &NSW, bool &NUW);
156166
157167 static const Value *
158168 DecomposeGEPExpression(const Value *V, int64_t &BaseOffs,
159169 SmallVectorImpl &VarIndices,
160170 bool &MaxLookupReached, const DataLayout &DL,
161171 AssumptionCache *AC, DominatorTree *DT);
172 /// \brief A Heuristic for aliasGEP that searches for a constant offset
173 /// between the variables.
174 ///
175 /// GetLinearExpression has some limitations, as generally zext(%x + 1)
176 /// != zext(%x) + zext(1) if the arithmetic overflows. GetLinearExpression
177 /// will therefore conservatively refuse to decompose these expressions.
178 /// However, we know that, for all %x, zext(%x) != zext(%x + 1), even if
179 /// the addition overflows.
180 bool
181 constantOffsetHeuristic(const SmallVectorImpl &VarIndices,
182 uint64_t V1Size, uint64_t V2Size, int64_t BaseOffset,
183 const DataLayout *DL, AssumptionCache *AC,
184 DominatorTree *DT);
162185
163186 bool isValueEqualInPotentialCycles(const Value *V1, const Value *V2);
164187
176176 ///
177177 /// Note that this looks through extends, so the high bits may not be
178178 /// represented in the result.
179 /*static*/ Value *BasicAliasAnalysis::GetLinearExpression(
180 Value *V, APInt &Scale, APInt &Offset, ExtensionKind &Extension,
181 const DataLayout &DL, unsigned Depth, AssumptionCache *AC,
182 DominatorTree *DT) {
179 /*static*/ const Value *BasicAliasAnalysis::GetLinearExpression(
180 const Value *V, APInt &Scale, APInt &Offset, unsigned &ZExtBits,
181 unsigned &SExtBits, const DataLayout &DL, unsigned Depth,
182 AssumptionCache *AC, DominatorTree *DT, bool &NSW, bool &NUW) {
183183 assert(V->getType()->isIntegerTy() && "Not an integer value");
184184
185185 // Limit our recursion depth.
189189 return V;
190190 }
191191
192 if (BinaryOperator *BOp = dyn_cast>(V)) {
192 if (const ConstantInt *Const = dyn_cast>(V)) {
193 // if it's a constant, just convert it to an offset and remove the variable.
194 // If we've been called recursively the Offset bit width will be greater
195 // than the constant's (the Offset's always as wide as the outermost call),
196 // so we'll zext here and process any extension in the isa &
197 // isa cases below.
198 Offset += Const->getValue().zextOrSelf(Offset.getBitWidth());
199 assert(Scale == 0 && "Constant values don't have a scale");
200 return V;
201 }
202
203 if (const BinaryOperator *BOp = dyn_cast(V)) {
193204 if (ConstantInt *RHSC = dyn_cast(BOp->getOperand(1))) {
205
206 // If we've been called recursively then Offset and Scale will be wider
207 // that the BOp operands. We'll always zext it here as we'll process sign
208 // extensions below (see the isa / isa cases).
209 APInt RHS = RHSC->getValue().zextOrSelf(Offset.getBitWidth());
210
194211 switch (BOp->getOpcode()) {
195212 default:
196 break;
213 // We don't understand this instruction, so we can't decompose it any
214 // further.
215 Scale = 1;
216 Offset = 0;
217 return V;
197218 case Instruction::Or:
198219 // X|C == X+C if all the bits in C are unset in X. Otherwise we can't
199220 // analyze it.
200221 if (!MaskedValueIsZero(BOp->getOperand(0), RHSC->getValue(), DL, 0, AC,
201 BOp, DT))
202 break;
222 BOp, DT)) {
223 Scale = 1;
224 Offset = 0;
225 return V;
226 }
203227 // FALL THROUGH.
204228 case Instruction::Add:
205 V = GetLinearExpression(BOp->getOperand(0), Scale, Offset, Extension,
206 DL, Depth + 1, AC, DT);
207 Offset += RHSC->getValue();
229 V = GetLinearExpression(BOp->getOperand(0), Scale, Offset, ZExtBits,
230 SExtBits, DL, Depth + 1, AC, DT, NSW, NUW);
231 Offset += RHS;
232 break;
233 case Instruction::Sub:
234 V = GetLinearExpression(BOp->getOperand(0), Scale, Offset, ZExtBits,
235 SExtBits, DL, Depth + 1, AC, DT, NSW, NUW);
236 Offset -= RHS;
237 break;
238 case Instruction::Mul:
239 V = GetLinearExpression(BOp->getOperand(0), Scale, Offset, ZExtBits,
240 SExtBits, DL, Depth + 1, AC, DT, NSW, NUW);
241 Offset *= RHS;
242 Scale *= RHS;
243 break;
244 case Instruction::Shl:
245 V = GetLinearExpression(BOp->getOperand(0), Scale, Offset, ZExtBits,
246 SExtBits, DL, Depth + 1, AC, DT, NSW, NUW);
247 Offset <<= RHS.getLimitedValue();
248 Scale <<= RHS.getLimitedValue();
249 // the semantics of nsw and nuw for left shifts don't match those of
250 // multiplications, so we won't propagate them.
251 NSW = NUW = false;
208252 return V;
209 case Instruction::Mul:
210 V = GetLinearExpression(BOp->getOperand(0), Scale, Offset, Extension,
211 DL, Depth + 1, AC, DT);
212 Offset *= RHSC->getValue();
213 Scale *= RHSC->getValue();
214 return V;
215 case Instruction::Shl:
216 V = GetLinearExpression(BOp->getOperand(0), Scale, Offset, Extension,
217 DL, Depth + 1, AC, DT);
218 Offset <<= RHSC->getValue().getLimitedValue();
219 Scale <<= RHSC->getValue().getLimitedValue();
220 return V;
221 }
253 }
254
255 if (isa(BOp)) {
256 NUW &= BOp->hasNoUnsignedWrap();
257 NSW &= BOp->hasNoSignedWrap();
258 }
259 return V;
222260 }
223261 }
224262
225263 // Since GEP indices are sign extended anyway, we don't care about the high
226264 // bits of a sign or zero extended value - just scales and offsets. The
227265 // extensions have to be consistent though.
228 if ((isa(V) && Extension != EK_ZeroExt) ||
229 (isa(V) && Extension != EK_SignExt)) {
266 if (isa(V) || isa(V)) {
230267 Value *CastOp = cast(V)->getOperand(0);
231 unsigned OldWidth = Scale.getBitWidth();
268 unsigned NewWidth = V->getType()->getPrimitiveSizeInBits();
232269 unsigned SmallWidth = CastOp->getType()->getPrimitiveSizeInBits();
233 Scale = Scale.trunc(SmallWidth);
234 Offset = Offset.trunc(SmallWidth);
235 Extension = isa(V) ? EK_SignExt : EK_ZeroExt;
236
237 Value *Result = GetLinearExpression(CastOp, Scale, Offset, Extension, DL,
238 Depth + 1, AC, DT);
239 Scale = Scale.zext(OldWidth);
240 Offset = Offset.zext(OldWidth);
270 unsigned OldZExtBits = ZExtBits, OldSExtBits = SExtBits;
271 const Value *Result =
272 GetLinearExpression(CastOp, Scale, Offset, ZExtBits, SExtBits, DL,
273 Depth + 1, AC, DT, NSW, NUW);
274
275 // zext(zext(%x)) == zext(%x), and similiarly for sext; we'll handle this
276 // by just incrementing the number of bits we've extended by.
277 unsigned ExtendedBy = NewWidth - SmallWidth;
278
279 if (isa(V) && ZExtBits == 0) {
280 // sext(sext(%x, a), b) == sext(%x, a + b)
281
282 if (NSW) {
283 // We haven't sign-wrapped, so it's valid to decompose sext(%x + c)
284 // into sext(%x) + sext(c). We'll sext the Offset ourselves:
285 unsigned OldWidth = Offset.getBitWidth();
286 Offset = Offset.trunc(SmallWidth).sext(NewWidth).zextOrSelf(OldWidth);
287 } else {
288 // We may have signed-wrapped, so don't decompose sext(%x + c) into
289 // sext(%x) + sext(c)
290 Scale = 1;
291 Offset = 0;
292 Result = CastOp;
293 ZExtBits = OldZExtBits;
294 SExtBits = OldSExtBits;
295 }
296 SExtBits += ExtendedBy;
297 } else {
298 // sext(zext(%x, a), b) = zext(zext(%x, a), b) = zext(%x, a + b)
299
300 if (!NUW) {
301 // We may have unsigned-wrapped, so don't decompose zext(%x + c) into
302 // zext(%x) + zext(c)
303 Scale = 1;
304 Offset = 0;
305 Result = CastOp;
306 ZExtBits = OldZExtBits;
307 SExtBits = OldSExtBits;
308 }
309 ZExtBits += ExtendedBy;
310 }
241311
242312 return Result;
243313 }
317387 gep_type_iterator GTI = gep_type_begin(GEPOp);
318388 for (User::const_op_iterator I = GEPOp->op_begin() + 1, E = GEPOp->op_end();
319389 I != E; ++I) {
320 Value *Index = *I;
390 const Value *Index = *I;
321391 // Compute the (potentially symbolic) offset in bytes for this index.
322392 if (StructType *STy = dyn_cast(*GTI++)) {
323393 // For a struct, add the member offset.
330400 }
331401
332402 // For an array/pointer, add the element offset, explicitly scaled.
333 if (ConstantInt *CIdx = dyn_cast(Index)) {
403 if (const ConstantInt *CIdx = dyn_cast(Index)) {
334404 if (CIdx->isZero())
335405 continue;
336406 BaseOffs += DL.getTypeAllocSize(*GTI) * CIdx->getSExtValue();
338408 }
339409
340410 uint64_t Scale = DL.getTypeAllocSize(*GTI);
341 ExtensionKind Extension = EK_NotExtended;
411 unsigned ZExtBits = 0, SExtBits = 0;
342412
343413 // If the integer type is smaller than the pointer size, it is implicitly
344414 // sign extended to pointer size.
345415 unsigned Width = Index->getType()->getIntegerBitWidth();
346 if (DL.getPointerSizeInBits(AS) > Width)
347 Extension = EK_SignExt;
416 unsigned PointerSize = DL.getPointerSizeInBits(AS);
417 if (PointerSize > Width)
418 SExtBits += PointerSize - Width;
348419
349420 // Use GetLinearExpression to decompose the index into a C1*V+C2 form.
350421 APInt IndexScale(Width, 0), IndexOffset(Width, 0);
351 Index = GetLinearExpression(Index, IndexScale, IndexOffset, Extension, DL,
352 0, AC, DT);
422 bool NSW = true, NUW = true;
423 Index = GetLinearExpression(Index, IndexScale, IndexOffset, ZExtBits,
424 SExtBits, DL, 0, AC, DT, NSW, NUW);
353425
354426 // The GEP index scale ("Scale") scales C1*V+C2, yielding (C1*V+C2)*Scale.
355427 // This gives us an aggregate computation of (C1*Scale)*V + C2*Scale.
361433 // A[x][x] -> x*16 + x*4 -> x*20
362434 // This also ensures that 'x' only appears in the index list once.
363435 for (unsigned i = 0, e = VarIndices.size(); i != e; ++i) {
364 if (VarIndices[i].V == Index && VarIndices[i].Extension == Extension) {
436 if (VarIndices[i].V == Index && VarIndices[i].ZExtBits == ZExtBits &&
437 VarIndices[i].SExtBits == SExtBits) {
365438 Scale += VarIndices[i].Scale;
366439 VarIndices.erase(VarIndices.begin() + i);
367440 break;
370443
371444 // Make sure that we have a scale that makes sense for this target's
372445 // pointer size.
373 if (unsigned ShiftBits = 64 - DL.getPointerSizeInBits(AS)) {
446 if (unsigned ShiftBits = 64 - PointerSize) {
374447 Scale <<= ShiftBits;
375448 Scale = (int64_t)Scale >> ShiftBits;
376449 }
377450
378451 if (Scale) {
379 VariableGEPIndex Entry = {Index, Extension,
452 VariableGEPIndex Entry = {Index, ZExtBits, SExtBits,
380453 static_cast(Scale)};
381454 VarIndices.push_back(Entry);
382455 }
9471020 }
9481021 }
9491022
950 // Try to distinguish something like &A[i][1] against &A[42][0].
951 // Grab the least significant bit set in any of the scales.
9521023 if (!GEP1VariableIndices.empty()) {
9531024 uint64_t Modulo = 0;
954 for (unsigned i = 0, e = GEP1VariableIndices.size(); i != e; ++i)
1025 bool AllPositive = true;
1026 for (unsigned i = 0, e = GEP1VariableIndices.size(); i != e; ++i) {
1027
1028 // Try to distinguish something like &A[i][1] against &A[42][0].
1029 // Grab the least significant bit set in any of the scales. We
1030 // don't need std::abs here (even if the scale's negative) as we'll
1031 // be ^'ing Modulo with itself later.
9551032 Modulo |= (uint64_t)GEP1VariableIndices[i].Scale;
1033
1034 if (AllPositive) {
1035 // If the Value could change between cycles, then any reasoning about
1036 // the Value this cycle may not hold in the next cycle. We'll just
1037 // give up if we can't determine conditions that hold for every cycle:
1038 const Value *V = GEP1VariableIndices[i].V;
1039
1040 bool SignKnownZero, SignKnownOne;
1041 ComputeSignBit(const_cast(V), SignKnownZero, SignKnownOne, *DL,
1042 0, AC1, nullptr, DT);
1043
1044 // Zero-extension widens the variable, and so forces the sign
1045 // bit to zero.
1046 bool IsZExt = GEP1VariableIndices[i].ZExtBits > 0 || isa(V);
1047 SignKnownZero |= IsZExt;
1048 SignKnownOne &= !IsZExt;
1049
1050 // If the variable begins with a zero then we know it's
1051 // positive, regardless of whether the value is signed or
1052 // unsigned.
1053 int64_t Scale = GEP1VariableIndices[i].Scale;
1054 AllPositive =
1055 (SignKnownZero && Scale >= 0) || (SignKnownOne && Scale < 0);
1056 }
1057 }
1058
9561059 Modulo = Modulo ^ (Modulo & (Modulo - 1));
9571060
9581061 // We can compute the difference between the two addresses
9621065 if (V1Size != MemoryLocation::UnknownSize &&
9631066 V2Size != MemoryLocation::UnknownSize && ModOffset >= V2Size &&
9641067 V1Size <= Modulo - ModOffset)
1068 return NoAlias;
1069
1070 // If we know all the variables are positive, then GEP1 >= GEP1BasePtr.
1071 // If GEP1BasePtr > V2 (GEP1BaseOffset > 0) then we know the pointers
1072 // don't alias if V2Size can fit in the gap between V2 and GEP1BasePtr.
1073 if (AllPositive && GEP1BaseOffset > 0 && V2Size <= (uint64_t)GEP1BaseOffset)
1074 return NoAlias;
1075
1076 if (constantOffsetHeuristic(GEP1VariableIndices, V1Size, V2Size,
1077 GEP1BaseOffset, DL, AC1, DT))
9651078 return NoAlias;
9661079 }
9671080
13321445
13331446 for (unsigned i = 0, e = Src.size(); i != e; ++i) {
13341447 const Value *V = Src[i].V;
1335 ExtensionKind Extension = Src[i].Extension;
1448 unsigned ZExtBits = Src[i].ZExtBits, SExtBits = Src[i].SExtBits;
13361449 int64_t Scale = Src[i].Scale;
13371450
13381451 // Find V in Dest. This is N^2, but pointer indices almost never have more
13391452 // than a few variable indexes.
13401453 for (unsigned j = 0, e = Dest.size(); j != e; ++j) {
13411454 if (!isValueEqualInPotentialCycles(Dest[j].V, V) ||
1342 Dest[j].Extension != Extension)
1455 Dest[j].ZExtBits != ZExtBits || Dest[j].SExtBits != SExtBits)
13431456 continue;
13441457
13451458 // If we found it, subtract off Scale V's from the entry in Dest. If it
13541467
13551468 // If we didn't consume this entry, add it to the end of the Dest list.
13561469 if (Scale) {
1357 VariableGEPIndex Entry = {V, Extension, -Scale};
1470 VariableGEPIndex Entry = {V, ZExtBits, SExtBits, -Scale};
13581471 Dest.push_back(Entry);
13591472 }
13601473 }
13611474 }
1475
1476 bool BasicAliasAnalysis::constantOffsetHeuristic(
1477 const SmallVectorImpl &VarIndices, uint64_t V1Size,
1478 uint64_t V2Size, int64_t BaseOffset, const DataLayout *DL,
1479 AssumptionCache *AC, DominatorTree *DT) {
1480 if (VarIndices.size() != 2 || V1Size == MemoryLocation::UnknownSize ||
1481 V2Size == MemoryLocation::UnknownSize || !DL)
1482 return false;
1483
1484 const VariableGEPIndex &Var0 = VarIndices[0], &Var1 = VarIndices[1];
1485
1486 if (Var0.ZExtBits != Var1.ZExtBits || Var0.SExtBits != Var1.SExtBits ||
1487 Var0.Scale != -Var1.Scale)
1488 return false;
1489
1490 unsigned Width = Var1.V->getType()->getIntegerBitWidth();
1491
1492 // We'll strip off the Extensions of Var0 and Var1 and do another round
1493 // of GetLinearExpression decomposition. In the example above, if Var0
1494 // is zext(%x + 1) we should get V1 == %x and V1Offset == 1.
1495
1496 APInt V0Scale(Width, 0), V0Offset(Width, 0), V1Scale(Width, 0),
1497 V1Offset(Width, 0);
1498 bool NSW = true, NUW = true;
1499 unsigned V0ZExtBits = 0, V0SExtBits = 0, V1ZExtBits = 0, V1SExtBits = 0;
1500 const Value *V0 = GetLinearExpression(Var0.V, V0Scale, V0Offset, V0ZExtBits,
1501 V0SExtBits, *DL, 0, AC, DT, NSW, NUW);
1502 NSW = true, NUW = true;
1503 const Value *V1 = GetLinearExpression(Var1.V, V1Scale, V1Offset, V1ZExtBits,
1504 V1SExtBits, *DL, 0, AC, DT, NSW, NUW);
1505
1506 if (V0Scale != V1Scale || V0ZExtBits != V1ZExtBits ||
1507 V0SExtBits != V1SExtBits || !isValueEqualInPotentialCycles(V0, V1))
1508 return false;
1509
1510 // We have a hit - Var0 and Var1 only differ by a constant offset!
1511
1512 // If we've been sext'ed then zext'd the maximum difference between Var0 and
1513 // Var1 is possible to calculate, but we're just interested in the absolute
1514 // minumum difference between the two. The minimum distance may occur due to
1515 // wrapping; consider "add i3 %i, 5": if %i == 7 then 7 + 5 mod 8 == 4, and so
1516 // the minimum distance between %i and %i + 5 is 3.
1517 APInt MinDiff = V0Offset - V1Offset,
1518 Wrapped = APInt::getMaxValue(Width) - MinDiff + APInt(Width, 1);
1519 MinDiff = APIntOps::umin(MinDiff, Wrapped);
1520 uint64_t MinDiffBytes = MinDiff.getZExtValue() * std::abs(Var0.Scale);
1521
1522 // We can't definitely say whether GEP1 is before or after V2 due to wrapping
1523 // arithmetic (i.e. for some values of GEP1 and V2 GEP1 < V2, and for other
1524 // values GEP1 > V2). We'll therefore only declare NoAlias if both V1Size and
1525 // V2Size can fit in the MinDiffBytes gap.
1526 return V1Size + std::abs(BaseOffset) <= MinDiffBytes &&
1527 V2Size + std::abs(BaseOffset) <= MinDiffBytes;
1528 }
0 ; RUN: opt < %s -basicaa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
1 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
2 target triple = "x86_64-unknown-linux-gnu"
3
4 @c = external global i32
5
6 ; CHECK-LABEL: f
7 ; CHECK: PartialAlias: i32* %arrayidx, i32* %arrayidx6
8 define void @f() {
9 %idxprom = zext i32 undef to i64
10 %add4 = add i32 0, 1
11 %idxprom5 = zext i32 %add4 to i64
12 %arrayidx6 = getelementptr inbounds i32, i32* @c, i64 %idxprom5
13 %arrayidx = getelementptr inbounds i32, i32* @c, i64 %idxprom
14 ret void
15 }
16
0 ; RUN: opt < %s -basicaa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
1 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
2 target triple = "x86_64-apple-darwin13.4.0"
3
4 ; CHECK-LABEL: compute1
5 ; CHECK: PartialAlias: i32* %arrayidx8, i32* %out
6 ; CHECK: PartialAlias: i32* %arrayidx11, i32* %out
7 ; CHECK: PartialAlias: i32* %arrayidx11, i32* %arrayidx8
8 ; CHECK: PartialAlias: i32* %arrayidx14, i32* %out
9 ; CHECK: PartialAlias: i32* %arrayidx14, i32* %arrayidx8
10 ; CHECK: PartialAlias: i32* %arrayidx11, i32* %arrayidx14
11 define void @compute1(i32 %num.0.lcssa, i32* %out) {
12 %idxprom = zext i32 %num.0.lcssa to i64
13 %arrayidx8 = getelementptr inbounds i32, i32* %out, i64 %idxprom
14 %add9 = or i32 %num.0.lcssa, 1
15 %idxprom10 = zext i32 %add9 to i64
16 %arrayidx11 = getelementptr inbounds i32, i32* %out, i64 %idxprom10
17 %add12 = or i32 %num.0.lcssa, 2
18 %idxprom13 = zext i32 %add12 to i64
19 %arrayidx14 = getelementptr inbounds i32, i32* %out, i64 %idxprom13
20 ret void
21 }
22
23 ; CHECK-LABEL: compute2
24 ; CHECK: PartialAlias: i32* %arrayidx11, i32* %out.addr
25 define void @compute2(i32 %num, i32* %out.addr) {
26 %add9 = add i32 %num, 1
27 %idxprom10 = zext i32 %add9 to i64
28 %arrayidx11 = getelementptr inbounds i32, i32* %out.addr, i64 %idxprom10
29 ret void
30 }
3838
3939 ; CHECK-LABEL: pr18068
4040 ; CHECK: MayAlias: i32* %0, i32* %arrayidx5
41 ; CHECK: NoAlias: i32* %arrayidx13, i32* %arrayidx5
4142
4243 define i32 @pr18068(i32* %jj7, i32* %j) {
4344 entry:
0 ; RUN: opt < %s -basicaa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
1 target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
2 target triple = "thumbv7--linux-gnueabi"
3
4 ; CHECK-LABEL: test_zext_sext_amounts255
5 ; CHECK: NoAlias: i8* %a, i8* %b
6 define void @test_zext_sext_amounts255(i8* %mem) {
7 %sext.1 = sext i8 255 to i16
8 %sext.zext.1 = zext i16 %sext.1 to i64
9 %sext.2 = sext i8 255 to i32
10 %sext.zext.2 = zext i32 %sext.2 to i64
11 %a = getelementptr inbounds i8, i8* %mem, i64 %sext.zext.1
12 %b = getelementptr inbounds i8, i8* %mem, i64 %sext.zext.2
13 ret void
14 }
15
16 ; CHECK-LABEL: test_zext_sext_amounts
17 ; CHECK: PartialAlias: i8* %a, i8* %b
18 ; %a and %b only PartialAlias as, although they're both zext(sext(%num)) they'll extend the sign by a different
19 ; number of bits before zext-ing the remainder.
20 define void @test_zext_sext_amounts(i8* %mem, i8 %num) {
21 %sext.1 = sext i8 %num to i16
22 %sext.zext.1 = zext i16 %sext.1 to i64
23 %sext.2 = sext i8 %num to i32
24 %sext.zext.2 = zext i32 %sext.2 to i64
25 %a = getelementptr inbounds i8, i8* %mem, i64 %sext.zext.1
26 %b = getelementptr inbounds i8, i8* %mem, i64 %sext.zext.2
27 ret void
28 }
29
30 ; CHECK-LABEL: based_on_pr18068
31 ; CHECK: NoAlias: i8* %a, i8* %b
32 ; CHECK: NoAlias: i8* %a, i8* %c
33 define void @based_on_pr18068(i32 %loaded, i8* %mem) {
34 %loaded.64 = zext i32 %loaded to i64
35 %add1 = add i32 %loaded, -1 ; unsigned wraps unless %loaded == 0
36 %add1.64 = zext i32 %add1 to i64 ; is zext(%loaded) always != zext(%loaded - 1)? Yes -> NoAlias
37 %sub1 = sub i32 %loaded, 1 ; unsigned wraps iff %loaded == 0
38 %sub1.64 = zext i32 %sub1 to i64 ; is zext(%loaded) always != zext(%loaded - 1)? Yes -> NoAlias
39 %a = getelementptr inbounds i8, i8* %mem, i64 %loaded.64
40 %b = getelementptr inbounds i8, i8* %mem, i64 %add1.64
41 %c = getelementptr inbounds i8, i8* %mem, i64 %sub1.64
42 ret void
43 }
44
45 ; CHECK-LABEL: test_path_dependence
46 ; CHECK: PartialAlias: i8* %a, i8* %b
47 ; CHECK: MustAlias: i8* %a, i8* %c
48 ; CHECK: PartialAlias: i8* %a, i8* %d
49 define void @test_path_dependence(i32 %p, i8* %mem) {
50 %p.minus1 = add i32 %p, -1 ; this will always unsigned-wrap, unless %p == 0
51 %p.minus1.64 = zext i32 %p.minus1 to i64
52 %p.64.again = add i64 %p.minus1.64, 1 ; either %p (if we wrapped) or 4294967296 (if we didn't)
53
54 %p.nsw.nuw.minus1 = sub nsw nuw i32 %p, 1 ; as nuw we know %p >= 1, and as nsw %p <= 2147483647
55 %p.nsw.nuw.minus1.64 = zext i32 %p.nsw.nuw.minus1 to i64
56 %p.nsw.nuw.64.again = add nsw nuw i64 %p.nsw.nuw.minus1.64, 1 ; ...so always exactly %p
57
58 %p.nsw.minus1 = sub nsw i32 %p, 1 ; only nsw, so can only guarantee %p != 0x10000000
59 %p.nsw.minus1.64 = zext i32 %p.nsw.minus1 to i64 ; when %p > 0x10000000 (ie <= 0 as a signed number) then the zext will make this a huge positive number
60 %p.nsw.64.again = add nsw i64 %p.nsw.minus1.64, 1 ; ...and so this is very much != %p
61
62 %p.64 = zext i32 %p to i64
63 %a = getelementptr inbounds i8, i8* %mem, i64 %p.64
64 %b = getelementptr inbounds i8, i8* %mem, i64 %p.64.again
65 %c = getelementptr inbounds i8, i8* %mem, i64 %p.nsw.nuw.64.again
66 %d = getelementptr inbounds i8, i8* %mem, i64 %p.nsw.64.again
67 ret void
68 }
69
70 ; CHECK-LABEL: test_zext_sext_255
71 ; CHECK: NoAlias: i8* %a, i8* %b
72 define void @test_zext_sext_255(i8* %mem) {
73 %zext.255 = zext i8 255 to i16 ; 0x00FF
74 %sext.255 = sext i8 255 to i16 ; 0xFFFF
75 %zext.sext.255 = zext i16 %sext.255 to i32 ; 0x0000FFFF
76 %sext.zext.255 = sext i16 %zext.255 to i32 ; 0x000000FF
77 %zext.zext.sext.255 = zext i32 %zext.sext.255 to i64
78 %zext.sext.zext.255 = zext i32 %sext.zext.255 to i64
79 %a = getelementptr inbounds i8, i8* %mem, i64 %zext.zext.sext.255
80 %b = getelementptr inbounds i8, i8* %mem, i64 %zext.sext.zext.255
81 ret void
82 }
83
84 ; CHECK-LABEL: test_zext_sext_num
85 ; CHECK: PartialAlias: i8* %a, i8* %b
86 ; %a and %b NoAlias if %num == 255 (see @test_zext_sext_255), but %a and %b NoAlias for other values of %num (e.g. 0)
87 define void @test_zext_sext_num(i8* %mem, i8 %num) {
88 %zext.num = zext i8 %num to i16
89 %sext.num = sext i8 %num to i16
90 %zext.sext.num = zext i16 %sext.num to i32
91 %sext.zext.num = sext i16 %zext.num to i32
92 %zext.zext.sext.num = zext i32 %zext.sext.num to i64
93 %zext.sext.zext.num = zext i32 %sext.zext.num to i64
94 %a = getelementptr inbounds i8, i8* %mem, i64 %zext.zext.sext.num
95 %b = getelementptr inbounds i8, i8* %mem, i64 %zext.sext.zext.num
96 ret void
97 }
98
99 ; CHECK-LABEL: uncompressStream
100 ; CHECK: MustAlias: i8* %a, i8* %b
101 ; CHECK: NoAlias: i8* %a, i8* %c
102 define void @uncompressStream(i8* %mem) {
103 %zext.255 = zext i8 255 to i32
104 %sext.255 = sext i8 255 to i32
105 %a = getelementptr inbounds i8, i8* %mem, i32 255
106 %b = getelementptr inbounds i8, i8* %mem, i32 %zext.255
107 %c = getelementptr inbounds i8, i8* %mem, i32 %sext.255
108 ret void
109 }
110
111 ; CHECK-LABEL: constantOffsetHeuristic_i3_i32
112 ; CHECK: NoAlias: i32* %a, i32* %b
113 ; CHECK: NoAlias: i32* %a, i32* %c
114 ; CHECK: NoAlias: i32* %b, i32* %c
115 define void @constantOffsetHeuristic_i3_i32(i32* %mem, i3 %val) {
116 %zext.plus.7 = add nsw i3 %val, 7
117 %zext.plus.4 = add nsw i3 %val, 4
118 %zext.val = zext i3 %val to i32
119 %zext.4 = zext i3 %zext.plus.4 to i32
120 %zext.7 = zext i3 %zext.plus.7 to i32
121 %a = getelementptr inbounds i32, i32* %mem, i32 %zext.4
122 %b = getelementptr inbounds i32, i32* %mem, i32 %zext.7
123 %c = getelementptr inbounds i32, i32* %mem, i32 %zext.val
124 ret void
125 }
126
127 ; CHECK-LABEL: constantOffsetHeuristic_i8_i32
128 ; CHECK: NoAlias: i32* %a, i32* %b
129 ; CHECK: NoAlias: i32* %a, i32* %c
130 ; CHECK: NoAlias: i32* %b, i32* %c
131 define void @constantOffsetHeuristic_i8_i32(i32* %mem, i8 %val) {
132 %zext.plus.7 = add nsw i8 %val, 7
133 %zext.plus.4 = add nsw i8 %val, 4
134 %zext.val = zext i8 %val to i32
135 %zext.4 = zext i8 %zext.plus.4 to i32
136 %zext.7 = zext i8 %zext.plus.7 to i32
137 %a = getelementptr inbounds i32, i32* %mem, i32 %zext.4
138 %b = getelementptr inbounds i32, i32* %mem, i32 %zext.7
139 %c = getelementptr inbounds i32, i32* %mem, i32 %zext.val
140 ret void
141 }
142
143 ; CHECK-LABEL: constantOffsetHeuristic_i3_i8
144 ; CHECK: PartialAlias: i32* %a, i32* %b
145 ; CHECK: NoAlias: i32* %a, i32* %c
146 ; CHECK: PartialAlias: i32* %b, i32* %c
147 define void @constantOffsetHeuristic_i3_i8(i8* %mem, i3 %val) {
148 %zext.plus.7 = add nsw i3 %val, 7
149 %zext.plus.4 = add nsw i3 %val, 4
150 %zext.val = zext i3 %val to i32
151 %zext.4 = zext i3 %zext.plus.4 to i32
152 %zext.7 = zext i3 %zext.plus.7 to i32
153 %a.8 = getelementptr inbounds i8, i8* %mem, i32 %zext.4
154 %b.8 = getelementptr inbounds i8, i8* %mem, i32 %zext.7
155 %c.8 = getelementptr inbounds i8, i8* %mem, i32 %zext.val
156 %a = bitcast i8* %a.8 to i32*
157 %b = bitcast i8* %b.8 to i32*
158 %c = bitcast i8* %c.8 to i32*
159 ret void
160 }
161
162 ; CHECK-LABEL: constantOffsetHeuristic_i8_i8
163 ; CHECK: PartialAlias: i32* %a, i32* %b
164 ; CHECK: NoAlias: i32* %a, i32* %c
165 ; CHECK: NoAlias: i32* %b, i32* %c
166 define void @constantOffsetHeuristic_i8_i8(i8* %mem, i8 %val) {
167 %zext.plus.7 = add nsw i8 %val, 7
168 %zext.plus.4 = add nsw i8 %val, 4
169 %zext.val = zext i8 %val to i32
170 %zext.4 = zext i8 %zext.plus.4 to i32
171 %zext.7 = zext i8 %zext.plus.7 to i32
172 %a.8 = getelementptr inbounds i8, i8* %mem, i32 %zext.4
173 %b.8 = getelementptr inbounds i8, i8* %mem, i32 %zext.7
174 %c.8 = getelementptr inbounds i8, i8* %mem, i32 %zext.val
175 %a = bitcast i8* %a.8 to i32*
176 %b = bitcast i8* %b.8 to i32*
177 %c = bitcast i8* %c.8 to i32*
178 ret void
179 }
0 ; RUN: opt < %s -basicaa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
1 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
2 target triple = "x86_64-unknown-linux-gnu"
3
4 ; CHECK-LABEL: test_with_zext
5 ; CHECK: NoAlias: i8* %a, i8* %b
6
7 define void @test_with_zext() {
8 %1 = tail call i8* @malloc(i64 120)
9 %a = getelementptr inbounds i8, i8* %1, i64 8
10 %2 = getelementptr inbounds i8, i8* %1, i64 16
11 %3 = zext i32 3 to i64
12 %b = getelementptr inbounds i8, i8* %2, i64 %3
13 ret void
14 }
15
16 ; CHECK-LABEL: test_with_lshr
17 ; CHECK: NoAlias: i8* %a, i8* %b
18
19 define void @test_with_lshr(i64 %i) {
20 %1 = tail call i8* @malloc(i64 120)
21 %a = getelementptr inbounds i8, i8* %1, i64 8
22 %2 = getelementptr inbounds i8, i8* %1, i64 16
23 %3 = lshr i64 %i, 2
24 %b = getelementptr inbounds i8, i8* %2, i64 %3
25 ret void
26 }
27
28 ; CHECK-LABEL: test_with_a_loop
29 ; CHECK: NoAlias: i8* %a, i8* %b
30
31 define void @test_with_a_loop(i8* %mem) {
32 br label %for.loop
33
34 for.loop:
35 %i = phi i32 [ 0, %0 ], [ %i.plus1, %for.loop ]
36 %a = getelementptr inbounds i8, i8* %mem, i64 8
37 %a.plus1 = getelementptr inbounds i8, i8* %mem, i64 16
38 %i.64 = zext i32 %i to i64
39 %b = getelementptr inbounds i8, i8* %a.plus1, i64 %i.64
40 %i.plus1 = add nuw nsw i32 %i, 1
41 %cmp = icmp eq i32 %i.plus1, 10
42 br i1 %cmp, label %for.loop.exit, label %for.loop
43
44 for.loop.exit:
45 ret void
46 }
47
48 ; CHECK-LABEL: test_with_varying_base_pointer_in_loop
49 ; CHECK: NoAlias: i8* %a, i8* %b
50
51 define void @test_with_varying_base_pointer_in_loop(i8* %mem.orig) {
52 br label %for.loop
53
54 for.loop:
55 %mem = phi i8* [ %mem.orig, %0 ], [ %mem.plus1, %for.loop ]
56 %i = phi i32 [ 0, %0 ], [ %i.plus1, %for.loop ]
57 %a = getelementptr inbounds i8, i8* %mem, i64 8
58 %a.plus1 = getelementptr inbounds i8, i8* %mem, i64 16
59 %i.64 = zext i32 %i to i64
60 %b = getelementptr inbounds i8, i8* %a.plus1, i64 %i.64
61 %i.plus1 = add nuw nsw i32 %i, 1
62 %mem.plus1 = getelementptr inbounds i8, i8* %mem, i64 8
63 %cmp = icmp eq i32 %i.plus1, 10
64 br i1 %cmp, label %for.loop.exit, label %for.loop
65
66 for.loop.exit:
67 ret void
68 }
69
70 ; CHECK-LABEL: test_sign_extension
71 ; CHECK: PartialAlias: i64* %b.i64, i8* %a
72
73 define void @test_sign_extension(i32 %p) {
74 %1 = tail call i8* @malloc(i64 120)
75 %p.64 = zext i32 %p to i64
76 %a = getelementptr inbounds i8, i8* %1, i64 %p.64
77 %p.minus1 = add i32 %p, -1
78 %p.minus1.64 = zext i32 %p.minus1 to i64
79 %b.i8 = getelementptr inbounds i8, i8* %1, i64 %p.minus1.64
80 %b.i64 = bitcast i8* %b.i8 to i64*
81 ret void
82 }
83
84 ; CHECK-LABEL: test_fe_tools
85 ; CHECK: PartialAlias: i32* %a, i32* %b
86
87 define void @test_fe_tools([8 x i32]* %values) {
88 br label %reorder
89
90 for.loop:
91 %i = phi i32 [ 0, %reorder ], [ %i.next, %for.loop ]
92 %idxprom = zext i32 %i to i64
93 %b = getelementptr inbounds [8 x i32], [8 x i32]* %values, i64 0, i64 %idxprom
94 %i.next = add nuw nsw i32 %i, 1
95 %1 = icmp eq i32 %i.next, 10
96 br i1 %1, label %for.loop.exit, label %for.loop
97
98 reorder:
99 %a = getelementptr inbounds [8 x i32], [8 x i32]* %values, i64 0, i64 1
100 br label %for.loop
101
102 for.loop.exit:
103 ret void
104 }
105
106 @b = global i32 0, align 4
107 @d = global i32 0, align 4
108
109 ; CHECK-LABEL: test_spec2006
110 ; CHECK: PartialAlias: i32** %x, i32** %y
111
112 define void @test_spec2006() {
113 %h = alloca [1 x [2 x i32*]], align 16
114 %d.val = load i32, i32* @d, align 4
115 %d.promoted = sext i32 %d.val to i64
116 %1 = icmp slt i32 %d.val, 2
117 br i1 %1, label %.lr.ph, label %3
118
119 .lr.ph: ; preds = %0
120 br label %2
121
122 ;
123 %i = phi i32 [ %d.val, %.lr.ph ], [ %i.plus1, %2 ]
124 %i.promoted = sext i32 %i to i64
125 %x = getelementptr inbounds [1 x [2 x i32*]], [1 x [2 x i32*]]* %h, i64 0, i64 %d.promoted, i64 %i.promoted
126 %i.plus1 = add nsw i32 %i, 1
127 %cmp = icmp slt i32 %i.plus1, 2
128 br i1 %cmp, label %2, label %3
129
130 ;
131 %y = getelementptr inbounds [1 x [2 x i32*]], [1 x [2 x i32*]]* %h, i64 0, i64 0, i64 1
132 ret void
133 }
134
135 ; CHECK-LABEL: test_modulo_analysis_easy_case
136 ; CHECK: NoAlias: i32** %x, i32** %y
137
138 define void @test_modulo_analysis_easy_case(i64 %i) {
139 %h = alloca [1 x [2 x i32*]], align 16
140 %x = getelementptr inbounds [1 x [2 x i32*]], [1 x [2 x i32*]]* %h, i64 0, i64 %i, i64 0
141 %y = getelementptr inbounds [1 x [2 x i32*]], [1 x [2 x i32*]]* %h, i64 0, i64 0, i64 1
142 ret void
143 }
144
145 ; CHECK-LABEL: test_modulo_analysis_in_loop
146 ; CHECK: NoAlias: i32** %x, i32** %y
147
148 define void @test_modulo_analysis_in_loop() {
149 %h = alloca [1 x [2 x i32*]], align 16
150 br label %for.loop
151
152 for.loop:
153 %i = phi i32 [ 0, %0 ], [ %i.plus1, %for.loop ]
154 %i.promoted = sext i32 %i to i64
155 %x = getelementptr inbounds [1 x [2 x i32*]], [1 x [2 x i32*]]* %h, i64 0, i64 %i.promoted, i64 0
156 %y = getelementptr inbounds [1 x [2 x i32*]], [1 x [2 x i32*]]* %h, i64 0, i64 0, i64 1
157 %i.plus1 = add nsw i32 %i, 1
158 %cmp = icmp slt i32 %i.plus1, 2
159 br i1 %cmp, label %for.loop, label %for.loop.exit
160
161 for.loop.exit:
162 ret void
163 }
164
165 ; CHECK-LABEL: test_modulo_analysis_with_global
166 ; CHECK: PartialAlias: i32** %x, i32** %y
167
168 define void @test_modulo_analysis_with_global() {
169 %h = alloca [1 x [2 x i32*]], align 16
170 %b = load i32, i32* @b, align 4
171 %b.promoted = sext i32 %b to i64
172 br label %for.loop
173
174 for.loop:
175 %i = phi i32 [ 0, %0 ], [ %i.plus1, %for.loop ]
176 %i.promoted = sext i32 %i to i64
177 %x = getelementptr inbounds [1 x [2 x i32*]], [1 x [2 x i32*]]* %h, i64 0, i64 %i.promoted, i64 %b.promoted
178 %y = getelementptr inbounds [1 x [2 x i32*]], [1 x [2 x i32*]]* %h, i64 0, i64 0, i64 1
179 %i.plus1 = add nsw i32 %i, 1
180 %cmp = icmp slt i32 %i.plus1, 2
181 br i1 %cmp, label %for.loop, label %for.loop.exit
182
183 for.loop.exit:
184 ret void
185 }
186
187 ; CHECK-LABEL: test_const_eval
188 ; CHECK: NoAlias: i8* %a, i8* %b
189 define void @test_const_eval(i8* %ptr, i64 %offset) {
190 %a = getelementptr inbounds i8, i8* %ptr, i64 %offset
191 %a.dup = getelementptr inbounds i8, i8* %ptr, i64 %offset
192 %three = zext i32 3 to i64
193 %b = getelementptr inbounds i8, i8* %a.dup, i64 %three
194 ret void
195 }
196
197 ; CHECK-LABEL: test_const_eval_scaled
198 ; CHECK: MustAlias: i8* %a, i8* %b
199 define void @test_const_eval_scaled(i8* %ptr) {
200 %three = zext i32 3 to i64
201 %six = mul i64 %three, 2
202 %a = getelementptr inbounds i8, i8* %ptr, i64 %six
203 %b = getelementptr inbounds i8, i8* %ptr, i64 6
204 ret void
205 }
206
207 ; CHECK-LABEL: Function: foo
208 ; CHECK: MustAlias: float* %arrayidx, float* %arrayidx4.84
209 define float @foo(i32 *%A, float %rend, float** %wayar) {
210 entry:
211 %x0 = load i32, i32* %A, align 4
212 %conv = sext i32 %x0 to i64
213 %mul = shl nsw i64 %conv, 3
214 %call = tail call i8* @malloc(i64 %mul)
215 %x1 = bitcast i8* %call to float*
216
217 %sub = add nsw i32 %x0, -1
218 %idxprom = sext i32 %sub to i64
219 %arrayidx = getelementptr inbounds float, float* %x1, i64 %idxprom
220 store float %rend, float* %arrayidx, align 8
221
222 %indvars.iv76.83 = add nsw i64 %conv, -1
223 %arrayidx4.84 = getelementptr inbounds float, float* %x1, i64 %indvars.iv76.83
224 %x4 = load float, float* %arrayidx4.84, align 8
225
226 ret float %x4
227 }
228
229 ; Function Attrs: nounwind
230 declare noalias i8* @malloc(i64)