40#define DEBUG_TYPE "evaluator"
63 if (
auto *GV = dyn_cast<GlobalValue>(
C))
64 return !GV->hasDLLImportStorageClass() && !GV->isThreadLocal();
67 if (
C->getNumOperands() == 0 || isa<BlockAddress>(
C))
71 if (isa<ConstantAggregate>(
C)) {
72 for (
Value *Op :
C->operands())
82 switch (CE->getOpcode()) {
83 case Instruction::BitCast:
87 case Instruction::IntToPtr:
88 case Instruction::PtrToInt:
91 if (
DL.getTypeSizeInBits(CE->getType()) !=
92 DL.getTypeSizeInBits(CE->getOperand(0)->getType()))
97 case Instruction::GetElementPtr:
98 for (
unsigned i = 1, e = CE->getNumOperands(); i != e; ++i)
99 if (!isa<ConstantInt>(CE->getOperand(i)))
103 case Instruction::Add:
105 if (!isa<ConstantInt>(CE->getOperand(1)))
117 if (!SimpleConstants.
insert(
C).second)
123void Evaluator::MutableValue::clear() {
124 if (
auto *Agg = Val.dyn_cast<MutableAggregate *>())
132 const MutableValue *
V =
this;
133 while (
const auto *Agg =
V->Val.dyn_cast<MutableAggregate *>()) {
134 Type *AggTy = Agg->Ty;
135 std::optional<APInt>
Index =
DL.getGEPIndexForOffset(AggTy,
Offset);
136 if (!
Index ||
Index->uge(Agg->Elements.size()) ||
137 !TypeSize::isKnownLE(TySize,
DL.getTypeStoreSize(AggTy)))
140 V = &Agg->Elements[
Index->getZExtValue()];
146bool Evaluator::MutableValue::makeMutable() {
148 Type *Ty =
C->getType();
149 unsigned NumElements;
150 if (
auto *VT = dyn_cast<FixedVectorType>(Ty)) {
151 NumElements = VT->getNumElements();
152 }
else if (
auto *AT = dyn_cast<ArrayType>(Ty))
153 NumElements = AT->getNumElements();
154 else if (
auto *ST = dyn_cast<StructType>(Ty))
155 NumElements =
ST->getNumElements();
159 MutableAggregate *MA =
new MutableAggregate(Ty);
160 MA->Elements.reserve(NumElements);
161 for (
unsigned I = 0;
I < NumElements; ++
I)
162 MA->Elements.push_back(
C->getAggregateElement(
I));
169 Type *Ty =
V->getType();
171 MutableValue *MV =
this;
174 if (MV->Val.is<
Constant *>() && !MV->makeMutable())
177 MutableAggregate *Agg = MV->Val.get<MutableAggregate *>();
178 Type *AggTy = Agg->Ty;
179 std::optional<APInt>
Index =
DL.getGEPIndexForOffset(AggTy,
Offset);
180 if (!
Index ||
Index->uge(Agg->Elements.size()) ||
181 !TypeSize::isKnownLE(TySize,
DL.getTypeStoreSize(AggTy)))
184 MV = &Agg->Elements[
Index->getZExtValue()];
187 Type *MVType = MV->getType();
193 else if (Ty != MVType)
200Constant *Evaluator::MutableAggregate::toConstant()
const {
202 for (
const MutableValue &MV : Elements)
205 if (
auto *ST = dyn_cast<StructType>(Ty))
207 if (
auto *AT = dyn_cast<ArrayType>(Ty))
209 assert(isa<FixedVectorType>(Ty) &&
"Must be vector");
217 P = cast<Constant>(
P->stripAndAccumulateConstantOffsets(
220 if (
auto *GV = dyn_cast<GlobalVariable>(
P))
221 return ComputeLoadResult(GV, Ty,
Offset);
227 auto It = MutatedMemory.find(GV);
228 if (It != MutatedMemory.end())
229 return It->second.read(Ty,
Offset, DL);
237 if (
auto *Fn = dyn_cast<Function>(
C))
240 if (
auto *Alias = dyn_cast<GlobalAlias>(
C))
241 if (
auto *Fn = dyn_cast<Function>(Alias->getAliasee()))
247Evaluator::getCalleeWithFormalArgs(
CallBase &CB,
251 return getFormalParams(CB, Fn, Formals) ? Fn :
nullptr;
260 auto *FTy =
F->getFunctionType();
261 if (FTy->getNumParams() > CB.
arg_size()) {
267 for (
Type *PTy : FTy->params()) {
282 if (!RV || RV->
getType() == ReturnType)
296 bool &StrippedPointerCastsForAliasAnalysis) {
301 LLVM_DEBUG(
dbgs() <<
"Evaluating Instruction: " << *CurInst <<
"\n");
303 if (
StoreInst *SI = dyn_cast<StoreInst>(CurInst)) {
304 if (
SI->isVolatile()) {
310 if (
Ptr != FoldedPtr) {
317 Ptr = cast<Constant>(
Ptr->stripAndAccumulateConstantOffsets(
320 auto *GV = dyn_cast<GlobalVariable>(
Ptr);
322 LLVM_DEBUG(
dbgs() <<
"Store is not to global with unique initializer: "
331 LLVM_DEBUG(
dbgs() <<
"Store value is too complex to evaluate store. "
337 if (!Res.first->second.write(Val,
Offset, DL))
339 }
else if (
LoadInst *LI = dyn_cast<LoadInst>(CurInst)) {
340 if (LI->isVolatile()) {
342 dbgs() <<
"Found a Load! Volatile load, can not evaluate.\n");
348 if (
Ptr != FoldedPtr) {
350 LLVM_DEBUG(
dbgs() <<
"Found a constant pointer expression, constant "
354 InstResult = ComputeLoadResult(
Ptr, LI->getType());
357 dbgs() <<
"Failed to compute load result. Can not evaluate load."
363 }
else if (
AllocaInst *AI = dyn_cast<AllocaInst>(CurInst)) {
364 if (AI->isArrayAllocation()) {
365 LLVM_DEBUG(
dbgs() <<
"Found an array alloca. Can not evaluate.\n");
368 Type *Ty = AI->getAllocatedType();
369 AllocaTmps.push_back(std::make_unique<GlobalVariable>(
372 AI->getType()->getPointerAddressSpace()));
373 InstResult = AllocaTmps.back().get();
374 LLVM_DEBUG(
dbgs() <<
"Found an alloca. Result: " << *InstResult <<
"\n");
375 }
else if (isa<CallInst>(CurInst) || isa<InvokeInst>(CurInst)) {
376 CallBase &CB = *cast<CallBase>(&*CurInst);
379 if (isa<DbgInfoIntrinsic>(CB)) {
392 if (
MemSetInst *MSI = dyn_cast<MemSetInst>(II)) {
393 if (MSI->isVolatile()) {
399 auto *LenC = dyn_cast<ConstantInt>(getVal(MSI->getLength()));
407 Ptr = cast<Constant>(
Ptr->stripAndAccumulateConstantOffsets(
409 auto *GV = dyn_cast<GlobalVariable>(
Ptr);
415 Constant *Val = getVal(MSI->getValue());
419 if (DestVal != Val) {
421 <<
Offset <<
" of " << *GV <<
".\n");
433 if (II->isLifetimeStartOrEnd()) {
439 if (II->getIntrinsicID() == Intrinsic::invariant_start) {
442 if (!II->use_empty()) {
444 <<
"Found unused invariant_start. Can't evaluate.\n");
448 Value *PtrArg = getVal(II->getArgOperand(1));
452 if (!
Size->isMinusOne() &&
453 Size->getValue().getLimitedValue() >=
454 DL.getTypeStoreSize(ElemTy)) {
455 Invariants.insert(GV);
460 <<
"Found a global var, but can not treat it as an "
467 }
else if (II->getIntrinsicID() == Intrinsic::assume) {
471 }
else if (II->getIntrinsicID() == Intrinsic::sideeffect) {
475 }
else if (II->getIntrinsicID() == Intrinsic::pseudoprobe) {
484 if (Stripped != &*CurInst) {
485 InstResult = getVal(Stripped);
489 <<
"Stripped pointer casts for alias analysis for "
490 "intrinsic call.\n");
491 StrippedPointerCastsForAliasAnalysis =
true;
509 if (
Callee->isDeclaration()) {
512 InstResult = castCallResultIfNeeded(CB.
getType(),
C);
516 << *InstResult <<
"\n");
524 <<
"Can not constant fold vararg function call.\n");
530 ValueStack.emplace_back();
535 ValueStack.pop_back();
536 InstResult = castCallResultIfNeeded(CB.
getType(), RetVal);
537 if (RetVal && !InstResult)
542 << *InstResult <<
"\n\n");
545 <<
"Successfully evaluated function. Result: 0\n\n");
549 }
else if (CurInst->isTerminator()) {
552 if (
BranchInst *BI = dyn_cast<BranchInst>(CurInst)) {
553 if (BI->isUnconditional()) {
554 NextBB = BI->getSuccessor(0);
557 dyn_cast<ConstantInt>(getVal(BI->getCondition()));
558 if (!
Cond)
return false;
560 NextBB = BI->getSuccessor(!
Cond->getZExtValue());
562 }
else if (
SwitchInst *SI = dyn_cast<SwitchInst>(CurInst)) {
564 dyn_cast<ConstantInt>(getVal(
SI->getCondition()));
565 if (!Val)
return false;
566 NextBB =
SI->findCaseValue(Val)->getCaseSuccessor();
567 }
else if (
IndirectBrInst *IBI = dyn_cast<IndirectBrInst>(CurInst)) {
570 NextBB = BA->getBasicBlock();
573 }
else if (isa<ReturnInst>(CurInst)) {
586 for (
Value *Op : CurInst->operands())
590 LLVM_DEBUG(
dbgs() <<
"Cannot fold instruction: " << *CurInst <<
"\n");
594 << *InstResult <<
"\n");
597 if (!CurInst->use_empty()) {
599 setVal(&*CurInst, InstResult);
603 if (
InvokeInst *II = dyn_cast<InvokeInst>(CurInst)) {
604 NextBB = II->getNormalDest();
605 LLVM_DEBUG(
dbgs() <<
"Found an invoke instruction. Finished Block.\n\n");
619 assert(ActualArgs.
size() ==
F->arg_size() &&
"wrong number of arguments");
626 CallStack.push_back(
F);
630 setVal(&
Arg, ActualArgs[ArgNo]);
644 LLVM_DEBUG(
dbgs() <<
"Trying to evaluate BB: " << *CurBB <<
"\n");
646 bool StrippedPointerCastsForAliasAnalysis =
false;
648 if (!EvaluateBlock(CurInst, NextBB, StrippedPointerCastsForAliasAnalysis))
661 if (StrippedPointerCastsForAliasAnalysis &&
667 CallStack.pop_back();
674 if (!ExecutedBlocks.
insert(NextBB).second)
681 for (CurInst = NextBB->
begin();
682 (PN = dyn_cast<PHINode>(CurInst)); ++CurInst)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
amdgpu Simplify well known AMD library false FunctionCallee Callee
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
SmallVector< MachineOperand, 4 > Cond
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file defines the DenseMap class.
static bool isSimpleEnoughValueToCommitHelper(Constant *C, SmallPtrSetImpl< Constant * > &SimpleConstants, const DataLayout &DL)
Return true if the specified constant can be handled by the code generator.
static bool isSimpleEnoughValueToCommit(Constant *C, SmallPtrSetImpl< Constant * > &SimpleConstants, const DataLayout &DL)
static Function * getFunction(Constant *C)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
Class for arbitrary precision integers.
an instruction to allocate memory on the stack
LLVM Basic Block Representation.
iterator begin()
Instruction iterator methods.
InstListType::iterator iterator
Instruction iterators...
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...
The address of a basic block.
Conditional or Unconditional Branch instruction.
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
bool isInlineAsm() const
Check if this call is an inline asm statement.
User::op_iterator arg_begin()
Return the iterator pointing to the beginning of the argument list.
Value * getCalledOperand() const
unsigned arg_size() const
static bool isBitOrNoopPointerCastable(Type *SrcTy, Type *DestTy, const DataLayout &DL)
Check whether a bitcast, inttoptr, or ptrtoint cast between these types is valid and a no-op.
static Constant * get(ArrayType *T, ArrayRef< Constant * > V)
A constant value that is initialized with an expression using other constant values.
static Constant * getIntToPtr(Constant *C, Type *Ty, bool OnlyIfReduced=false)
static Constant * getPtrToInt(Constant *C, Type *Ty, bool OnlyIfReduced=false)
static Constant * getBitCast(Constant *C, Type *Ty, bool OnlyIfReduced=false)
This is the shared class of boolean and integer constants.
static Constant * get(StructType *T, ArrayRef< Constant * > V)
static Constant * get(ArrayRef< Constant * > V)
This is an important base class in LLVM.
const Constant * stripPointerCasts() const
A parsed version of the target data layout string in and methods for querying it.
bool EvaluateFunction(Function *F, Constant *&RetVal, const SmallVectorImpl< Constant * > &ActualArgs)
Evaluate a call to function F, returning true if successful, false if we can't evaluate it.
FunctionType * getFunctionType()
@ InternalLinkage
Rename collisions when linking (static functions).
Type * getValueType() const
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
bool hasUniqueInitializer() const
hasUniqueInitializer - Whether the global variable has an initializer, and any changes made to the in...
bool hasDefinitiveInitializer() const
hasDefinitiveInitializer - Whether the global variable has an initializer, and any other instances of...
Indirect Branch Instruction.
A wrapper class for inspecting calls to intrinsic functions.
An instruction for reading from memory.
This class wraps the llvm.memset and llvm.memset.inline intrinsics.
Value * getIncomingValueForBlock(const BasicBlock *BB) const
Return a value (possibly void), from a function.
Value * getReturnValue() const
Convenience accessor. Returns null if there is no return value.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
The instances of the Type class are immutable: once they are created, they are never changed.
bool isPointerTy() const
True if this is an instance of PointerType.
bool isIntegerTy() const
True if this is an instance of IntegerType.
bool isVoidTy() const
Return true if this is 'void'.
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
StringRef getName() const
Return a constant reference to the value's name.
const Value * stripPointerCastsForAliasAnalysis() const
Strip off pointer casts, all-zero GEPs, single-argument phi nodes and invariant group info.
@ C
The default llvm calling convention, compatible with C.
This is an optimization pass for GlobalISel generic memory operations.
Constant * ConstantFoldLoadThroughBitcast(Constant *C, Type *DestTy, const DataLayout &DL)
ConstantFoldLoadThroughBitcast - try to cast constant to destination type returning null if unsuccess...
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are are tuples (A,...
Constant * ConstantFoldCall(const CallBase *Call, Function *F, ArrayRef< Constant * > Operands, const TargetLibraryInfo *TLI=nullptr)
ConstantFoldCall - Attempt to constant fold a call to the specified function with the specified argum...
Constant * ConstantFoldConstant(const Constant *C, const DataLayout &DL, const TargetLibraryInfo *TLI=nullptr)
ConstantFoldConstant - Fold the constant using the specified DataLayout.
Constant * ConstantFoldInstOperands(Instruction *I, ArrayRef< Constant * > Ops, const DataLayout &DL, const TargetLibraryInfo *TLI=nullptr)
ConstantFoldInstOperands - Attempt to constant fold an instruction with the specified operands.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Constant * ConstantFoldLoadFromConst(Constant *C, Type *Ty, const APInt &Offset, const DataLayout &DL)
Extract value of C at the given Offset reinterpreted as Ty.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.