mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-09 11:25:55 +00:00
Be more conservative with our symbolic alias analysis. In particular,
don't assume that A[1][0] and A[0][i] can't alias. "i" might be out of range, or even negative. This fixes a miscompilation of 188.ammp (which does bad pointer tricks) with the new CFE. Testcase here: Analysis/BasicAA/2006-03-03-BadArraySubscript.ll git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26515 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -527,6 +527,14 @@ CheckGEPInstructions(const Type* BasePtr1Ty, std::vector<Value*> &GEP1Ops,
|
|||||||
// chain. For example:
|
// chain. For example:
|
||||||
// A[i][0] != A[j][1] iff (&A[0][1]-&A[0][0] >= std::max(G1S, G2S))
|
// A[i][0] != A[j][1] iff (&A[0][1]-&A[0][0] >= std::max(G1S, G2S))
|
||||||
//
|
//
|
||||||
|
// We have to be careful here about array accesses. In particular, consider:
|
||||||
|
// A[1][0] vs A[0][i]
|
||||||
|
// In this case, we don't *know* that the array will be accessed in bounds:
|
||||||
|
// the index could even be negative. Because of this, we have to
|
||||||
|
// conservatively *give up* and return may alias. We disregard differing
|
||||||
|
// array subscripts that are followed by a variable index without going
|
||||||
|
// through a struct.
|
||||||
|
//
|
||||||
unsigned SizeMax = std::max(G1S, G2S);
|
unsigned SizeMax = std::max(G1S, G2S);
|
||||||
if (SizeMax == ~0U) return MayAlias; // Avoid frivolous work.
|
if (SizeMax == ~0U) return MayAlias; // Avoid frivolous work.
|
||||||
|
|
||||||
@@ -547,15 +555,36 @@ CheckGEPInstructions(const Type* BasePtr1Ty, std::vector<Value*> &GEP1Ops,
|
|||||||
GEP1Ops[FirstConstantOper] = G1OC;
|
GEP1Ops[FirstConstantOper] = G1OC;
|
||||||
GEP2Ops[FirstConstantOper] = G2OC;
|
GEP2Ops[FirstConstantOper] = G2OC;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (G1OC != G2OC) {
|
if (G1OC != G2OC) {
|
||||||
|
// Handle the "be careful" case above: if this is an array
|
||||||
|
// subscript, scan for a subsequent variable array index.
|
||||||
|
if (isa<ArrayType>(BasePtr1Ty)) {
|
||||||
|
const Type *NextTy =cast<ArrayType>(BasePtr1Ty)->getElementType();
|
||||||
|
bool isBadCase = false;
|
||||||
|
|
||||||
|
for (unsigned Idx = FirstConstantOper+1;
|
||||||
|
Idx != MinOperands && isa<ArrayType>(NextTy); ++Idx) {
|
||||||
|
const Value *V1 = GEP1Ops[Idx], *V2 = GEP2Ops[Idx];
|
||||||
|
if (!isa<Constant>(V1) || !isa<Constant>(V2)) {
|
||||||
|
isBadCase = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
NextTy = cast<ArrayType>(NextTy)->getElementType();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isBadCase) G1OC = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure they are comparable (ie, not constant expressions), and
|
// Make sure they are comparable (ie, not constant expressions), and
|
||||||
// make sure the GEP with the smaller leading constant is GEP1.
|
// make sure the GEP with the smaller leading constant is GEP1.
|
||||||
Constant *Compare = ConstantExpr::getSetGT(G1OC, G2OC);
|
if (G1OC) {
|
||||||
if (ConstantBool *CV = dyn_cast<ConstantBool>(Compare)) {
|
Constant *Compare = ConstantExpr::getSetGT(G1OC, G2OC);
|
||||||
if (CV->getValue()) // If they are comparable and G2 > G1
|
if (ConstantBool *CV = dyn_cast<ConstantBool>(Compare)) {
|
||||||
std::swap(GEP1Ops, GEP2Ops); // Make GEP1 < GEP2
|
if (CV->getValue()) // If they are comparable and G2 > G1
|
||||||
break;
|
std::swap(GEP1Ops, GEP2Ops); // Make GEP1 < GEP2
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user