mirror of
https://github.com/RPCSX/llvm.git
synced 2024-12-05 02:16:46 +00:00
move DecomposeGEPExpression out into ValueTracking.cpp
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@89956 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
fa3966881f
commit
e405c64f6b
@ -19,6 +19,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
template <typename T> class SmallVectorImpl;
|
||||||
class Value;
|
class Value;
|
||||||
class Instruction;
|
class Instruction;
|
||||||
class APInt;
|
class APInt;
|
||||||
@ -77,6 +78,20 @@ namespace llvm {
|
|||||||
///
|
///
|
||||||
bool CannotBeNegativeZero(const Value *V, unsigned Depth = 0);
|
bool CannotBeNegativeZero(const Value *V, unsigned Depth = 0);
|
||||||
|
|
||||||
|
/// DecomposeGEPExpression - If V is a symbolic pointer expression, decompose
|
||||||
|
/// it into a base pointer with a constant offset and a number of scaled
|
||||||
|
/// symbolic offsets.
|
||||||
|
///
|
||||||
|
/// When TargetData is around, this function is capable of analyzing
|
||||||
|
/// everything that Value::getUnderlyingObject() can look through. When not,
|
||||||
|
/// it just looks through pointer casts.
|
||||||
|
///
|
||||||
|
const Value *DecomposeGEPExpression(const Value *V, int64_t &BaseOffs,
|
||||||
|
SmallVectorImpl<std::pair<const Value*, int64_t> > &VarIndices,
|
||||||
|
const TargetData *TD);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// FindScalarValue - Given an aggregrate and an sequence of indices, see if
|
/// FindScalarValue - Given an aggregrate and an sequence of indices, see if
|
||||||
/// the scalar value indexed is already around as a register, for example if
|
/// the scalar value indexed is already around as a register, for example if
|
||||||
/// it were inserted directly into the aggregrate.
|
/// it were inserted directly into the aggregrate.
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
#include "llvm/Constants.h"
|
#include "llvm/Constants.h"
|
||||||
#include "llvm/DerivedTypes.h"
|
#include "llvm/DerivedTypes.h"
|
||||||
#include "llvm/Function.h"
|
#include "llvm/Function.h"
|
||||||
#include "llvm/GlobalAlias.h"
|
|
||||||
#include "llvm/GlobalVariable.h"
|
#include "llvm/GlobalVariable.h"
|
||||||
#include "llvm/Instructions.h"
|
#include "llvm/Instructions.h"
|
||||||
#include "llvm/IntrinsicInst.h"
|
#include "llvm/IntrinsicInst.h"
|
||||||
@ -28,11 +27,9 @@
|
|||||||
#include "llvm/Analysis/MemoryBuiltins.h"
|
#include "llvm/Analysis/MemoryBuiltins.h"
|
||||||
#include "llvm/Analysis/ValueTracking.h"
|
#include "llvm/Analysis/ValueTracking.h"
|
||||||
#include "llvm/Target/TargetData.h"
|
#include "llvm/Target/TargetData.h"
|
||||||
#include "llvm/ADT/SmallSet.h"
|
#include "llvm/ADT/SmallPtrSet.h"
|
||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
#include "llvm/ADT/STLExtras.h"
|
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
#include "llvm/Support/GetElementPtrTypeIterator.h"
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
@ -379,160 +376,6 @@ BasicAliasAnalysis::getModRefInfo(CallSite CS1, CallSite CS2) {
|
|||||||
return NoAA::getModRefInfo(CS1, CS2);
|
return NoAA::getModRefInfo(CS1, CS2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// GetLinearExpression - Analyze the specified value as a linear expression:
|
|
||||||
/// "A*V + B". Return the scale and offset values as APInts and return V as a
|
|
||||||
/// Value*. The incoming Value is known to be a scalar integer.
|
|
||||||
static Value *GetLinearExpression(Value *V, APInt &Scale, APInt &Offset,
|
|
||||||
const TargetData *TD) {
|
|
||||||
assert(isa<IntegerType>(V->getType()) && "Not an integer value");
|
|
||||||
|
|
||||||
if (BinaryOperator *BOp = dyn_cast<BinaryOperator>(V)) {
|
|
||||||
if (ConstantInt *RHSC = dyn_cast<ConstantInt>(BOp->getOperand(1))) {
|
|
||||||
switch (BOp->getOpcode()) {
|
|
||||||
default: break;
|
|
||||||
case Instruction::Or:
|
|
||||||
// X|C == X+C if all the bits in C are unset in X. Otherwise we can't
|
|
||||||
// analyze it.
|
|
||||||
if (!MaskedValueIsZero(BOp->getOperand(0), RHSC->getValue(), TD))
|
|
||||||
break;
|
|
||||||
// FALL THROUGH.
|
|
||||||
case Instruction::Add:
|
|
||||||
V = GetLinearExpression(BOp->getOperand(0), Scale, Offset, TD);
|
|
||||||
Offset += RHSC->getValue();
|
|
||||||
return V;
|
|
||||||
case Instruction::Mul:
|
|
||||||
V = GetLinearExpression(BOp->getOperand(0), Scale, Offset, TD);
|
|
||||||
Offset *= RHSC->getValue();
|
|
||||||
Scale *= RHSC->getValue();
|
|
||||||
return V;
|
|
||||||
case Instruction::Shl:
|
|
||||||
V = GetLinearExpression(BOp->getOperand(0), Scale, Offset, TD);
|
|
||||||
Offset <<= RHSC->getValue().getLimitedValue();
|
|
||||||
Scale <<= RHSC->getValue().getLimitedValue();
|
|
||||||
return V;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Scale = 1;
|
|
||||||
Offset = 0;
|
|
||||||
return V;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// DecomposeGEPExpression - If V is a symbolic pointer expression, decompose it
|
|
||||||
/// into a base pointer with a constant offset and a number of scaled symbolic
|
|
||||||
/// offsets.
|
|
||||||
///
|
|
||||||
/// When TargetData is around, this function is capable of analyzing everything
|
|
||||||
/// that Value::getUnderlyingObject() can look through. When not, it just looks
|
|
||||||
/// through pointer casts.
|
|
||||||
///
|
|
||||||
/// FIXME: Move this out to ValueTracking.cpp
|
|
||||||
///
|
|
||||||
static const Value *DecomposeGEPExpression(const Value *V, int64_t &BaseOffs,
|
|
||||||
SmallVectorImpl<std::pair<const Value*, int64_t> > &VarIndices,
|
|
||||||
const TargetData *TD) {
|
|
||||||
// FIXME: Should limit depth like getUnderlyingObject?
|
|
||||||
BaseOffs = 0;
|
|
||||||
while (1) {
|
|
||||||
// See if this is a bitcast or GEP.
|
|
||||||
const Operator *Op = dyn_cast<Operator>(V);
|
|
||||||
if (Op == 0) {
|
|
||||||
// The only non-operator case we can handle are GlobalAliases.
|
|
||||||
if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(V)) {
|
|
||||||
if (!GA->mayBeOverridden()) {
|
|
||||||
V = GA->getAliasee();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return V;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Op->getOpcode() == Instruction::BitCast) {
|
|
||||||
V = Op->getOperand(0);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const GEPOperator *GEPOp = dyn_cast<GEPOperator>(Op);
|
|
||||||
if (GEPOp == 0)
|
|
||||||
return V;
|
|
||||||
|
|
||||||
// Don't attempt to analyze GEPs over unsized objects.
|
|
||||||
if (!cast<PointerType>(GEPOp->getOperand(0)->getType())
|
|
||||||
->getElementType()->isSized())
|
|
||||||
return V;
|
|
||||||
|
|
||||||
// If we are lacking TargetData information, we can't compute the offets of
|
|
||||||
// elements computed by GEPs. However, we can handle bitcast equivalent
|
|
||||||
// GEPs.
|
|
||||||
if (!TD) {
|
|
||||||
if (!GEPOp->hasAllZeroIndices())
|
|
||||||
return V;
|
|
||||||
V = GEPOp->getOperand(0);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Walk the indices of the GEP, accumulating them into BaseOff/VarIndices.
|
|
||||||
gep_type_iterator GTI = gep_type_begin(GEPOp);
|
|
||||||
for (User::const_op_iterator I = next(GEPOp->op_begin()),
|
|
||||||
E = GEPOp->op_end(); I != E; ++I) {
|
|
||||||
Value *Index = *I;
|
|
||||||
// Compute the (potentially symbolic) offset in bytes for this index.
|
|
||||||
if (const StructType *STy = dyn_cast<StructType>(*GTI++)) {
|
|
||||||
// For a struct, add the member offset.
|
|
||||||
unsigned FieldNo = cast<ConstantInt>(Index)->getZExtValue();
|
|
||||||
if (FieldNo == 0) continue;
|
|
||||||
|
|
||||||
BaseOffs += TD->getStructLayout(STy)->getElementOffset(FieldNo);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// For an array/pointer, add the element offset, explicitly scaled.
|
|
||||||
if (ConstantInt *CIdx = dyn_cast<ConstantInt>(Index)) {
|
|
||||||
if (CIdx->isZero()) continue;
|
|
||||||
BaseOffs += TD->getTypeAllocSize(*GTI)*CIdx->getSExtValue();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Could handle linear expressions here like A[X+1], also A[X*4|1].
|
|
||||||
uint64_t Scale = TD->getTypeAllocSize(*GTI);
|
|
||||||
|
|
||||||
unsigned Width = cast<IntegerType>(Index->getType())->getBitWidth();
|
|
||||||
APInt IndexScale(Width, 0), IndexOffset(Width, 0);
|
|
||||||
Index = GetLinearExpression(Index, IndexScale, IndexOffset, TD);
|
|
||||||
|
|
||||||
Scale *= IndexScale.getZExtValue();
|
|
||||||
BaseOffs += IndexOffset.getZExtValue()*Scale;
|
|
||||||
|
|
||||||
|
|
||||||
// If we already had an occurrance of this index variable, merge this
|
|
||||||
// scale into it. For example, we want to handle:
|
|
||||||
// A[x][x] -> x*16 + x*4 -> x*20
|
|
||||||
// This also ensures that 'x' only appears in the index list once.
|
|
||||||
for (unsigned i = 0, e = VarIndices.size(); i != e; ++i) {
|
|
||||||
if (VarIndices[i].first == Index) {
|
|
||||||
Scale += VarIndices[i].second;
|
|
||||||
VarIndices.erase(VarIndices.begin()+i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure that we have a scale that makes sense for this target's
|
|
||||||
// pointer size.
|
|
||||||
if (unsigned ShiftBits = 64-TD->getPointerSizeInBits()) {
|
|
||||||
Scale <<= ShiftBits;
|
|
||||||
Scale >>= ShiftBits;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Scale)
|
|
||||||
VarIndices.push_back(std::make_pair(Index, Scale));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Analyze the base pointer next.
|
|
||||||
V = GEPOp->getOperand(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// GetIndiceDifference - Dest and Src are the variable indices from two
|
/// GetIndiceDifference - Dest and Src are the variable indices from two
|
||||||
/// decomposed GetElementPtr instructions GEP1 and GEP2 which have common base
|
/// decomposed GetElementPtr instructions GEP1 and GEP2 which have common base
|
||||||
/// pointers. Subtract the GEP2 indices from GEP1 to find the symbolic
|
/// pointers. Subtract the GEP2 indices from GEP1 to find the symbolic
|
||||||
|
@ -948,6 +948,160 @@ bool llvm::CannotBeNegativeZero(const Value *V, unsigned Depth) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// GetLinearExpression - Analyze the specified value as a linear expression:
|
||||||
|
/// "A*V + B". Return the scale and offset values as APInts and return V as a
|
||||||
|
/// Value*. The incoming Value is known to be a scalar integer.
|
||||||
|
static Value *GetLinearExpression(Value *V, APInt &Scale, APInt &Offset,
|
||||||
|
const TargetData *TD) {
|
||||||
|
assert(isa<IntegerType>(V->getType()) && "Not an integer value");
|
||||||
|
|
||||||
|
if (BinaryOperator *BOp = dyn_cast<BinaryOperator>(V)) {
|
||||||
|
if (ConstantInt *RHSC = dyn_cast<ConstantInt>(BOp->getOperand(1))) {
|
||||||
|
switch (BOp->getOpcode()) {
|
||||||
|
default: break;
|
||||||
|
case Instruction::Or:
|
||||||
|
// X|C == X+C if all the bits in C are unset in X. Otherwise we can't
|
||||||
|
// analyze it.
|
||||||
|
if (!MaskedValueIsZero(BOp->getOperand(0), RHSC->getValue(), TD))
|
||||||
|
break;
|
||||||
|
// FALL THROUGH.
|
||||||
|
case Instruction::Add:
|
||||||
|
V = GetLinearExpression(BOp->getOperand(0), Scale, Offset, TD);
|
||||||
|
Offset += RHSC->getValue();
|
||||||
|
return V;
|
||||||
|
case Instruction::Mul:
|
||||||
|
V = GetLinearExpression(BOp->getOperand(0), Scale, Offset, TD);
|
||||||
|
Offset *= RHSC->getValue();
|
||||||
|
Scale *= RHSC->getValue();
|
||||||
|
return V;
|
||||||
|
case Instruction::Shl:
|
||||||
|
V = GetLinearExpression(BOp->getOperand(0), Scale, Offset, TD);
|
||||||
|
Offset <<= RHSC->getValue().getLimitedValue();
|
||||||
|
Scale <<= RHSC->getValue().getLimitedValue();
|
||||||
|
return V;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Scale = 1;
|
||||||
|
Offset = 0;
|
||||||
|
return V;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// DecomposeGEPExpression - If V is a symbolic pointer expression, decompose it
|
||||||
|
/// into a base pointer with a constant offset and a number of scaled symbolic
|
||||||
|
/// offsets.
|
||||||
|
///
|
||||||
|
/// When TargetData is around, this function is capable of analyzing everything
|
||||||
|
/// that Value::getUnderlyingObject() can look through. When not, it just looks
|
||||||
|
/// through pointer casts.
|
||||||
|
///
|
||||||
|
const Value *llvm::DecomposeGEPExpression(const Value *V, int64_t &BaseOffs,
|
||||||
|
SmallVectorImpl<std::pair<const Value*, int64_t> > &VarIndices,
|
||||||
|
const TargetData *TD) {
|
||||||
|
// FIXME: Should limit depth like getUnderlyingObject?
|
||||||
|
BaseOffs = 0;
|
||||||
|
while (1) {
|
||||||
|
// See if this is a bitcast or GEP.
|
||||||
|
const Operator *Op = dyn_cast<Operator>(V);
|
||||||
|
if (Op == 0) {
|
||||||
|
// The only non-operator case we can handle are GlobalAliases.
|
||||||
|
if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(V)) {
|
||||||
|
if (!GA->mayBeOverridden()) {
|
||||||
|
V = GA->getAliasee();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return V;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Op->getOpcode() == Instruction::BitCast) {
|
||||||
|
V = Op->getOperand(0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const GEPOperator *GEPOp = dyn_cast<GEPOperator>(Op);
|
||||||
|
if (GEPOp == 0)
|
||||||
|
return V;
|
||||||
|
|
||||||
|
// Don't attempt to analyze GEPs over unsized objects.
|
||||||
|
if (!cast<PointerType>(GEPOp->getOperand(0)->getType())
|
||||||
|
->getElementType()->isSized())
|
||||||
|
return V;
|
||||||
|
|
||||||
|
// If we are lacking TargetData information, we can't compute the offets of
|
||||||
|
// elements computed by GEPs. However, we can handle bitcast equivalent
|
||||||
|
// GEPs.
|
||||||
|
if (!TD) {
|
||||||
|
if (!GEPOp->hasAllZeroIndices())
|
||||||
|
return V;
|
||||||
|
V = GEPOp->getOperand(0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Walk the indices of the GEP, accumulating them into BaseOff/VarIndices.
|
||||||
|
gep_type_iterator GTI = gep_type_begin(GEPOp);
|
||||||
|
for (User::const_op_iterator I = GEPOp->op_begin()+1,
|
||||||
|
E = GEPOp->op_end(); I != E; ++I) {
|
||||||
|
Value *Index = *I;
|
||||||
|
// Compute the (potentially symbolic) offset in bytes for this index.
|
||||||
|
if (const StructType *STy = dyn_cast<StructType>(*GTI++)) {
|
||||||
|
// For a struct, add the member offset.
|
||||||
|
unsigned FieldNo = cast<ConstantInt>(Index)->getZExtValue();
|
||||||
|
if (FieldNo == 0) continue;
|
||||||
|
|
||||||
|
BaseOffs += TD->getStructLayout(STy)->getElementOffset(FieldNo);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For an array/pointer, add the element offset, explicitly scaled.
|
||||||
|
if (ConstantInt *CIdx = dyn_cast<ConstantInt>(Index)) {
|
||||||
|
if (CIdx->isZero()) continue;
|
||||||
|
BaseOffs += TD->getTypeAllocSize(*GTI)*CIdx->getSExtValue();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Could handle linear expressions here like A[X+1], also A[X*4|1].
|
||||||
|
uint64_t Scale = TD->getTypeAllocSize(*GTI);
|
||||||
|
|
||||||
|
unsigned Width = cast<IntegerType>(Index->getType())->getBitWidth();
|
||||||
|
APInt IndexScale(Width, 0), IndexOffset(Width, 0);
|
||||||
|
Index = GetLinearExpression(Index, IndexScale, IndexOffset, TD);
|
||||||
|
|
||||||
|
Scale *= IndexScale.getZExtValue();
|
||||||
|
BaseOffs += IndexOffset.getZExtValue()*Scale;
|
||||||
|
|
||||||
|
|
||||||
|
// If we already had an occurrance of this index variable, merge this
|
||||||
|
// scale into it. For example, we want to handle:
|
||||||
|
// A[x][x] -> x*16 + x*4 -> x*20
|
||||||
|
// This also ensures that 'x' only appears in the index list once.
|
||||||
|
for (unsigned i = 0, e = VarIndices.size(); i != e; ++i) {
|
||||||
|
if (VarIndices[i].first == Index) {
|
||||||
|
Scale += VarIndices[i].second;
|
||||||
|
VarIndices.erase(VarIndices.begin()+i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure that we have a scale that makes sense for this target's
|
||||||
|
// pointer size.
|
||||||
|
if (unsigned ShiftBits = 64-TD->getPointerSizeInBits()) {
|
||||||
|
Scale <<= ShiftBits;
|
||||||
|
Scale >>= ShiftBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Scale)
|
||||||
|
VarIndices.push_back(std::make_pair(Index, Scale));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Analyze the base pointer next.
|
||||||
|
V = GEPOp->getOperand(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// This is the recursive version of BuildSubAggregate. It takes a few different
|
// This is the recursive version of BuildSubAggregate. It takes a few different
|
||||||
// arguments. Idxs is the index within the nested struct From that we are
|
// arguments. Idxs is the index within the nested struct From that we are
|
||||||
// looking at now (which is of type IndexedType). IdxSkip is the number of
|
// looking at now (which is of type IndexedType). IdxSkip is the number of
|
||||||
|
Loading…
Reference in New Issue
Block a user