mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2026-04-25 21:18:19 +00:00
implement the first part of PR8882: when lowering an inbounds
gep to explicit addressing, we know that none of the intermediate
computation overflows.
This could use review: it seems that the shifts certainly wouldn't
overflow, but could the intermediate adds overflow if there is a
negative index?
Previously the testcase would instcombine to:
define i1 @test(i64 %i) {
%p1.idx.mask = and i64 %i, 4611686018427387903
%cmp = icmp eq i64 %p1.idx.mask, 1000
ret i1 %cmp
}
now we get:
define i1 @test(i64 %i) {
%cmp = icmp eq i64 %i, 1000
ret i1 %cmp
}
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@125271 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -399,6 +399,10 @@ Value *InstCombiner::EmitGEPOffset(User *GEP) {
|
||||
const Type *IntPtrTy = TD.getIntPtrType(GEP->getContext());
|
||||
Value *Result = Constant::getNullValue(IntPtrTy);
|
||||
|
||||
// If the GEP is inbounds, we know that none of the addressing operations will
|
||||
// overflow in an unsigned sense.
|
||||
bool isInBounds = cast<GEPOperator>(GEP)->isInBounds();
|
||||
|
||||
// Build a mask for high order bits.
|
||||
unsigned IntPtrWidth = TD.getPointerSizeInBits();
|
||||
uint64_t PtrSizeMask = ~0ULL >> (64-IntPtrWidth);
|
||||
@@ -414,31 +418,34 @@ Value *InstCombiner::EmitGEPOffset(User *GEP) {
|
||||
if (const StructType *STy = dyn_cast<StructType>(*GTI)) {
|
||||
Size = TD.getStructLayout(STy)->getElementOffset(OpC->getZExtValue());
|
||||
|
||||
Result = Builder->CreateAdd(Result,
|
||||
ConstantInt::get(IntPtrTy, Size),
|
||||
GEP->getName()+".offs");
|
||||
if (Size)
|
||||
Result = Builder->CreateAdd(Result, ConstantInt::get(IntPtrTy, Size),
|
||||
GEP->getName()+".offs",
|
||||
isInBounds /*NUW*/);
|
||||
continue;
|
||||
}
|
||||
|
||||
Constant *Scale = ConstantInt::get(IntPtrTy, Size);
|
||||
Constant *OC =
|
||||
ConstantExpr::getIntegerCast(OpC, IntPtrTy, true /*SExt*/);
|
||||
Scale = ConstantExpr::getMul(OC, Scale);
|
||||
Scale = ConstantExpr::getMul(OC, Scale, isInBounds/*NUW*/);
|
||||
// Emit an add instruction.
|
||||
Result = Builder->CreateAdd(Result, Scale, GEP->getName()+".offs");
|
||||
Result = Builder->CreateAdd(Result, Scale, GEP->getName()+".offs",
|
||||
isInBounds /*NUW*/);
|
||||
continue;
|
||||
}
|
||||
// Convert to correct type.
|
||||
if (Op->getType() != IntPtrTy)
|
||||
Op = Builder->CreateIntCast(Op, IntPtrTy, true, Op->getName()+".c");
|
||||
if (Size != 1) {
|
||||
Constant *Scale = ConstantInt::get(IntPtrTy, Size);
|
||||
// We'll let instcombine(mul) convert this to a shl if possible.
|
||||
Op = Builder->CreateMul(Op, Scale, GEP->getName()+".idx");
|
||||
Op = Builder->CreateMul(Op, ConstantInt::get(IntPtrTy, Size),
|
||||
GEP->getName()+".idx", isInBounds /*NUW*/);
|
||||
}
|
||||
|
||||
// Emit an add instruction.
|
||||
Result = Builder->CreateAdd(Op, Result, GEP->getName()+".offs");
|
||||
Result = Builder->CreateAdd(Op, Result, GEP->getName()+".offs",
|
||||
isInBounds /*NUW*/);
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user