mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-26 21:32:10 +00:00
Holding my nose and moving the accumulation routine to GEPOperator
instead of the instruction. I've left a forwarding wrapper for the instruction so users with the instruction don't need to create a GEPOperator themselves. This lets us remove the copy of this code in instsimplify. I've looked at most of the other copies of similar code, and this is the only one I've found that is actually exactly the same. The one in InlineCost is very close, but it requires re-mapping non-constant indices through the cost analysis value simplification map. I could add direct support for this to the generic routine, but it seems overly specific. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@169853 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
4ced4ee94b
commit
7550f96b2f
@ -16,9 +16,11 @@
|
||||
#define LLVM_OPERATOR_H
|
||||
|
||||
#include "llvm/Constants.h"
|
||||
#include "llvm/DataLayout.h"
|
||||
#include "llvm/DerivedTypes.h"
|
||||
#include "llvm/Instruction.h"
|
||||
#include "llvm/Type.h"
|
||||
#include "llvm/Support/GetElementPtrTypeIterator.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
@ -430,6 +432,45 @@ public:
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// \brief Accumulate the constant address offset of this GEP if possible.
|
||||
///
|
||||
/// This routine accepts an APInt into which it will accumulate the constant
|
||||
/// offset of this GEP if the GEP is in fact constant. If the GEP is not
|
||||
/// all-constant, it returns false and the value of the offset APInt is
|
||||
/// undefined (it is *not* preserved!). The APInt passed into this routine
|
||||
/// must be at least as wide as the IntPtr type for the address space of
|
||||
/// the base GEP pointer.
|
||||
bool accumulateConstantOffset(const DataLayout &DL, APInt &Offset) const {
|
||||
assert(Offset.getBitWidth() ==
|
||||
DL.getPointerSizeInBits(getPointerAddressSpace()) &&
|
||||
"The offset must have exactly as many bits as our pointer.");
|
||||
|
||||
for (gep_type_iterator GTI = gep_type_begin(this), GTE = gep_type_end(this);
|
||||
GTI != GTE; ++GTI) {
|
||||
ConstantInt *OpC = dyn_cast<ConstantInt>(GTI.getOperand());
|
||||
if (!OpC)
|
||||
return false;
|
||||
if (OpC->isZero())
|
||||
continue;
|
||||
|
||||
// Handle a struct index, which adds its field offset to the pointer.
|
||||
if (StructType *STy = dyn_cast<StructType>(*GTI)) {
|
||||
unsigned ElementIdx = OpC->getZExtValue();
|
||||
const StructLayout *SL = DL.getStructLayout(STy);
|
||||
Offset += APInt(Offset.getBitWidth(),
|
||||
SL->getElementOffset(ElementIdx));
|
||||
continue;
|
||||
}
|
||||
|
||||
// For array or vector indices, scale the index by the size of the type.
|
||||
APInt Index = OpC->getValue().sextOrTrunc(Offset.getBitWidth());
|
||||
Offset += Index * APInt(Offset.getBitWidth(),
|
||||
DL.getTypeAllocSize(GTI.getIndexedType()));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
@ -657,39 +657,6 @@ Value *llvm::SimplifyAddInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,
|
||||
RecursionLimit);
|
||||
}
|
||||
|
||||
/// \brief Accumulate the constant integer offset a GEP represents.
|
||||
///
|
||||
/// Given a getelementptr instruction/constantexpr, accumulate the constant
|
||||
/// offset from the base pointer into the provided APInt 'Offset'. Returns true
|
||||
/// if the GEP has all-constant indices. Returns false if any non-constant
|
||||
/// index is encountered leaving the 'Offset' in an undefined state. The
|
||||
/// 'Offset' APInt must be the bitwidth of the target's pointer size.
|
||||
static bool accumulateGEPOffset(const DataLayout &TD, GEPOperator *GEP,
|
||||
APInt &Offset) {
|
||||
unsigned IntPtrWidth = TD.getPointerSizeInBits();
|
||||
assert(IntPtrWidth == Offset.getBitWidth());
|
||||
|
||||
gep_type_iterator GTI = gep_type_begin(GEP);
|
||||
for (User::op_iterator I = GEP->op_begin() + 1, E = GEP->op_end(); I != E;
|
||||
++I, ++GTI) {
|
||||
ConstantInt *OpC = dyn_cast<ConstantInt>(*I);
|
||||
if (!OpC) return false;
|
||||
if (OpC->isZero()) continue;
|
||||
|
||||
// Handle a struct index, which adds its field offset to the pointer.
|
||||
if (StructType *STy = dyn_cast<StructType>(*GTI)) {
|
||||
unsigned ElementIdx = OpC->getZExtValue();
|
||||
const StructLayout *SL = TD.getStructLayout(STy);
|
||||
Offset += APInt(IntPtrWidth, SL->getElementOffset(ElementIdx));
|
||||
continue;
|
||||
}
|
||||
|
||||
APInt TypeSize(IntPtrWidth, TD.getTypeAllocSize(GTI.getIndexedType()));
|
||||
Offset += OpC->getValue().sextOrTrunc(IntPtrWidth) * TypeSize;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// \brief Compute the base pointer and cumulative constant offsets for V.
|
||||
///
|
||||
/// This strips all constant offsets off of V, leaving it the base pointer, and
|
||||
@ -710,7 +677,7 @@ static Constant *stripAndComputeConstantOffsets(const DataLayout &TD,
|
||||
Visited.insert(V);
|
||||
do {
|
||||
if (GEPOperator *GEP = dyn_cast<GEPOperator>(V)) {
|
||||
if (!GEP->isInBounds() || !accumulateGEPOffset(TD, GEP, Offset))
|
||||
if (!GEP->isInBounds() || !GEP->accumulateConstantOffset(TD, Offset))
|
||||
break;
|
||||
V = GEP->getPointerOperand();
|
||||
} else if (Operator::getOpcode(V) == Instruction::BitCast) {
|
||||
|
@ -23,7 +23,6 @@
|
||||
#include "llvm/Support/CallSite.h"
|
||||
#include "llvm/Support/ConstantRange.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/GetElementPtrTypeIterator.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
using namespace llvm;
|
||||
|
||||
@ -1427,33 +1426,8 @@ bool GetElementPtrInst::isInBounds() const {
|
||||
|
||||
bool GetElementPtrInst::accumulateConstantOffset(const DataLayout &DL,
|
||||
APInt &Offset) const {
|
||||
assert(Offset.getBitWidth() ==
|
||||
DL.getPointerSizeInBits(getPointerAddressSpace()) &&
|
||||
"The offset must have exactly as many bits as our pointer.");
|
||||
|
||||
for (gep_type_iterator GTI = gep_type_begin(this), GTE = gep_type_end(this);
|
||||
GTI != GTE; ++GTI) {
|
||||
ConstantInt *OpC = dyn_cast<ConstantInt>(GTI.getOperand());
|
||||
if (!OpC)
|
||||
return false;
|
||||
if (OpC->isZero())
|
||||
continue;
|
||||
|
||||
// Handle a struct index, which adds its field offset to the pointer.
|
||||
if (StructType *STy = dyn_cast<StructType>(*GTI)) {
|
||||
unsigned ElementIdx = OpC->getZExtValue();
|
||||
const StructLayout *SL = DL.getStructLayout(STy);
|
||||
Offset += APInt(Offset.getBitWidth(),
|
||||
SL->getElementOffset(ElementIdx));
|
||||
continue;
|
||||
}
|
||||
|
||||
// For array or vector indices, scale the index by the size of the type.
|
||||
APInt Index = OpC->getValue().sextOrTrunc(Offset.getBitWidth());
|
||||
Offset += Index * APInt(Offset.getBitWidth(),
|
||||
DL.getTypeAllocSize(GTI.getIndexedType()));
|
||||
}
|
||||
return true;
|
||||
// Delegate to the generic GEPOperator implementation.
|
||||
return cast<GEPOperator>(this)->accumulateConstantOffset(DL, Offset);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
Loading…
Reference in New Issue
Block a user