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)) {
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 = dyn_cast_if_present<MutableAggregate *>(Val))
132 const MutableValue *
V =
this;
133 while (
const auto *Agg = dyn_cast_if_present<MutableAggregate *>(
V->Val)) {
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 (isa<Constant *>(MV->Val) && !MV->makeMutable())
177 MutableAggregate *Agg = cast<MutableAggregate *>(MV->Val);
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)) {
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());
418 if (!Val->
isNullValue() || MutatedMemory.contains(GV) ||
422 if (
Len.ugt(64 * 1024)) {
430 if (DestVal != Val) {
432 <<
Offset <<
" of " << *GV <<
".\n");
445 if (
II->isLifetimeStartOrEnd()) {
451 if (
II->getIntrinsicID() == Intrinsic::invariant_start) {
454 if (!
II->use_empty()) {
456 <<
"Found unused invariant_start. Can't evaluate.\n");
460 Value *PtrArg = getVal(
II->getArgOperand(1));
464 if (!
Size->isMinusOne() &&
465 Size->getValue().getLimitedValue() >=
466 DL.getTypeStoreSize(ElemTy)) {
467 Invariants.insert(GV);
472 <<
"Found a global var, but can not treat it as an "
479 }
else if (
II->getIntrinsicID() == Intrinsic::assume) {
483 }
else if (
II->getIntrinsicID() == Intrinsic::sideeffect) {
487 }
else if (
II->getIntrinsicID() == Intrinsic::pseudoprobe) {
496 if (Stripped != &*CurInst) {
497 InstResult = getVal(Stripped);
501 <<
"Stripped pointer casts for alias analysis for "
502 "intrinsic call.\n");
503 StrippedPointerCastsForAliasAnalysis =
true;
516 if (!Callee ||
Callee->isInterposable()) {
521 if (
Callee->isDeclaration()) {
524 InstResult = castCallResultIfNeeded(CB.
getType(),
C);
528 << *InstResult <<
"\n");
534 if (
Callee->getFunctionType()->isVarArg()) {
536 <<
"Can not constant fold vararg function call.\n");
542 ValueStack.emplace_back();
547 ValueStack.pop_back();
548 InstResult = castCallResultIfNeeded(CB.
getType(), RetVal);
549 if (RetVal && !InstResult)
554 << *InstResult <<
"\n\n");
557 <<
"Successfully evaluated function. Result: 0\n\n");
561 }
else if (CurInst->isTerminator()) {
564 if (
BranchInst *BI = dyn_cast<BranchInst>(CurInst)) {
565 if (BI->isUnconditional()) {
566 NextBB = BI->getSuccessor(0);
569 dyn_cast<ConstantInt>(getVal(BI->getCondition()));
570 if (!
Cond)
return false;
572 NextBB = BI->getSuccessor(!
Cond->getZExtValue());
574 }
else if (
SwitchInst *SI = dyn_cast<SwitchInst>(CurInst)) {
576 dyn_cast<ConstantInt>(getVal(
SI->getCondition()));
577 if (!Val)
return false;
578 NextBB =
SI->findCaseValue(Val)->getCaseSuccessor();
579 }
else if (
IndirectBrInst *IBI = dyn_cast<IndirectBrInst>(CurInst)) {
582 NextBB = BA->getBasicBlock();
585 }
else if (isa<ReturnInst>(CurInst)) {
598 for (
Value *
Op : CurInst->operands())
602 LLVM_DEBUG(
dbgs() <<
"Cannot fold instruction: " << *CurInst <<
"\n");
606 << *InstResult <<
"\n");
609 if (!CurInst->use_empty()) {
611 setVal(&*CurInst, InstResult);
616 NextBB =
II->getNormalDest();
617 LLVM_DEBUG(
dbgs() <<
"Found an invoke instruction. Finished Block.\n\n");
631 assert(ActualArgs.
size() ==
F->arg_size() &&
"wrong number of arguments");
638 CallStack.push_back(
F);
642 setVal(&Arg, ActualArgs[ArgNo]);
656 LLVM_DEBUG(
dbgs() <<
"Trying to evaluate BB: " << *CurBB <<
"\n");
658 bool StrippedPointerCastsForAliasAnalysis =
false;
660 if (!EvaluateBlock(CurInst, NextBB, StrippedPointerCastsForAliasAnalysis))
673 if (StrippedPointerCastsForAliasAnalysis &&
679 CallStack.pop_back();
686 if (!ExecutedBlocks.
insert(NextBB).second)
693 for (CurInst = NextBB->
begin();
694 (PN = dyn_cast<PHINode>(CurInst)); ++CurInst)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
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)
uint64_t IntrinsicInst * II
const SmallVectorImpl< MachineOperand > & Cond
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
bool isNullValue() const
Return true if this is the value that would be returned by getNullValue.
This class represents an Operation in the Expression.
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.
@ 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 tuples (A, B,...
Constant * ConstantFoldCall(const CallBase *Call, Function *F, ArrayRef< Constant * > Operands, const TargetLibraryInfo *TLI=nullptr, bool AllowNonDeterministic=true)
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.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Constant * ConstantFoldInstOperands(Instruction *I, ArrayRef< Constant * > Ops, const DataLayout &DL, const TargetLibraryInfo *TLI=nullptr, bool AllowNonDeterministic=true)
ConstantFoldInstOperands - Attempt to constant fold an instruction with the specified operands.
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.