mirror of
https://github.com/RPCS3/llvm.git
synced 2025-01-31 07:43:37 +00:00
[GVN] Split AvailableValueInBlock into two parts [NFC]
AvailableValue is the part that represents the potential rematerialization. AvailableValueInBlock is simply a pair of an AvailableValue and a BB which we might materialize it in. This is motivated by http://reviews.llvm.org/D16608. The intent is that we'll have a single function which handles the local case which both local and non-local will use to identify available values. Once that's done, the local case can rematerialize at the use site and the non-local case can do the SSA construction as it does currently. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@258882 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
a3f542f695
commit
0de25e87a7
@ -512,9 +512,11 @@ void ValueTable::verifyRemoved(const Value *V) const {
|
||||
|
||||
namespace {
|
||||
class GVN;
|
||||
struct AvailableValueInBlock {
|
||||
/// BB - The basic block in question.
|
||||
BasicBlock *BB;
|
||||
/// Represents a particular available value that we know how to materialize.
|
||||
/// Materialization of an AvailableValue never fails. An AvailableValue is
|
||||
/// implicitly associated with a rematerialization point which is the
|
||||
/// location of the instruction from which it was formed.
|
||||
struct AvailableValue {
|
||||
enum ValType {
|
||||
SimpleVal, // A simple offsetted value that is accessed.
|
||||
LoadVal, // A value produced by a load.
|
||||
@ -529,39 +531,35 @@ namespace {
|
||||
/// Offset - The byte offset in Val that is interesting for the load query.
|
||||
unsigned Offset;
|
||||
|
||||
static AvailableValueInBlock get(BasicBlock *BB, Value *V,
|
||||
unsigned Offset = 0) {
|
||||
AvailableValueInBlock Res;
|
||||
Res.BB = BB;
|
||||
static AvailableValue get(Value *V,
|
||||
unsigned Offset = 0) {
|
||||
AvailableValue Res;
|
||||
Res.Val.setPointer(V);
|
||||
Res.Val.setInt(SimpleVal);
|
||||
Res.Offset = Offset;
|
||||
return Res;
|
||||
}
|
||||
|
||||
static AvailableValueInBlock getMI(BasicBlock *BB, MemIntrinsic *MI,
|
||||
unsigned Offset = 0) {
|
||||
AvailableValueInBlock Res;
|
||||
Res.BB = BB;
|
||||
static AvailableValue getMI(MemIntrinsic *MI,
|
||||
unsigned Offset = 0) {
|
||||
AvailableValue Res;
|
||||
Res.Val.setPointer(MI);
|
||||
Res.Val.setInt(MemIntrin);
|
||||
Res.Offset = Offset;
|
||||
return Res;
|
||||
}
|
||||
|
||||
static AvailableValueInBlock getLoad(BasicBlock *BB, LoadInst *LI,
|
||||
unsigned Offset = 0) {
|
||||
AvailableValueInBlock Res;
|
||||
Res.BB = BB;
|
||||
static AvailableValue getLoad(LoadInst *LI,
|
||||
unsigned Offset = 0) {
|
||||
AvailableValue Res;
|
||||
Res.Val.setPointer(LI);
|
||||
Res.Val.setInt(LoadVal);
|
||||
Res.Offset = Offset;
|
||||
return Res;
|
||||
}
|
||||
|
||||
static AvailableValueInBlock getUndef(BasicBlock *BB) {
|
||||
AvailableValueInBlock Res;
|
||||
Res.BB = BB;
|
||||
static AvailableValue getUndef() {
|
||||
AvailableValue Res;
|
||||
Res.Val.setPointer(nullptr);
|
||||
Res.Val.setInt(UndefVal);
|
||||
Res.Offset = 0;
|
||||
@ -587,10 +585,50 @@ namespace {
|
||||
assert(isMemIntrinValue() && "Wrong accessor");
|
||||
return cast<MemIntrinsic>(Val.getPointer());
|
||||
}
|
||||
|
||||
/// Emit code at the specified insertion point to adjust the value defined
|
||||
/// here to the specified type. This handles various coercion cases.
|
||||
Value *MaterializeAdjustedValue(LoadInst *LI, Instruction *InsertPt,
|
||||
GVN &gvn) const;
|
||||
};
|
||||
|
||||
/// Represents an AvailableValue which can be rematerialized at the end of
|
||||
/// the associated BasicBlock.
|
||||
struct AvailableValueInBlock {
|
||||
/// BB - The basic block in question.
|
||||
BasicBlock *BB;
|
||||
|
||||
/// AV - The actual available value
|
||||
AvailableValue AV;
|
||||
|
||||
static AvailableValueInBlock get(BasicBlock *BB, AvailableValue &&AV) {
|
||||
AvailableValueInBlock Res;
|
||||
Res.BB = BB;
|
||||
Res.AV = std::move(AV);
|
||||
return Res;
|
||||
}
|
||||
|
||||
static AvailableValueInBlock get(BasicBlock *BB, Value *V,
|
||||
unsigned Offset = 0) {
|
||||
return get(BB, AvailableValue::get(V, Offset));
|
||||
}
|
||||
static AvailableValueInBlock getMI(BasicBlock *BB, MemIntrinsic *MI,
|
||||
unsigned Offset = 0) {
|
||||
return get(BB, AvailableValue::getMI(MI, Offset));
|
||||
}
|
||||
static AvailableValueInBlock getLoad(BasicBlock *BB, LoadInst *LI,
|
||||
unsigned Offset = 0) {
|
||||
return get(BB, AvailableValue::getLoad(LI, Offset));
|
||||
}
|
||||
static AvailableValueInBlock getUndef(BasicBlock *BB) {
|
||||
return get(BB, AvailableValue::getUndef());
|
||||
}
|
||||
|
||||
/// Emit code into this block to adjust the value defined here to the
|
||||
/// specified type. This handles various coercion cases.
|
||||
Value *MaterializeAdjustedValue(LoadInst *LI, GVN &gvn) const;
|
||||
/// Emit code at the end of this block to adjust the value defined here to
|
||||
/// the specified type. This handles various coercion cases.
|
||||
Value *MaterializeAdjustedValue(LoadInst *LI, GVN &gvn) const {
|
||||
return AV.MaterializeAdjustedValue(LI, BB->getTerminator(), gvn);
|
||||
}
|
||||
};
|
||||
|
||||
class GVN : public FunctionPass {
|
||||
@ -1294,7 +1332,8 @@ static Value *ConstructSSAForLoadSet(LoadInst *LI,
|
||||
if (ValuesPerBlock.size() == 1 &&
|
||||
gvn.getDominatorTree().properlyDominates(ValuesPerBlock[0].BB,
|
||||
LI->getParent())) {
|
||||
assert(!ValuesPerBlock[0].isUndefValue() && "Dead BB dominate this block");
|
||||
assert(!ValuesPerBlock[0].AV.isUndefValue() &&
|
||||
"Dead BB dominate this block");
|
||||
return ValuesPerBlock[0].MaterializeAdjustedValue(LI, gvn);
|
||||
}
|
||||
|
||||
@ -1316,15 +1355,16 @@ static Value *ConstructSSAForLoadSet(LoadInst *LI,
|
||||
return SSAUpdate.GetValueInMiddleOfBlock(LI->getParent());
|
||||
}
|
||||
|
||||
Value *AvailableValueInBlock::MaterializeAdjustedValue(LoadInst *LI,
|
||||
GVN &gvn) const {
|
||||
Value *AvailableValue::MaterializeAdjustedValue(LoadInst *LI,
|
||||
Instruction *InsertPt,
|
||||
GVN &gvn) const {
|
||||
Value *Res;
|
||||
Type *LoadTy = LI->getType();
|
||||
const DataLayout &DL = LI->getModule()->getDataLayout();
|
||||
if (isSimpleValue()) {
|
||||
Res = getSimpleValue();
|
||||
if (Res->getType() != LoadTy) {
|
||||
Res = GetStoreValueForLoad(Res, Offset, LoadTy, BB->getTerminator(), DL);
|
||||
Res = GetStoreValueForLoad(Res, Offset, LoadTy, InsertPt, DL);
|
||||
|
||||
DEBUG(dbgs() << "GVN COERCED NONLOCAL VAL:\nOffset: " << Offset << " "
|
||||
<< *getSimpleValue() << '\n'
|
||||
@ -1335,16 +1375,15 @@ Value *AvailableValueInBlock::MaterializeAdjustedValue(LoadInst *LI,
|
||||
if (Load->getType() == LoadTy && Offset == 0) {
|
||||
Res = Load;
|
||||
} else {
|
||||
Res = GetLoadValueForLoad(Load, Offset, LoadTy, BB->getTerminator(),
|
||||
gvn);
|
||||
|
||||
Res = GetLoadValueForLoad(Load, Offset, LoadTy, InsertPt, gvn);
|
||||
|
||||
DEBUG(dbgs() << "GVN COERCED NONLOCAL LOAD:\nOffset: " << Offset << " "
|
||||
<< *getCoercedLoadValue() << '\n'
|
||||
<< *Res << '\n' << "\n\n\n");
|
||||
}
|
||||
} else if (isMemIntrinValue()) {
|
||||
Res = GetMemInstValueForLoad(getMemIntrinValue(), Offset, LoadTy,
|
||||
BB->getTerminator(), DL);
|
||||
InsertPt, DL);
|
||||
DEBUG(dbgs() << "GVN COERCED NONLOCAL MEM INTRIN:\nOffset: " << Offset
|
||||
<< " " << *getMemIntrinValue() << '\n'
|
||||
<< *Res << '\n' << "\n\n\n");
|
||||
@ -1353,6 +1392,7 @@ Value *AvailableValueInBlock::MaterializeAdjustedValue(LoadInst *LI,
|
||||
DEBUG(dbgs() << "GVN COERCED NONLOCAL Undef:\n";);
|
||||
return UndefValue::get(LoadTy);
|
||||
}
|
||||
assert(Res && "failed to materialize?");
|
||||
return Res;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user