16#include "llvm/Config/llvm-config.h"
27 cl::desc(
"Enable phi-translation of add instructions"));
30 if (isa<PHINode>(Inst) || isa<GetElementPtrInst>(Inst) || isa<CastInst>(Inst))
33 if (Inst->
getOpcode() == Instruction::Add &&
40#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
43 dbgs() <<
"PHITransAddr: null\n";
46 dbgs() <<
"PHITransAddr: " << *Addr <<
"\n";
47 for (
unsigned i = 0, e = InstInputs.size(); i != e; ++i)
48 dbgs() <<
" Input #" << i <<
" is " << *InstInputs[i] <<
"\n";
60 if (
auto Entry =
find(InstInputs,
I); Entry != InstInputs.
end()) {
61 InstInputs.
erase(Entry);
68 errs() <<
"Instruction in PHITransAddr is not phi-translatable:\n";
71 "canPHITrans is wrong.");
76 [&](
Value *
Op) { return verifySubExpr(Op, InstInputs); });
83 if (!Addr)
return true;
91 errs() <<
"PHITransAddr contains extra instructions:\n";
92 for (
unsigned i = 0, e = InstInputs.size(); i != e; ++i)
93 errs() <<
" InstInput #" << i <<
" is " << *InstInputs[i] <<
"\n";
117 if (
auto Entry =
find(InstInputs,
I); Entry != InstInputs.
end()) {
118 InstInputs.
erase(Entry);
122 assert(!isa<PHINode>(
I) &&
"Error, removing something that isn't an input");
152 InstInputs.erase(
find(InstInputs, Inst));
155 if (
PHINode *PN = dyn_cast<PHINode>(Inst))
156 return addAsInput(PN->getIncomingValueForBlock(PredBB));
173 if (
CastInst *Cast = dyn_cast<CastInst>(Inst)) {
174 Value *PHIIn = translateSubExpr(Cast->getOperand(0), CurBB, PredBB, DT);
175 if (!PHIIn)
return nullptr;
176 if (PHIIn == Cast->getOperand(0))
183 {DL, TLI, DT, AC})) {
185 return addAsInput(V);
191 if (
CastInst *CastI = dyn_cast<CastInst>(U))
192 if (CastI->getOpcode() == Cast->getOpcode() &&
193 CastI->getType() == Cast->getType() &&
194 (!DT || DT->
dominates(CastI->getParent(), PredBB)))
203 bool AnyChanged =
false;
205 Value *GEPOp = translateSubExpr(
Op, CurBB, PredBB, DT);
206 if (!GEPOp)
return nullptr;
208 AnyChanged |= GEPOp !=
Op;
218 GEP->getNoWrapFlags(), {DL, TLI, DT, AC})) {
222 return addAsInput(V);
226 Value *APHIOp = GEPOps[0];
229 if (GEPI->getType() ==
GEP->getType() &&
230 GEPI->getSourceElementType() ==
GEP->getSourceElementType() &&
231 GEPI->getNumOperands() == GEPOps.
size() &&
232 GEPI->getParent()->getParent() == CurBB->
getParent() &&
233 (!DT || DT->
dominates(GEPI->getParent(), PredBB))) {
234 if (std::equal(GEPOps.
begin(), GEPOps.
end(), GEPI->op_begin()))
242 if (Inst->
getOpcode() == Instruction::Add &&
246 bool isNSW = cast<BinaryOperator>(Inst)->hasNoSignedWrap();
247 bool isNUW = cast<BinaryOperator>(Inst)->hasNoUnsignedWrap();
250 if (!LHS)
return nullptr;
254 if (BOp->getOpcode() == Instruction::Add)
255 if (
ConstantInt *CI = dyn_cast<ConstantInt>(BOp->getOperand(1))) {
256 LHS = BOp->getOperand(0);
258 isNSW = isNUW =
false;
272 return addAsInput(Res);
282 if (BO->getOpcode() == Instruction::Add &&
283 BO->getOperand(0) == LHS && BO->getOperand(1) == RHS &&
284 BO->getParent()->getParent() == CurBB->
getParent() &&
285 (!DT || DT->
dominates(BO->getParent(), PredBB)))
302 assert(DT || !MustDominate);
305 Addr = translateSubExpr(Addr, CurBB, PredBB, DT);
312 if (
Instruction *Inst = dyn_cast_or_null<Instruction>(Addr))
330 unsigned NISize = NewInsts.
size();
333 Addr = insertTranslatedSubExpr(Addr, CurBB, PredBB, DT, NewInsts);
336 if (Addr)
return Addr;
339 while (NewInsts.
size() != NISize)
349Value *PHITransAddr::insertTranslatedSubExpr(
356 Tmp.translateValue(CurBB, PredBB, &DT,
true))
360 auto *Inst = dyn_cast<Instruction>(InVal);
365 if (
CastInst *Cast = dyn_cast<CastInst>(Inst)) {
366 Value *OpVal = insertTranslatedSubExpr(Cast->getOperand(0), CurBB, PredBB,
368 if (!OpVal)
return nullptr;
372 InVal->
getName() +
".phi.trans.insert",
384 Value *OpVal = insertTranslatedSubExpr(
Op, CurBB, PredBB, DT, NewInsts);
385 if (!OpVal)
return nullptr;
390 GEP->getSourceElementType(), GEPOps[0],
ArrayRef(GEPOps).slice(1),
391 InVal->
getName() +
".phi.trans.insert",
394 Result->setNoWrapFlags(
GEP->getNoWrapFlags());
408 Value *OpVal = insertTranslatedSubExpr(Inst->
getOperand(0), CurBB, PredBB,
410 if (OpVal ==
nullptr)
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static bool hasNoSignedWrap(BinaryOperator &I)
static bool hasNoUnsignedWrap(BinaryOperator &I)
static bool isInput(const ArrayRef< StringLiteral > &Prefixes, StringRef Arg)
static void RemoveInstInputs(Value *V, SmallVectorImpl< Instruction * > &InstInputs)
static bool canPHITrans(Instruction *Inst)
static cl::opt< bool > EnableAddPhiTranslation("gvn-add-phi-translation", cl::init(false), cl::Hidden, cl::desc("Enable phi-translation of add instructions"))
static bool verifySubExpr(Value *Expr, SmallVectorImpl< Instruction * > &InstInputs)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
ArrayRef< T > slice(size_t N, size_t M) const
slice(n, m) - Chop off the first N elements of the array, and keep M elements in the array.
LLVM Basic Block Representation.
const Function * getParent() const
Return the enclosing method, or null if none.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
This is the base class for all instructions that perform data casts.
static CastInst * Create(Instruction::CastOps, Value *S, Type *Ty, const Twine &Name="", InsertPosition InsertBefore=nullptr)
Provides a way to construct any of the CastInst subclasses using an opcode instead of the subclass's ...
static Constant * getAdd(Constant *C1, Constant *C2, bool HasNUW=false, bool HasNSW=false)
This is the shared class of boolean and integer constants.
This is an important base class in LLVM.
This class represents an Operation in the Expression.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
bool isReachableFromEntry(const Use &U) const
Provide an overload for a Use.
bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
static GetElementPtrInst * Create(Type *PointeeType, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
void setHasNoUnsignedWrap(bool b=true)
Set or clear the nuw flag on this instruction, which must be an operator which supports this flag.
void setHasNoSignedWrap(bool b=true)
Set or clear the nsw flag on this instruction, which must be an operator which supports this flag.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
PHITransAddr - An address value which tracks and handles phi translation.
Value * translateValue(BasicBlock *CurBB, BasicBlock *PredBB, const DominatorTree *DT, bool MustDominate)
translateValue - PHI translate the current address up the CFG from CurBB to Pred, updating our state ...
bool isPotentiallyPHITranslatable() const
isPotentiallyPHITranslatable - If this needs PHI translation, return true if we have some hope of doi...
bool verify() const
verify - Check internal consistency of this data structure.
Value * translateWithInsertion(BasicBlock *CurBB, BasicBlock *PredBB, const DominatorTree &DT, SmallVectorImpl< Instruction * > &NewInsts)
translateWithInsertion - PHI translate this value into the specified predecessor block,...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
iterator erase(const_iterator CI)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
iterator_range< user_iterator > users()
StringRef getName() const
Return a constant reference to the value's name.
const ParentTy * getParent() const
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Value * simplifyGEPInst(Type *SrcTy, Value *Ptr, ArrayRef< Value * > Indices, GEPNoWrapFlags NW, const SimplifyQuery &Q)
Given operands for a GetElementPtrInst, fold the result or return null.
Value * simplifyCastInst(unsigned CastOpc, Value *Op, Type *Ty, const SimplifyQuery &Q)
Given operands for a CastInst, fold the result or return null.
Value * simplifyAddInst(Value *LHS, Value *RHS, bool IsNSW, bool IsNUW, const SimplifyQuery &Q)
Given operands for an Add, fold the result or return null.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
DWARFExpression::Operation Op
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.