51#define DEBUG_TYPE "functioncomparator"
62 if (L.value() < R.value())
64 if (L.value() > R.value())
78 if (
int Res =
cmpNumbers(L.getBitWidth(), R.getBitWidth()))
90 const fltSemantics &SL = L.getSemantics(), &SR = R.getSemantics();
103 return cmpAPInts(L.bitcastToAPInt(), R.bitcastToAPInt());
113 return std::clamp(L.compare(R), -1, 1);
118 if (
int Res =
cmpNumbers(L.getNumAttrSets(), R.getNumAttrSets()))
121 for (
unsigned i : L.indexes()) {
126 for (; LI != LE && RI != RE; ++LI, ++RI) {
134 Type *TyR =
RA.getValueAsType();
160int FunctionComparator::cmpMetadata(
const Metadata *L,
167 auto *CL = dyn_cast<ConstantAsMetadata>(L);
168 auto *CR = dyn_cast<ConstantAsMetadata>(R);
178int FunctionComparator::cmpMDNode(
const MDNode *L,
const MDNode *R)
const {
191 if (
int Res =
cmpNumbers(
L->getNumOperands(),
R->getNumOperands()))
193 for (
size_t I = 0;
I <
L->getNumOperands(); ++
I)
194 if (
int Res = cmpMetadata(
L->getOperand(
I),
R->getOperand(
I)))
199int FunctionComparator::cmpInstMetadata(
Instruction const *L,
205 L->getAllMetadataOtherThanDebugLoc(MDL);
206 R->getAllMetadataOtherThanDebugLoc(MDR);
211 for (
size_t I = 0,
N = MDL.
size();
I <
N; ++
I) {
212 auto const [KeyL,
ML] = MDL[
I];
213 auto const [KeyR, MR] = MDR[
I];
216 if (
int Res = cmpMDNode(
ML, MR))
222int FunctionComparator::cmpOperandBundlesSchema(
const CallBase &LCS,
234 if (
int Res = OBL.getTagName().compare(OBR.getTagName()))
237 if (
int Res =
cmpNumbers(OBL.Inputs.size(), OBR.Inputs.size()))
251 Type *TyL = L->getType();
252 Type *TyR = R->getType();
275 unsigned TyLWidth = 0;
276 unsigned TyRWidth = 0;
278 if (
auto *VecTyL = dyn_cast<VectorType>(TyL))
279 TyLWidth = VecTyL->getPrimitiveSizeInBits().getFixedValue();
280 if (
auto *VecTyR = dyn_cast<VectorType>(TyR))
281 TyRWidth = VecTyR->getPrimitiveSizeInBits().getFixedValue();
283 if (TyLWidth != TyRWidth)
293 if (
int Res =
cmpNumbers(AddrSpaceL, AddrSpaceR))
309 if (L->isNullValue() && R->isNullValue())
311 if (L->isNullValue() && !R->isNullValue())
313 if (!L->isNullValue() && R->isNullValue())
316 auto GlobalValueL =
const_cast<GlobalValue *
>(dyn_cast<GlobalValue>(L));
317 auto GlobalValueR =
const_cast<GlobalValue *
>(dyn_cast<GlobalValue>(R));
318 if (GlobalValueL && GlobalValueR) {
322 if (
int Res =
cmpNumbers(L->getValueID(), R->getValueID()))
325 if (
const auto *SeqL = dyn_cast<ConstantDataSequential>(L)) {
326 const auto *SeqR = cast<ConstantDataSequential>(R);
332 return cmpMem(SeqL->getRawDataValues(), SeqR->getRawDataValues());
335 switch (L->getValueID()) {
336 case Value::UndefValueVal:
337 case Value::PoisonValueVal:
338 case Value::ConstantTokenNoneVal:
340 case Value::ConstantIntVal: {
341 const APInt &LInt = cast<ConstantInt>(L)->getValue();
342 const APInt &RInt = cast<ConstantInt>(R)->getValue();
345 case Value::ConstantFPVal: {
346 const APFloat &LAPF = cast<ConstantFP>(L)->getValueAPF();
347 const APFloat &RAPF = cast<ConstantFP>(R)->getValueAPF();
350 case Value::ConstantArrayVal: {
353 uint64_t NumElementsL = cast<ArrayType>(TyL)->getNumElements();
354 uint64_t NumElementsR = cast<ArrayType>(TyR)->getNumElements();
355 if (
int Res =
cmpNumbers(NumElementsL, NumElementsR))
357 for (
uint64_t i = 0; i < NumElementsL; ++i) {
359 cast<Constant>(
RA->getOperand(i))))
364 case Value::ConstantStructVal: {
367 unsigned NumElementsL = cast<StructType>(TyL)->getNumElements();
368 unsigned NumElementsR = cast<StructType>(TyR)->getNumElements();
369 if (
int Res =
cmpNumbers(NumElementsL, NumElementsR))
371 for (
unsigned i = 0; i != NumElementsL; ++i) {
372 if (
int Res =
cmpConstants(cast<Constant>(LS->getOperand(i)),
378 case Value::ConstantVectorVal: {
381 unsigned NumElementsL = cast<FixedVectorType>(TyL)->getNumElements();
382 unsigned NumElementsR = cast<FixedVectorType>(TyR)->getNumElements();
383 if (
int Res =
cmpNumbers(NumElementsL, NumElementsR))
385 for (
uint64_t i = 0; i < NumElementsL; ++i) {
392 case Value::ConstantExprVal: {
395 unsigned NumOperandsL = LE->getNumOperands();
397 if (
int Res =
cmpNumbers(NumOperandsL, NumOperandsR))
399 for (
unsigned i = 0; i < NumOperandsL; ++i) {
400 if (
int Res =
cmpConstants(cast<Constant>(LE->getOperand(i)),
406 case Value::BlockAddressVal: {
440 case Value::DSOLocalEquivalentVal: {
445 const auto *LEquiv = cast<DSOLocalEquivalent>(L);
446 const auto *REquiv = cast<DSOLocalEquivalent>(R);
447 return cmpGlobalValues(LEquiv->getGlobalValue(), REquiv->getGlobalValue());
450 LLVM_DEBUG(
dbgs() <<
"Looking at valueID " << L->getValueID() <<
"\n");
471 TyL =
DL.getIntPtrType(TyL);
473 TyR =
DL.getIntPtrType(TyR);
500 assert(PTyL && PTyR &&
"Both types must be pointers here.");
531 for (
unsigned i = 0, e = FTyL->
getNumParams(); i != e; ++i) {
539 auto *STyL = cast<ArrayType>(TyL);
540 auto *STyR = cast<ArrayType>(TyR);
541 if (STyL->getNumElements() != STyR->getNumElements())
542 return cmpNumbers(STyL->getNumElements(), STyR->getNumElements());
543 return cmpTypes(STyL->getElementType(), STyR->getElementType());
547 auto *STyL = cast<VectorType>(TyL);
548 auto *STyR = cast<VectorType>(TyR);
549 if (STyL->getElementCount().isScalable() !=
550 STyR->getElementCount().isScalable())
551 return cmpNumbers(STyL->getElementCount().isScalable(),
552 STyR->getElementCount().isScalable());
553 if (STyL->getElementCount() != STyR->getElementCount())
554 return cmpNumbers(STyL->getElementCount().getKnownMinValue(),
555 STyR->getElementCount().getKnownMinValue());
556 return cmpTypes(STyL->getElementType(), STyR->getElementType());
567 bool &needToCmpOperands)
const {
568 needToCmpOperands =
true;
576 if (
int Res =
cmpNumbers(L->getOpcode(), R->getOpcode()))
580 needToCmpOperands =
false;
585 return cmpGEPs(GEPL, GEPR);
588 if (
int Res =
cmpNumbers(L->getNumOperands(), R->getNumOperands()))
591 if (
int Res =
cmpTypes(L->getType(), R->getType()))
594 if (
int Res =
cmpNumbers(L->getRawSubclassOptionalData(),
595 R->getRawSubclassOptionalData()))
600 for (
unsigned i = 0, e = L->getNumOperands(); i != e; ++i) {
602 cmpTypes(L->getOperand(i)->getType(), R->getOperand(i)->getType()))
607 if (
const AllocaInst *AI = dyn_cast<AllocaInst>(L)) {
608 if (
int Res =
cmpTypes(AI->getAllocatedType(),
609 cast<AllocaInst>(R)->getAllocatedType()))
611 return cmpAligns(AI->getAlign(), cast<AllocaInst>(R)->getAlign());
613 if (
const LoadInst *LI = dyn_cast<LoadInst>(L)) {
614 if (
int Res =
cmpNumbers(LI->isVolatile(), cast<LoadInst>(R)->isVolatile()))
616 if (
int Res =
cmpAligns(LI->getAlign(), cast<LoadInst>(R)->getAlign()))
619 cmpOrderings(LI->getOrdering(), cast<LoadInst>(R)->getOrdering()))
621 if (
int Res =
cmpNumbers(LI->getSyncScopeID(),
622 cast<LoadInst>(R)->getSyncScopeID()))
624 return cmpInstMetadata(L, R);
626 if (
const StoreInst *SI = dyn_cast<StoreInst>(L)) {
628 cmpNumbers(SI->isVolatile(), cast<StoreInst>(R)->isVolatile()))
630 if (
int Res =
cmpAligns(SI->getAlign(), cast<StoreInst>(R)->getAlign()))
633 cmpOrderings(SI->getOrdering(), cast<StoreInst>(R)->getOrdering()))
636 cast<StoreInst>(R)->getSyncScopeID());
638 if (
const CmpInst *CI = dyn_cast<CmpInst>(L))
639 return cmpNumbers(CI->getPredicate(), cast<CmpInst>(R)->getPredicate());
640 if (
auto *CBL = dyn_cast<CallBase>(L)) {
641 auto *CBR = cast<CallBase>(R);
642 if (
int Res =
cmpNumbers(CBL->getCallingConv(), CBR->getCallingConv()))
644 if (
int Res = cmpAttrs(CBL->getAttributes(), CBR->getAttributes()))
646 if (
int Res = cmpOperandBundlesSchema(*CBL, *CBR))
648 if (
const CallInst *CI = dyn_cast<CallInst>(L))
649 if (
int Res =
cmpNumbers(CI->getTailCallKind(),
650 cast<CallInst>(R)->getTailCallKind()))
652 return cmpMDNode(L->getMetadata(LLVMContext::MD_range),
653 R->getMetadata(LLVMContext::MD_range));
660 for (
size_t i = 0, e = LIndices.
size(); i != e; ++i) {
661 if (
int Res =
cmpNumbers(LIndices[i], RIndices[i]))
671 for (
size_t i = 0, e = LIndices.
size(); i != e; ++i) {
672 if (
int Res =
cmpNumbers(LIndices[i], RIndices[i]))
676 if (
const FenceInst *FI = dyn_cast<FenceInst>(L)) {
678 cmpOrderings(FI->getOrdering(), cast<FenceInst>(R)->getOrdering()))
681 cast<FenceInst>(R)->getSyncScopeID());
685 cast<AtomicCmpXchgInst>(R)->isVolatile()))
688 cmpNumbers(CXI->isWeak(), cast<AtomicCmpXchgInst>(R)->isWeak()))
691 cmpOrderings(CXI->getSuccessOrdering(),
692 cast<AtomicCmpXchgInst>(R)->getSuccessOrdering()))
695 cmpOrderings(CXI->getFailureOrdering(),
696 cast<AtomicCmpXchgInst>(R)->getFailureOrdering()))
699 cast<AtomicCmpXchgInst>(R)->getSyncScopeID());
701 if (
const AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(L)) {
702 if (
int Res =
cmpNumbers(RMWI->getOperation(),
703 cast<AtomicRMWInst>(R)->getOperation()))
706 cast<AtomicRMWInst>(R)->isVolatile()))
708 if (
int Res = cmpOrderings(RMWI->getOrdering(),
709 cast<AtomicRMWInst>(R)->getOrdering()))
712 cast<AtomicRMWInst>(R)->getSyncScopeID());
716 ArrayRef<int> RMask = cast<ShuffleVectorInst>(R)->getShuffleMask();
719 for (
size_t i = 0, e = LMask.
size(); i != e; ++i) {
724 if (
const PHINode *PNL = dyn_cast<PHINode>(L)) {
725 const PHINode *PNR = cast<PHINode>(R);
729 for (
unsigned i = 0, e = PNL->getNumIncomingValues(); i != e; ++i) {
740int FunctionComparator::cmpGEPs(
const GEPOperator *GEPL,
751 unsigned OffsetBitWidth =
DL.getIndexSizeInBits(ASL);
752 APInt OffsetL(OffsetBitWidth, 0), OffsetR(OffsetBitWidth, 0);
771int FunctionComparator::cmpInlineAsm(
const InlineAsm *L,
777 if (
int Res =
cmpTypes(
L->getFunctionType(),
R->getFunctionType()))
779 if (
int Res =
cmpMem(
L->getAsmString(),
R->getAsmString()))
781 if (
int Res =
cmpMem(
L->getConstraintString(),
R->getConstraintString()))
783 if (
int Res =
cmpNumbers(
L->hasSideEffects(),
R->hasSideEffects()))
785 if (
int Res =
cmpNumbers(
L->isAlignStack(),
R->isAlignStack()))
787 if (
int Res =
cmpNumbers(
L->getDialect(),
R->getDialect()))
789 assert(
L->getFunctionType() !=
R->getFunctionType());
810 const Constant *ConstL = dyn_cast<Constant>(L);
811 const Constant *ConstR = dyn_cast<Constant>(R);
812 if (ConstL && ConstR) {
823 const InlineAsm *InlineAsmL = dyn_cast<InlineAsm>(L);
824 const InlineAsm *InlineAsmR = dyn_cast<InlineAsm>(R);
826 if (InlineAsmL && InlineAsmR)
827 return cmpInlineAsm(InlineAsmL, InlineAsmR);
833 auto LeftSN = sn_mapL.insert(std::make_pair(L, sn_mapL.size())),
834 RightSN = sn_mapR.insert(std::make_pair(R, sn_mapR.size()));
836 return cmpNumbers(LeftSN.first->second, RightSN.first->second);
846 bool needToCmpOperands =
true;
847 if (
int Res =
cmpOperations(&*InstL, &*InstR, needToCmpOperands))
849 if (needToCmpOperands) {
850 assert(InstL->getNumOperands() == InstR->getNumOperands());
852 for (
unsigned i = 0, e = InstL->getNumOperands(); i != e; ++i) {
853 Value *OpL = InstL->getOperand(i);
854 Value *OpR = InstR->getOperand(i);
864 }
while (InstL != InstLE && InstR != InstRE);
866 if (InstL != InstLE && InstR == InstRE)
868 if (InstL == InstLE && InstR != InstRE)
905 "Identically typed functions have different numbers of args!");
912 ArgLI != ArgLE; ++ArgLI, ++ArgRI) {
936 VisitedBBs.
insert(FnLBBs[0]);
937 while (!FnLBBs.
empty()) {
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Module.h This file contains the declarations for the Module class.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
SI optimize exec mask operations pre RA
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
static unsigned getBitWidth(Type *Ty, const DataLayout &DL)
Returns the bitwidth of the given scalar or pointer type.
Class for arbitrary precision integers.
an instruction to allocate memory on the stack
This class represents an incoming formal argument to a Function.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
An instruction that atomically checks whether a specified value is in a memory location,...
an instruction that atomically reads a memory location, combines it with another value,...
Attribute::AttrKind getKindAsEnum() const
Return the attribute's kind as an enum (Attribute::AttrKind).
bool isTypeAttribute() const
Return true if the attribute is a type attribute.
Type * getValueAsType() const
Return the attribute's value as a Type.
LLVM Basic Block Representation.
iterator begin()
Instruction iterator methods.
InstListType::const_iterator const_iterator
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.
Function * getFunction() const
BasicBlock * getBasicBlock() const
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
OperandBundleUse getOperandBundleAt(unsigned Index) const
Return the operand bundle at a specific index.
unsigned getNumOperandBundles() const
Return the number of operand bundles associated with this User.
This class represents a function call, abstracting a target machine's calling convention.
This class is the base class for the comparison instructions.
ConstantArray - Constant Array Declarations.
A constant value that is initialized with an expression using other constant values.
Constant Vector Declarations.
This is an important base class in LLVM.
A parsed version of the target data layout string in and methods for querying it.
An instruction for ordering other memory operations.
int cmpBasicBlocks(const BasicBlock *BBL, const BasicBlock *BBR) const
Test whether two basic blocks have equivalent behaviour.
int compareSignature() const
Compares the signature and other general attributes of the two functions.
int cmpMem(StringRef L, StringRef R) const
int compare()
Test whether the two functions have equivalent behaviour.
int cmpAPFloats(const APFloat &L, const APFloat &R) const
int cmpTypes(Type *TyL, Type *TyR) const
cmpType - compares two types, defines total ordering among the types set.
int cmpOperations(const Instruction *L, const Instruction *R, bool &needToCmpOperands) const
Compare two Instructions for equivalence, similar to Instruction::isSameOperationAs.
int cmpNumbers(uint64_t L, uint64_t R) const
int cmpAligns(Align L, Align R) const
void beginCompare()
Start the comparison.
int cmpValues(const Value *L, const Value *R) const
Assign or look up previously assigned numbers for the two values, and return whether the numbers are ...
int cmpGlobalValues(GlobalValue *L, GlobalValue *R) const
Compares two global values by number.
int cmpConstants(const Constant *L, const Constant *R) const
Constants comparison.
int cmpAPInts(const APInt &L, const APInt &R) const
Class to represent function types.
unsigned getNumParams() const
Return the number of fixed parameters this function type requires.
Type * getParamType(unsigned i) const
Parameter type accessors.
Type * getReturnType() const
const BasicBlock & getEntryBlock() const
FunctionType * getFunctionType() const
Returns the FunctionType for me.
bool hasGC() const
hasGC/getGC/setGC/clearGC - The name of the garbage collection algorithm to use during code generatio...
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
AttributeList getAttributes() const
Return the attribute list for this Function.
const std::string & getGC() const
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
Type * getSourceElementType() const
bool accumulateConstantOffset(const DataLayout &DL, APInt &Offset, function_ref< bool(Value &, APInt &)> ExternalAnalysis=nullptr) const
Accumulate the constant address offset of this GEP if possible.
unsigned getPointerAddressSpace() const
Method to return the address space of the pointer operand.
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
Value * getPointerOperand()
uint64_t getNumber(GlobalValue *Global)
StringRef getSection() const
Get the custom section of this global if it has one.
bool hasSection() const
Check if this global has a custom object file section.
Module * getParent()
Get the module that this global value is contained inside of...
This instruction inserts a struct field of array element value into an aggregate value.
unsigned getNumSuccessors() const LLVM_READONLY
Return the number of successors that this instruction has.
BasicBlock * getSuccessor(unsigned Idx) const LLVM_READONLY
Return the specified successor. This instruction must be a terminator.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
An instruction for reading from memory.
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
BasicBlock * getIncomingBlock(unsigned i) const
Return incoming basic block number i.
Class to represent pointers.
unsigned getAddressSpace() const
Return the address space of the Pointer type.
This instruction constructs a fixed permutation of two input vectors.
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.
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.
StringRef - Represent a constant reference to a string, i.e.
Class to represent struct types.
unsigned getNumElements() const
Random access to the elements.
Type * getElementType(unsigned N) const
The instances of the Type class are immutable: once they are created, they are never changed.
@ VoidTyID
type with no size
@ ScalableVectorTyID
Scalable SIMD vector type.
@ FloatTyID
32-bit floating point type
@ IntegerTyID
Arbitrary bit width integers.
@ FixedVectorTyID
Fixed width SIMD vector type.
@ DoubleTyID
64-bit floating point type
@ X86_FP80TyID
80-bit floating point type (X87)
@ PPC_FP128TyID
128-bit floating point type (two 64-bits, PowerPC)
@ FP128TyID
128-bit floating point type (112-bit significand)
bool isFirstClassType() const
Return true if the type is "first class", meaning it is a valid type for a Value.
TypeID getTypeID() const
Return the type id for the 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.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
AtomicOrdering
Atomic ordering for LLVM's memory model.
static ExponentType semanticsMinExponent(const fltSemantics &)
static unsigned int semanticsSizeInBits(const fltSemantics &)
static ExponentType semanticsMaxExponent(const fltSemantics &)
static unsigned int semanticsPrecision(const fltSemantics &)
This struct is a compact representation of a valid (non-zero power of two) alignment.