diff options
author | Chris Lattner <sabre@nondot.org> | 2005-09-26 05:27:10 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2005-09-26 05:27:10 +0000 |
commit | c5f52e6da18e6e8ccb62aac2a4cb431df98e7d6d (patch) | |
tree | 874adfcadfa1d13ea16c66dd5a6aa3e59ffd45d3 /lib/Transforms/Utils/Local.cpp | |
parent | c5406b55d58b7378822d5f6316bf253ad0eaa82d (diff) |
Move the ConstantFoldLoadThroughGEPConstantExpr function out of the InstCombine
pass.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23444 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms/Utils/Local.cpp')
-rw-r--r-- | lib/Transforms/Utils/Local.cpp | 46 |
1 files changed, 45 insertions, 1 deletions
diff --git a/lib/Transforms/Utils/Local.cpp b/lib/Transforms/Utils/Local.cpp index 9744af3c60..b1dd58331b 100644 --- a/lib/Transforms/Utils/Local.cpp +++ b/lib/Transforms/Utils/Local.cpp @@ -12,11 +12,13 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Support/MathExtras.h" #include "llvm/Transforms/Utils/Local.h" #include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" #include "llvm/Instructions.h" #include "llvm/Intrinsics.h" +#include "llvm/Support/GetElementPtrTypeIterator.h" +#include "llvm/Support/MathExtras.h" #include <cerrno> #include <cmath> using namespace llvm; @@ -366,6 +368,48 @@ Constant *llvm::ConstantFoldCall(Function *F, } +/// ConstantFoldLoadThroughGEPConstantExpr - Given a constant and a +/// getelementptr constantexpr, return the constant value being addressed by the +/// constant expression, or null if something is funny and we can't decide. +Constant *llvm::ConstantFoldLoadThroughGEPConstantExpr(Constant *C, + ConstantExpr *CE) { + if (CE->getOperand(1) != Constant::getNullValue(CE->getOperand(1)->getType())) + return 0; // Do not allow stepping over the value! + + // Loop over all of the operands, tracking down which value we are + // addressing... + gep_type_iterator I = gep_type_begin(CE), E = gep_type_end(CE); + for (++I; I != E; ++I) + if (const StructType *STy = dyn_cast<StructType>(*I)) { + ConstantUInt *CU = cast<ConstantUInt>(I.getOperand()); + assert(CU->getValue() < STy->getNumElements() && + "Struct index out of range!"); + unsigned El = (unsigned)CU->getValue(); + if (ConstantStruct *CS = dyn_cast<ConstantStruct>(C)) { + C = CS->getOperand(El); + } else if (isa<ConstantAggregateZero>(C)) { + C = Constant::getNullValue(STy->getElementType(El)); + } else if (isa<UndefValue>(C)) { + C = UndefValue::get(STy->getElementType(El)); + } else { + return 0; + } + } else if (ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand())) { + const ArrayType *ATy = cast<ArrayType>(*I); + if ((uint64_t)CI->getRawValue() >= ATy->getNumElements()) return 0; + if (ConstantArray *CA = dyn_cast<ConstantArray>(C)) + C = CA->getOperand((unsigned)CI->getRawValue()); + else if (isa<ConstantAggregateZero>(C)) + C = Constant::getNullValue(ATy->getElementType()); + else if (isa<UndefValue>(C)) + C = UndefValue::get(ATy->getElementType()); + else + return 0; + } else { + return 0; + } + return C; +} //===----------------------------------------------------------------------===// |