-> b2
// Request is
// -> ?
// The function tries to find or build phi [b1, BB1], [b2, BB2] in BB3
Value *findCommon(FoldAddrToValueMapping &Map) {
// Tracks the simplification of newly created phi nodes. The reason we use
// this mapping is because we will add new created Phi nodes in AddrToBase.
// Simplification of Phi nodes is recursive, so some Phi node may
// be simplified after we added it to AddrToBase.
// Using this mapping we can find the current value in AddrToBase.
SimplificationTracker ST(SQ);
// First step, DFS to create PHI nodes for all intermediate blocks.
// Also fill traverse order for the second step.
SmallVector TraverseOrder;
InsertPlaceholders(Map, TraverseOrder, ST);
// Second Step, fill new nodes by merged values and simplify if possible.
FillPlaceholders(Map, TraverseOrder, ST);
if (!AddrSinkNewSelects && ST.countNewSelectNodes() > 0) {
ST.destroyNewNodes(CommonType);
return nullptr;
}
// Now we'd like to match New Phi nodes to existed ones.
unsigned PhiNotMatchedCount = 0;
if (!MatchPhiSet(ST, AddrSinkNewPhis, PhiNotMatchedCount)) {
ST.destroyNewNodes(CommonType);
return nullptr;
}
auto *Result = ST.Get(Map.find(Original)->second);
if (Result) {
NumMemoryInstsPhiCreated += ST.countNewPhiNodes() + PhiNotMatchedCount;
NumMemoryInstsSelectCreated += ST.countNewSelectNodes();
}
return Result;
}
/// Try to match PHI node to Candidate.
/// Matcher tracks the matched Phi nodes.
bool MatchPhiNode(PHINode *PHI, PHINode *Candidate,
SmallSetVector &Matcher,
SmallSetVector &PhiNodesToMatch) {
SmallVector WorkList;
Matcher.insert({ PHI, Candidate });
WorkList.push_back({ PHI, Candidate });
SmallSet Visited;
while (!WorkList.empty()) {
auto Item = WorkList.pop_back_val();
if (!Visited.insert(Item).second)
continue;
// We iterate over all incoming values to Phi to compare them.
// If values are different and both of them Phi and the first one is a
// Phi we added (subject to match) and both of them is in the same basic
// block then we can match our pair if values match. So we state that
// these values match and add it to work list to verify that.
for (auto B : Item.first->blocks()) {
Value *FirstValue = Item.first->getIncomingValueForBlock(B);
Value *SecondValue = Item.second->getIncomingValueForBlock(B);
if (FirstValue == SecondValue)
continue;
PHINode *FirstPhi = dyn_cast(FirstValue);
PHINode *SecondPhi = dyn_cast(SecondValue);
// One of them is not Phi or
// The first one is not Phi node from the set we'd like to match or
// Phi nodes from different basic blocks then
// we will not be able to match.
if (!FirstPhi || !SecondPhi || !PhiNodesToMatch.count(FirstPhi) ||
FirstPhi->getParent() != SecondPhi->getParent())
return false;
// If we already matched them then continue.
if (Matcher.count({ FirstPhi, SecondPhi }))
continue;
// So the values are different and does not match. So we need them to
// match.
Matcher.insert({ FirstPhi, SecondPhi });
// But me must check it.
WorkList.push_back({ FirstPhi, SecondPhi });
}
}
return true;
}
/// For the given set of PHI nodes (in the SimplificationTracker) try
/// to find their equivalents.
/// Returns false if this matching fails and creation of new Phi is disabled.
bool MatchPhiSet(SimplificationTracker &ST, bool AllowNewPhiNodes,
unsigned &PhiNotMatchedCount) {
// Use a SetVector for Matched to make sure we do replacements (ReplacePhi)
// in a deterministic order below.
SmallSetVector Matched;
SmallPtrSet WillNotMatch;
SmallSetVector &PhiNodesToMatch = ST.newPhiNodes();
while (PhiNodesToMatch.size()) {
PHINode *PHI = *PhiNodesToMatch.begin();
// Add us, if no Phi nodes in the basic block we do not match.
WillNotMatch.clear();
WillNotMatch.insert(PHI);
// Traverse all Phis until we found equivalent or fail to do that.
bool IsMatched = false;
for (auto &P : PHI->getParent()->phis()) {
if (&P == PHI)
continue;
if ((IsMatched = MatchPhiNode(PHI, &P, Matched, PhiNodesToMatch)))
break;
// If it does not match, collect all Phi nodes from matcher.
// if we end up with no match, them all these Phi nodes will not match
// later.
for (auto M : Matched)
WillNotMatch.insert(M.first);
Matched.clear();
}
if (IsMatched) {
// Replace all matched values and erase them.
for (auto MV : Matched)
ST.ReplacePhi(MV.first, MV.second);
Matched.clear();
continue;
}
// If we are not allowed to create new nodes then bail out.
if (!AllowNewPhiNodes)
return false;
// Just remove all seen values in matcher. They will not match anything.
PhiNotMatchedCount += WillNotMatch.size();
for (auto *P : WillNotMatch)
PhiNodesToMatch.remove(P);
}
return true;
}
/// Fill the placeholder with values from predecessors and simplify it.
void FillPlaceholders(FoldAddrToValueMapping &Map,
SmallVectorImpl &TraverseOrder,
SimplificationTracker &ST) {
while (!TraverseOrder.empty()) {
auto Current = TraverseOrder.pop_back_val();
assert(Map.find(Current) != Map.end() && "No node to fill!!!");
Value *CurrentValue = Current.first;
BasicBlock *CurrentBlock = Current.second;
Value *V = Map[Current];
if (SelectInst *Select = dyn_cast(V)) {
// CurrentValue also must be Select.
auto *CurrentSelect = cast(CurrentValue);
auto *TrueValue = CurrentSelect->getTrueValue();
ValueInBB TrueItem = { TrueValue, isa(TrueValue)
? CurrentBlock
: nullptr };
assert(Map.find(TrueItem) != Map.end() && "No True Value!");
Select->setTrueValue(ST.Get(Map[TrueItem]));
auto *FalseValue = CurrentSelect->getFalseValue();
ValueInBB FalseItem = { FalseValue, isa(FalseValue)
? CurrentBlock
: nullptr };
assert(Map.find(FalseItem) != Map.end() && "No False Value!");
Select->setFalseValue(ST.Get(Map[FalseItem]));
} else {
// Must be a Phi node then.
PHINode *PHI = cast(V);
// Fill the Phi node with values from predecessors.
bool IsDefinedInThisBB =
cast(CurrentValue)->getParent() == CurrentBlock;
auto *CurrentPhi = dyn_cast(CurrentValue);
for (auto B : predecessors(CurrentBlock)) {
Value *PV = IsDefinedInThisBB
? CurrentPhi->getIncomingValueForBlock(B)
: CurrentValue;
ValueInBB item = { PV, isa(PV) ? B : nullptr };
assert(Map.find(item) != Map.end() && "No predecessor Value!");
PHI->addIncoming(ST.Get(Map[item]), B);
}
}
// Simplify if possible.
Map[Current] = ST.Simplify(V);
}
}
/// Starting from value recursively iterates over predecessors up to known
/// ending values represented in a map. For each traversed block inserts
/// a placeholder Phi or Select.
/// Reports all new created Phi/Select nodes by adding them to set.
/// Also reports and order in what basic blocks have been traversed.
void InsertPlaceholders(FoldAddrToValueMapping &Map,
SmallVectorImpl &TraverseOrder,
SimplificationTracker &ST) {
SmallVector Worklist;
assert((isa(Original.first) || isa(Original.first)) &&
"Address must be a Phi or Select node");
auto *Dummy = UndefValue::get(CommonType);
Worklist.push_back(Original);
while (!Worklist.empty()) {
auto Current = Worklist.pop_back_val();
// If value is not an instruction it is something global, constant,
// parameter and we can say that this value is observable in any block.
// Set block to null to denote it.
// Also please take into account that it is how we build anchors.
if (!isa(Current.first))
Current.second = nullptr;
// if it is already visited or it is an ending value then skip it.
if (Map.find(Current) != Map.end())
continue;
TraverseOrder.push_back(Current);
Value *CurrentValue = Current.first;
BasicBlock *CurrentBlock = Current.second;
// CurrentValue must be a Phi node or select. All others must be covered
// by anchors.
Instruction *CurrentI = cast(CurrentValue);
bool IsDefinedInThisBB = CurrentI->getParent() == CurrentBlock;
unsigned PredCount = pred_size(CurrentBlock);
// if Current Value is not defined in this basic block we are interested
// in values in predecessors.
if (!IsDefinedInThisBB) {
assert(PredCount && "Unreachable block?!");
PHINode *PHI = PHINode::Create(CommonType, PredCount, "sunk_phi",
&CurrentBlock->front());
Map[Current] = PHI;
ST.insertNewPhi(PHI);
// Add all predecessors in work list.
for (auto B : predecessors(CurrentBlock))
Worklist.push_back({ CurrentValue, B });
continue;
}
// Value is defined in this basic block.
if (SelectInst *OrigSelect = dyn_cast(CurrentI)) {
// Is it OK to get metadata from OrigSelect?!
// Create a Select placeholder with dummy value.
SelectInst *Select =
SelectInst::Create(OrigSelect->getCondition(), Dummy, Dummy,
OrigSelect->getName(), OrigSelect, OrigSelect);
Map[Current] = Select;
ST.insertNewSelect(Select);
// We are interested in True and False value in this basic block.
Worklist.push_back({ OrigSelect->getTrueValue(), CurrentBlock });
Worklist.push_back({ OrigSelect->getFalseValue(), CurrentBlock });
} else {
// It must be a Phi node then.
auto *CurrentPhi = cast(CurrentI);
// Create new Phi node for merge of bases.
assert(PredCount && "Unreachable block?!");
PHINode *PHI = PHINode::Create(CommonType, PredCount, "sunk_phi",
&CurrentBlock->front());
Map[Current] = PHI;
ST.insertNewPhi(PHI);
// Add all predecessors in work list.
for (auto B : predecessors(CurrentBlock))
Worklist.push_back({ CurrentPhi->getIncomingValueForBlock(B), B });
}
}
}
bool addrModeCombiningAllowed() {
if (DisableComplexAddrModes)
return false;
switch (DifferentField) {
default:
return false;
case ExtAddrMode::BaseRegField:
return AddrSinkCombineBaseReg;
case ExtAddrMode::BaseGVField:
return AddrSinkCombineBaseGV;
case ExtAddrMode::BaseOffsField:
return AddrSinkCombineBaseOffs;
case ExtAddrMode::ScaledRegField:
return AddrSinkCombineScaledReg;
}
}
};
} // end anonymous namespace
/// Try adding ScaleReg*Scale to the current addressing mode.
/// Return true and update AddrMode if this addr mode is legal for the target,
/// false if not.
bool AddressingModeMatcher::matchScaledValue(Value *ScaleReg, int64_t Scale,
unsigned Depth) {
// If Scale is 1, then this is the same as adding ScaleReg to the addressing
// mode. Just process that directly.
if (Scale == 1)
return matchAddr(ScaleReg, Depth);
// If the scale is 0, it takes nothing to add this.
if (Scale == 0)
return true;
// If we already have a scale of this value, we can add to it, otherwise, we
// need an available scale field.
if (AddrMode.Scale != 0 && AddrMode.ScaledReg != ScaleReg)
return false;
ExtAddrMode TestAddrMode = AddrMode;
// Add scale to turn X*4+X*3 -> X*7. This could also do things like
// [A+B + A*7] -> [B+A*8].
TestAddrMode.Scale += Scale;
TestAddrMode.ScaledReg = ScaleReg;
// If the new address isn't legal, bail out.
if (!TLI.isLegalAddressingMode(DL, TestAddrMode, AccessTy, AddrSpace))
return false;
// It was legal, so commit it.
AddrMode = TestAddrMode;
// Okay, we decided that we can add ScaleReg+Scale to AddrMode. Check now
// to see if ScaleReg is actually X+C. If so, we can turn this into adding
// X*Scale + C*Scale to addr mode.
ConstantInt *CI = nullptr; Value *AddLHS = nullptr;
if (isa(ScaleReg) && // not a constant expr.
match(ScaleReg, m_Add(m_Value(AddLHS), m_ConstantInt(CI)))) {
TestAddrMode.ScaledReg = AddLHS;
TestAddrMode.BaseOffs += CI->getSExtValue()*TestAddrMode.Scale;
// If this addressing mode is legal, commit it and remember that we folded
// this instruction.
if (TLI.isLegalAddressingMode(DL, TestAddrMode, AccessTy, AddrSpace)) {
AddrModeInsts.push_back(cast(ScaleReg));
AddrMode = TestAddrMode;
return true;
}
}
// Otherwise, not (x+c)*scale, just return what we have.
return true;
}
/// This is a little filter, which returns true if an addressing computation
/// involving I might be folded into a load/store accessing it.
/// This doesn't need to be perfect, but needs to accept at least
/// the set of instructions that MatchOperationAddr can.
static bool MightBeFoldableInst(Instruction *I) {
switch (I->getOpcode()) {
case Instruction::BitCast:
case Instruction::AddrSpaceCast:
// Don't touch identity bitcasts.
if (I->getType() == I->getOperand(0)->getType())
return false;
return I->getType()->isIntOrPtrTy();
case Instruction::PtrToInt:
// PtrToInt is always a noop, as we know that the int type is pointer sized.
return true;
case Instruction::IntToPtr:
// We know the input is intptr_t, so this is foldable.
return true;
case Instruction::Add:
return true;
case Instruction::Mul:
case Instruction::Shl:
// Can only handle X*C and X << C.
return isa(I->getOperand(1));
case Instruction::GetElementPtr:
return true;
default:
return false;
}
}
/// Check whether or not \p Val is a legal instruction for \p TLI.
/// \note \p Val is assumed to be the product of some type promotion.
/// Therefore if \p Val has an undefined state in \p TLI, this is assumed
/// to be legal, as the non-promoted value would have had the same state.
static bool isPromotedInstructionLegal(const TargetLowering &TLI,
const DataLayout &DL, Value *Val) {
Instruction *PromotedInst = dyn_cast(Val);
if (!PromotedInst)
return false;
int ISDOpcode = TLI.InstructionOpcodeToISD(PromotedInst->getOpcode());
// If the ISDOpcode is undefined, it was undefined before the promotion.
if (!ISDOpcode)
return true;
// Otherwise, check if the promoted instruction is legal or not.
return TLI.isOperationLegalOrCustom(
ISDOpcode, TLI.getValueType(DL, PromotedInst->getType()));
}
namespace {
/// Hepler class to perform type promotion.
class TypePromotionHelper {
/// Utility function to add a promoted instruction \p ExtOpnd to
/// \p PromotedInsts and record the type of extension we have seen.
static void addPromotedInst(InstrToOrigTy &PromotedInsts,
Instruction *ExtOpnd,
bool IsSExt) {
ExtType ExtTy = IsSExt ? SignExtension : ZeroExtension;
InstrToOrigTy::iterator It = PromotedInsts.find(ExtOpnd);
if (It != PromotedInsts.end()) {
// If the new extension is same as original, the information in
// PromotedInsts[ExtOpnd] is still correct.
if (It->second.getInt() == ExtTy)
return;
// Now the new extension is different from old extension, we make
// the type information invalid by setting extension type to
// BothExtension.
ExtTy = BothExtension;
}
PromotedInsts[ExtOpnd] = TypeIsSExt(ExtOpnd->getType(), ExtTy);
}
/// Utility function to query the original type of instruction \p Opnd
/// with a matched extension type. If the extension doesn't match, we
/// cannot use the information we had on the original type.
/// BothExtension doesn't match any extension type.
static const Type *getOrigType(const InstrToOrigTy &PromotedInsts,
Instruction *Opnd,
bool IsSExt) {
ExtType ExtTy = IsSExt ? SignExtension : ZeroExtension;
InstrToOrigTy::const_iterator It = PromotedInsts.find(Opnd);
if (It != PromotedInsts.end() && It->second.getInt() == ExtTy)
return It->second.getPointer();
return nullptr;
}
/// Utility function to check whether or not a sign or zero extension
/// of \p Inst with \p ConsideredExtType can be moved through \p Inst by
/// either using the operands of \p Inst or promoting \p Inst.
/// The type of the extension is defined by \p IsSExt.
/// In other words, check if:
/// ext (Ty Inst opnd1 opnd2 ... opndN) to ConsideredExtType.
/// #1 Promotion applies:
/// ConsideredExtType Inst (ext opnd1 to ConsideredExtType, ...).
/// #2 Operand reuses:
/// ext opnd1 to ConsideredExtType.
/// \p PromotedInsts maps the instructions to their type before promotion.
static bool canGetThrough(const Instruction *Inst, Type *ConsideredExtType,
const InstrToOrigTy &PromotedInsts, bool IsSExt);
/// Utility function to determine if \p OpIdx should be promoted when
/// promoting \p Inst.
static bool shouldExtOperand(const Instruction *Inst, int OpIdx) {
return !(isa(Inst) && OpIdx == 0);
}
/// Utility function to promote the operand of \p Ext when this
/// operand is a promotable trunc or sext or zext.
/// \p PromotedInsts maps the instructions to their type before promotion.
/// \p CreatedInstsCost[out] contains the cost of all instructions
/// created to promote the operand of Ext.
/// Newly added extensions are inserted in \p Exts.
/// Newly added truncates are inserted in \p Truncs.
/// Should never be called directly.
/// \return The promoted value which is used instead of Ext.
static Value *promoteOperandForTruncAndAnyExt(
Instruction *Ext, TypePromotionTransaction &TPT,
InstrToOrigTy &PromotedInsts, unsigned &CreatedInstsCost,
SmallVectorImpl *Exts,
SmallVectorImpl *Truncs, const TargetLowering &TLI);
/// Utility function to promote the operand of \p Ext when this
/// operand is promotable and is not a supported trunc or sext.
/// \p PromotedInsts maps the instructions to their type before promotion.
/// \p CreatedInstsCost[out] contains the cost of all the instructions
/// created to promote the operand of Ext.
/// Newly added extensions are inserted in \p Exts.
/// Newly added truncates are inserted in \p Truncs.
/// Should never be called directly.
/// \return The promoted value which is used instead of Ext.
static Value *promoteOperandForOther(Instruction *Ext,
TypePromotionTransaction &TPT,
InstrToOrigTy &PromotedInsts,
unsigned &CreatedInstsCost,
SmallVectorImpl *Exts,
SmallVectorImpl *Truncs,
const TargetLowering &TLI, bool IsSExt);
/// \see promoteOperandForOther.
static Value *signExtendOperandForOther(
Instruction *Ext, TypePromotionTransaction &TPT,
InstrToOrigTy &PromotedInsts, unsigned &CreatedInstsCost,
SmallVectorImpl *Exts,
SmallVectorImpl *Truncs, const TargetLowering &TLI) {
return promoteOperandForOther(Ext, TPT, PromotedInsts, CreatedInstsCost,
Exts, Truncs, TLI, true);
}
/// \see promoteOperandForOther.
static Value *zeroExtendOperandForOther(
Instruction *Ext, TypePromotionTransaction &TPT,
InstrToOrigTy &PromotedInsts, unsigned &CreatedInstsCost,
SmallVectorImpl *Exts,
SmallVectorImpl *Truncs, const TargetLowering &TLI) {
return promoteOperandForOther(Ext, TPT, PromotedInsts, CreatedInstsCost,
Exts, Truncs, TLI, false);
}
public:
/// Type for the utility function that promotes the operand of Ext.
using Action = Value *(*)(Instruction *Ext, TypePromotionTransaction &TPT,
InstrToOrigTy &PromotedInsts,
unsigned &CreatedInstsCost,
SmallVectorImpl *Exts,
SmallVectorImpl *Truncs,
const TargetLowering &TLI);
/// Given a sign/zero extend instruction \p Ext, return the appropriate
/// action to promote the operand of \p Ext instead of using Ext.
/// \return NULL if no promotable action is possible with the current
/// sign extension.
/// \p InsertedInsts keeps track of all the instructions inserted by the
/// other CodeGenPrepare optimizations. This information is important
/// because we do not want to promote these instructions as CodeGenPrepare
/// will reinsert them later. Thus creating an infinite loop: create/remove.
/// \p PromotedInsts maps the instructions to their type before promotion.
static Action getAction(Instruction *Ext, const SetOfInstrs &InsertedInsts,
const TargetLowering &TLI,
const InstrToOrigTy &PromotedInsts);
};
} // end anonymous namespace
bool TypePromotionHelper::canGetThrough(const Instruction *Inst,
Type *ConsideredExtType,
const InstrToOrigTy &PromotedInsts,
bool IsSExt) {
// The promotion helper does not know how to deal with vector types yet.
// To be able to fix that, we would need to fix the places where we
// statically extend, e.g., constants and such.
if (Inst->getType()->isVectorTy())
return false;
// We can always get through zext.
if (isa(Inst))
return true;
// sext(sext) is ok too.
if (IsSExt && isa(Inst))
return true;
// We can get through binary operator, if it is legal. In other words, the
// binary operator must have a nuw or nsw flag.
const BinaryOperator *BinOp = dyn_cast(Inst);
if (BinOp && isa(BinOp) &&
((!IsSExt && BinOp->hasNoUnsignedWrap()) ||
(IsSExt && BinOp->hasNoSignedWrap())))
return true;
// ext(and(opnd, cst)) --> and(ext(opnd), ext(cst))
if ((Inst->getOpcode() == Instruction::And ||
Inst->getOpcode() == Instruction::Or))
return true;
// ext(xor(opnd, cst)) --> xor(ext(opnd), ext(cst))
if (Inst->getOpcode() == Instruction::Xor) {
const ConstantInt *Cst = dyn_cast(Inst->getOperand(1));
// Make sure it is not a NOT.
if (Cst && !Cst->getValue().isAllOnesValue())
return true;
}
// zext(shrl(opnd, cst)) --> shrl(zext(opnd), zext(cst))
// It may change a poisoned value into a regular value, like
// zext i32 (shrl i8 %val, 12) --> shrl i32 (zext i8 %val), 12
// poisoned value regular value
// It should be OK since undef covers valid value.
if (Inst->getOpcode() == Instruction::LShr && !IsSExt)
return true;
// and(ext(shl(opnd, cst)), cst) --> and(shl(ext(opnd), ext(cst)), cst)
// It may change a poisoned value into a regular value, like
// zext i32 (shl i8 %val, 12) --> shl i32 (zext i8 %val), 12
// poisoned value regular value
// It should be OK since undef covers valid value.
if (Inst->getOpcode() == Instruction::Shl && Inst->hasOneUse()) {
const Instruction *ExtInst =
dyn_cast(*Inst->user_begin());
if (ExtInst->hasOneUse()) {
const Instruction *AndInst =
dyn_cast(*ExtInst->user_begin());
if (AndInst && AndInst->getOpcode() == Instruction::And) {
const ConstantInt *Cst = dyn_cast(AndInst->getOperand(1));
if (Cst &&
Cst->getValue().isIntN(Inst->getType()->getIntegerBitWidth()))
return true;
}
}
}
// Check if we can do the following simplification.
// ext(trunc(opnd)) --> ext(opnd)
if (!isa(Inst))
return false;
Value *OpndVal = Inst->getOperand(0);
// Check if we can use this operand in the extension.
// If the type is larger than the result type of the extension, we cannot.
if (!OpndVal->getType()->isIntegerTy() ||
OpndVal->getType()->getIntegerBitWidth() >
ConsideredExtType->getIntegerBitWidth())
return false;
// If the operand of the truncate is not an instruction, we will not have
// any information on the dropped bits.
// (Actually we could for constant but it is not worth the extra logic).
Instruction *Opnd = dyn_cast(OpndVal);
if (!Opnd)
return false;
// Check if the source of the type is narrow enough.
// I.e., check that trunc just drops extended bits of the same kind of
// the extension.
// #1 get the type of the operand and check the kind of the extended bits.
const Type *OpndType = getOrigType(PromotedInsts, Opnd, IsSExt);
if (OpndType)
;
else if ((IsSExt && isa(Opnd)) || (!IsSExt && isa(Opnd)))
OpndType = Opnd->getOperand(0)->getType();
else
return false;
// #2 check that the truncate just drops extended bits.
return Inst->getType()->getIntegerBitWidth() >=
OpndType->getIntegerBitWidth();
}
TypePromotionHelper::Action TypePromotionHelper::getAction(
Instruction *Ext, const SetOfInstrs &InsertedInsts,
const TargetLowering &TLI, const InstrToOrigTy &PromotedInsts) {
assert((isa