implement constant folding support for an exotic constant expr:

ret i64 ptrtoint (i8* getelementptr ([1000 x i8]* @X, i64 1, i64 sub (i64 0, i64 ptrtoint ([1000 x i8]* @X to i64))) to i64)

to "ret i64 1000".  This allows us to correctly compute the trip count
on a loop in PR8883, which occurs with std::fill on a char array.  This
allows us to transform it into a memset with a constant size.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@122950 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2011-01-06 06:19:46 +00:00
parent 255874ff52
commit 8cd4efb6a5
2 changed files with 38 additions and 1 deletions

View File

@ -575,8 +575,26 @@ static Constant *SymbolicallyEvaluateGEP(Constant *const *Ops, unsigned NumOps,
// If this is a constant expr gep that is effectively computing an
// "offsetof", fold it into 'cast int Size to T*' instead of 'gep 0, 0, 12'
for (unsigned i = 1; i != NumOps; ++i)
if (!isa<ConstantInt>(Ops[i]))
if (!isa<ConstantInt>(Ops[i])) {
// If this is "gep i8* Ptr, (sub 0, V)", fold this as:
// "inttoptr (sub (ptrtoint Ptr), V)"
if (NumOps == 2 &&
cast<PointerType>(ResultTy)->getElementType()->isIntegerTy(8)) {
ConstantExpr *CE = dyn_cast<ConstantExpr>(Ops[1]);
if (CE && CE->getOpcode() == Instruction::Sub &&
isa<ConstantInt>(CE->getOperand(0)) &&
cast<ConstantInt>(CE->getOperand(0))->isZero()) {
Constant *Res = ConstantExpr::getPtrToInt(Ptr, CE->getType());
Res = ConstantExpr::getSub(Res, CE->getOperand(1));
Res = ConstantExpr::getIntToPtr(Res, ResultTy);
if (ConstantExpr *ResCE = dyn_cast<ConstantExpr>(Res))
Res = ConstantFoldConstantExpression(ResCE, TD);
return Res;
}
}
return 0;
}
APInt Offset = APInt(BitWidth,
TD->getIndexedOffset(Ptr->getType(),

View File

@ -53,3 +53,22 @@ define void @frob() {
store i32 1, i32* getelementptr ([3 x %struct.X]* @Y, i64 0, i64 0, i32 0, i64 19), align 8
ret void
}
; PR8883 - Constant fold exotic gep subtract
; CHECK: @test2
@X = global [1000 x i8] zeroinitializer, align 16
define i64 @test2() {
entry:
%A = bitcast i8* getelementptr inbounds ([1000 x i8]* @X, i64 1, i64 0) to i8*
%B = bitcast i8* getelementptr inbounds ([1000 x i8]* @X, i64 0, i64 0) to i8*
%B2 = ptrtoint i8* %B to i64
%C = sub i64 0, %B2
%D = getelementptr i8* %A, i64 %C
%E = ptrtoint i8* %D to i64
ret i64 %E
; CHECK: ret i64 1000
}