From a424b9fbd16bbca930b62110a1f52cc155d0a91b Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 28 Jan 2010 18:08:26 +0000 Subject: [PATCH] Remove the folding rule getelementptr (i8* inttoptr (i64 1 to i8*), i32 -1) to inttoptr (i64 0 to i8*) from the VMCore constant folder. It didn't handle sign-extension properly in the case where the source integer is smaller than a pointer size. And, it relied on an assumption about sizeof(i8). The Analysis constant folder still folds these kinds of things; it has access to TargetData, so it can do them right. Add a testcase which tests that the VMCore constant folder doesn't miscompile this, and that the Analysis folder does fold it. llvm-svn: 94750 --- llvm/lib/VMCore/ConstantFold.cpp | 22 -------- llvm/test/Other/constant-fold-gep.ll | 84 ++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 22 deletions(-) create mode 100644 llvm/test/Other/constant-fold-gep.ll diff --git a/llvm/lib/VMCore/ConstantFold.cpp b/llvm/lib/VMCore/ConstantFold.cpp index 24b78ae969af..40061ee3d7b1 100644 --- a/llvm/lib/VMCore/ConstantFold.cpp +++ b/llvm/lib/VMCore/ConstantFold.cpp @@ -2021,28 +2021,6 @@ Constant *llvm::ConstantFoldGetElementPtr(LLVMContext &Context, ConstantExpr::getGetElementPtr( (Constant*)CE->getOperand(0), Idxs, NumIdx); } - - // Fold: getelementptr (i8* inttoptr (i64 1 to i8*), i32 -1) - // Into: inttoptr (i64 0 to i8*) - // This happens with pointers to member functions in C++. - if (CE->getOpcode() == Instruction::IntToPtr && NumIdx == 1 && - isa(CE->getOperand(0)) && isa(Idxs[0]) && - cast(CE->getType())->getElementType() == - Type::getInt8Ty(Context)) { - Constant *Base = CE->getOperand(0); - Constant *Offset = Idxs[0]; - - // Convert the smaller integer to the larger type. - if (Offset->getType()->getPrimitiveSizeInBits() < - Base->getType()->getPrimitiveSizeInBits()) - Offset = ConstantExpr::getSExt(Offset, Base->getType()); - else if (Base->getType()->getPrimitiveSizeInBits() < - Offset->getType()->getPrimitiveSizeInBits()) - Base = ConstantExpr::getZExt(Base, Offset->getType()); - - Base = ConstantExpr::getAdd(Base, Offset); - return ConstantExpr::getIntToPtr(Base, CE->getType()); - } } // Check to see if any array indices are not within the corresponding diff --git a/llvm/test/Other/constant-fold-gep.ll b/llvm/test/Other/constant-fold-gep.ll new file mode 100644 index 000000000000..513918d58f6e --- /dev/null +++ b/llvm/test/Other/constant-fold-gep.ll @@ -0,0 +1,84 @@ +; RUN: opt -S -o - < %s | FileCheck --check-prefix=PLAIN %s +; RUN: opt -S -o - -instcombine -globalopt < %s | FileCheck --check-prefix=OPT %s + +; The automatic constant folder in opt does not have targetdata access, so +; it can't fold gep arithmetic, in general. However, the constant folder run +; from instcombine and global opt does, and can. + +; PLAIN: @G8 = global i8* getelementptr (i8* inttoptr (i32 1 to i8*), i32 -1) +; PLAIN: @G1 = global i1* getelementptr (i1* inttoptr (i32 1 to i1*), i32 -1) +; PLAIN: @F8 = global i8* getelementptr (i8* inttoptr (i32 1 to i8*), i32 -2) +; PLAIN: @F1 = global i1* getelementptr (i1* inttoptr (i32 1 to i1*), i32 -2) +; PLAIN: @H8 = global i8* getelementptr (i8* null, i32 -1) +; PLAIN: @H1 = global i1* getelementptr (i1* null, i32 -1) +; PLAIN: define i8* @goo8() nounwind { +; PLAIN: ret i8* getelementptr (i8* inttoptr (i32 1 to i8*), i32 -1) +; PLAIN: } +; PLAIN: define i1* @goo1() nounwind { +; PLAIN: ret i1* getelementptr (i1* inttoptr (i32 1 to i1*), i32 -1) +; PLAIN: } +; PLAIN: define i8* @foo8() nounwind { +; PLAIN: ret i8* getelementptr (i8* inttoptr (i32 1 to i8*), i32 -2) +; PLAIN: } +; PLAIN: define i1* @foo1() nounwind { +; PLAIN: ret i1* getelementptr (i1* inttoptr (i32 1 to i1*), i32 -2) +; PLAIN: } +; PLAIN: define i8* @hoo8() nounwind { +; PLAIN: ret i8* getelementptr (i8* null, i32 -1) +; PLAIN: } +; PLAIN: define i1* @hoo1() nounwind { +; PLAIN: ret i1* getelementptr (i1* null, i32 -1) +; PLAIN: } + +; OPT: @G8 = global i8* null +; OPT: @G1 = global i1* null +; OPT: @F8 = global i8* inttoptr (i64 -1 to i8*) +; OPT: @F1 = global i1* inttoptr (i64 -1 to i1*) +; OPT: @H8 = global i8* inttoptr (i64 -1 to i8*) +; OPT: @H1 = global i1* inttoptr (i64 -1 to i1*) +; OPT: define i8* @goo8() nounwind { +; OPT: ret i8* null +; OPT: } +; OPT: define i1* @goo1() nounwind { +; OPT: ret i1* null +; OPT: } +; OPT: define i8* @foo8() nounwind { +; OPT: ret i8* inttoptr (i64 -1 to i8*) +; OPT: } +; OPT: define i1* @foo1() nounwind { +; OPT: ret i1* inttoptr (i64 -1 to i1*) +; OPT: } +; OPT: define i8* @hoo8() nounwind { +; OPT: ret i8* inttoptr (i64 -1 to i8*) +; OPT: } +; OPT: define i1* @hoo1() nounwind { +; OPT: ret i1* inttoptr (i64 -1 to i1*) +; OPT: } + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" + +@G8 = global i8* getelementptr (i8* inttoptr (i32 1 to i8*), i32 -1) +@G1 = global i1* getelementptr (i1* inttoptr (i32 1 to i1*), i32 -1) +@F8 = global i8* getelementptr (i8* inttoptr (i32 1 to i8*), i32 -2) +@F1 = global i1* getelementptr (i1* inttoptr (i32 1 to i1*), i32 -2) +@H8 = global i8* getelementptr (i8* inttoptr (i32 0 to i8*), i32 -1) +@H1 = global i1* getelementptr (i1* inttoptr (i32 0 to i1*), i32 -1) + +define i8* @goo8() nounwind { + ret i8* getelementptr (i8* inttoptr (i32 1 to i8*), i32 -1) +} +define i1* @goo1() nounwind { + ret i1* getelementptr (i1* inttoptr (i32 1 to i1*), i32 -1) +} +define i8* @foo8() nounwind { + ret i8* getelementptr (i8* inttoptr (i32 1 to i8*), i32 -2) +} +define i1* @foo1() nounwind { + ret i1* getelementptr (i1* inttoptr (i32 1 to i1*), i32 -2) +} +define i8* @hoo8() nounwind { + ret i8* getelementptr (i8* inttoptr (i32 0 to i8*), i32 -1) +} +define i1* @hoo1() nounwind { + ret i1* getelementptr (i1* inttoptr (i32 0 to i1*), i32 -1) +}