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,
168 auto *MDStringL = dyn_cast<MDString>(L);
169 auto *MDStringR = dyn_cast<MDString>(R);
170 if (MDStringL && MDStringR) {
171 if (MDStringL == MDStringR)
173 return MDStringL->getString().compare(MDStringR->getString());
180 auto *CL = dyn_cast<ConstantAsMetadata>(L);
181 auto *CR = dyn_cast<ConstantAsMetadata>(R);
191int FunctionComparator::cmpMDNode(
const MDNode *L,
const MDNode *R)
const {
204 if (
int Res =
cmpNumbers(
L->getNumOperands(),
R->getNumOperands()))
206 for (
size_t I = 0;
I <
L->getNumOperands(); ++
I)
207 if (
int Res = cmpMetadata(
L->getOperand(
I),
R->getOperand(
I)))
212int FunctionComparator::cmpInstMetadata(
Instruction const *L,
218 L->getAllMetadataOtherThanDebugLoc(MDL);
219 R->getAllMetadataOtherThanDebugLoc(MDR);
224 for (
size_t I = 0,
N = MDL.
size();
I <
N; ++
I) {
225 auto const [KeyL,
ML] = MDL[
I];
226 auto const [KeyR, MR] = MDR[
I];
229 if (
int Res = cmpMDNode(
ML, MR))
235int FunctionComparator::cmpOperandBundlesSchema(
const CallBase &LCS,
247 if (
int Res = OBL.getTagName().compare(OBR.getTagName()))
250 if (
int Res =
cmpNumbers(OBL.Inputs.size(), OBR.Inputs.size()))
264 Type *TyL = L->getType();
265 Type *TyR = R->getType();
288 unsigned TyLWidth = 0;
289 unsigned TyRWidth = 0;
291 if (
auto *VecTyL = dyn_cast<VectorType>(TyL))
292 TyLWidth = VecTyL->getPrimitiveSizeInBits().getFixedValue();
293 if (
auto *VecTyR = dyn_cast<VectorType>(TyR))
294 TyRWidth = VecTyR->getPrimitiveSizeInBits().getFixedValue();
296 if (TyLWidth != TyRWidth)
306 if (
int Res =
cmpNumbers(AddrSpaceL, AddrSpaceR))
322 if (L->isNullValue() && R->isNullValue())
324 if (L->isNullValue() && !R->isNullValue())
326 if (!L->isNullValue() && R->isNullValue())
329 auto GlobalValueL =
const_cast<GlobalValue *
>(dyn_cast<GlobalValue>(L));
330 auto GlobalValueR =
const_cast<GlobalValue *
>(dyn_cast<GlobalValue>(R));
331 if (GlobalValueL && GlobalValueR) {
335 if (
int Res =
cmpNumbers(L->getValueID(), R->getValueID()))
338 if (
const auto *SeqL = dyn_cast<ConstantDataSequential>(L)) {
339 const auto *SeqR = cast<ConstantDataSequential>(R);
345 return cmpMem(SeqL->getRawDataValues(), SeqR->getRawDataValues());
348 switch (L->getValueID()) {
349 case Value::UndefValueVal:
350 case Value::PoisonValueVal:
351 case Value::ConstantTokenNoneVal:
353 case Value::ConstantIntVal: {
354 const APInt &LInt = cast<ConstantInt>(L)->getValue();
355 const APInt &RInt = cast<ConstantInt>(R)->getValue();
358 case Value::ConstantFPVal: {
359 const APFloat &LAPF = cast<ConstantFP>(L)->getValueAPF();
360 const APFloat &RAPF = cast<ConstantFP>(R)->getValueAPF();
363 case Value::ConstantArrayVal: {
366 uint64_t NumElementsL = cast<ArrayType>(TyL)->getNumElements();
367 uint64_t NumElementsR = cast<ArrayType>(TyR)->getNumElements();
368 if (
int Res =
cmpNumbers(NumElementsL, NumElementsR))
370 for (
uint64_t i = 0; i < NumElementsL; ++i) {
372 cast<Constant>(
RA->getOperand(i))))
377 case Value::ConstantStructVal: {
380 unsigned NumElementsL = cast<StructType>(TyL)->getNumElements();
381 unsigned NumElementsR = cast<StructType>(TyR)->getNumElements();
382 if (
int Res =
cmpNumbers(NumElementsL, NumElementsR))
384 for (
unsigned i = 0; i != NumElementsL; ++i) {
385 if (
int Res =
cmpConstants(cast<Constant>(LS->getOperand(i)),
391 case Value::ConstantVectorVal: {
394 unsigned NumElementsL = cast<FixedVectorType>(TyL)->getNumElements();
395 unsigned NumElementsR = cast<FixedVectorType>(TyR)->getNumElements();
396 if (
int Res =
cmpNumbers(NumElementsL, NumElementsR))
398 for (
uint64_t i = 0; i < NumElementsL; ++i) {
405 case Value::ConstantExprVal: {
410 unsigned NumOperandsL = LE->getNumOperands();
412 if (
int Res =
cmpNumbers(NumOperandsL, NumOperandsR))
414 for (
unsigned i = 0; i < NumOperandsL; ++i) {
415 if (
int Res =
cmpConstants(cast<Constant>(LE->getOperand(i)),
422 if (
auto *GEPL = dyn_cast<GEPOperator>(LE)) {
423 auto *GEPR = cast<GEPOperator>(RE);
424 if (
int Res =
cmpTypes(GEPL->getSourceElementType(),
425 GEPR->getSourceElementType()))
427 if (
int Res =
cmpNumbers(GEPL->isInBounds(), GEPR->isInBounds()))
430 std::optional<ConstantRange> InRangeL = GEPL->getInRange();
431 std::optional<ConstantRange> InRangeR = GEPR->getInRange();
435 if (
int Res =
cmpAPInts(InRangeL->getLower(), InRangeR->getLower()))
437 if (
int Res =
cmpAPInts(InRangeL->getUpper(), InRangeR->getUpper()))
439 }
else if (InRangeR) {
443 if (
auto *
OBOL = dyn_cast<OverflowingBinaryOperator>(LE)) {
444 auto *OBOR = cast<OverflowingBinaryOperator>(RE);
454 case Value::BlockAddressVal: {
488 case Value::DSOLocalEquivalentVal: {
493 const auto *LEquiv = cast<DSOLocalEquivalent>(L);
494 const auto *REquiv = cast<DSOLocalEquivalent>(R);
495 return cmpGlobalValues(LEquiv->getGlobalValue(), REquiv->getGlobalValue());
498 LLVM_DEBUG(
dbgs() <<
"Looking at valueID " << L->getValueID() <<
"\n");
519 TyL =
DL.getIntPtrType(TyL);
521 TyR =
DL.getIntPtrType(TyR);
548 assert(PTyL && PTyR &&
"Both types must be pointers here.");
579 for (
unsigned i = 0, e = FTyL->
getNumParams(); i != e; ++i) {
587 auto *STyL = cast<ArrayType>(TyL);
588 auto *STyR = cast<ArrayType>(TyR);
589 if (STyL->getNumElements() != STyR->getNumElements())
590 return cmpNumbers(STyL->getNumElements(), STyR->getNumElements());
591 return cmpTypes(STyL->getElementType(), STyR->getElementType());
595 auto *STyL = cast<VectorType>(TyL);
596 auto *STyR = cast<VectorType>(TyR);
597 if (STyL->getElementCount().isScalable() !=
598 STyR->getElementCount().isScalable())
599 return cmpNumbers(STyL->getElementCount().isScalable(),
600 STyR->getElementCount().isScalable());
601 if (STyL->getElementCount() != STyR->getElementCount())
602 return cmpNumbers(STyL->getElementCount().getKnownMinValue(),
603 STyR->getElementCount().getKnownMinValue());
604 return cmpTypes(STyL->getElementType(), STyR->getElementType());
615 bool &needToCmpOperands)
const {
616 needToCmpOperands =
true;
624 if (
int Res =
cmpNumbers(L->getOpcode(), R->getOpcode()))
628 needToCmpOperands =
false;
633 return cmpGEPs(GEPL, GEPR);
636 if (
int Res =
cmpNumbers(L->getNumOperands(), R->getNumOperands()))
639 if (
int Res =
cmpTypes(L->getType(), R->getType()))
642 if (
int Res =
cmpNumbers(L->getRawSubclassOptionalData(),
643 R->getRawSubclassOptionalData()))
648 for (
unsigned i = 0, e = L->getNumOperands(); i != e; ++i) {
650 cmpTypes(L->getOperand(i)->getType(), R->getOperand(i)->getType()))
655 if (
const AllocaInst *AI = dyn_cast<AllocaInst>(L)) {
656 if (
int Res =
cmpTypes(AI->getAllocatedType(),
657 cast<AllocaInst>(R)->getAllocatedType()))
659 return cmpAligns(AI->getAlign(), cast<AllocaInst>(R)->getAlign());
661 if (
const LoadInst *LI = dyn_cast<LoadInst>(L)) {
662 if (
int Res =
cmpNumbers(LI->isVolatile(), cast<LoadInst>(R)->isVolatile()))
664 if (
int Res =
cmpAligns(LI->getAlign(), cast<LoadInst>(R)->getAlign()))
667 cmpOrderings(LI->getOrdering(), cast<LoadInst>(R)->getOrdering()))
669 if (
int Res =
cmpNumbers(LI->getSyncScopeID(),
670 cast<LoadInst>(R)->getSyncScopeID()))
672 return cmpInstMetadata(L, R);
674 if (
const StoreInst *SI = dyn_cast<StoreInst>(L)) {
676 cmpNumbers(SI->isVolatile(), cast<StoreInst>(R)->isVolatile()))
678 if (
int Res =
cmpAligns(SI->getAlign(), cast<StoreInst>(R)->getAlign()))
681 cmpOrderings(SI->getOrdering(), cast<StoreInst>(R)->getOrdering()))
684 cast<StoreInst>(R)->getSyncScopeID());
686 if (
const CmpInst *CI = dyn_cast<CmpInst>(L))
687 return cmpNumbers(CI->getPredicate(), cast<CmpInst>(R)->getPredicate());
688 if (
auto *CBL = dyn_cast<CallBase>(L)) {
689 auto *CBR = cast<CallBase>(R);
690 if (
int Res =
cmpNumbers(CBL->getCallingConv(), CBR->getCallingConv()))
692 if (
int Res = cmpAttrs(CBL->getAttributes(), CBR->getAttributes()))
694 if (
int Res = cmpOperandBundlesSchema(*CBL, *CBR))
696 if (
const CallInst *CI = dyn_cast<CallInst>(L))
697 if (
int Res =
cmpNumbers(CI->getTailCallKind(),
698 cast<CallInst>(R)->getTailCallKind()))
700 return cmpMDNode(L->getMetadata(LLVMContext::MD_range),
701 R->getMetadata(LLVMContext::MD_range));
708 for (
size_t i = 0, e = LIndices.
size(); i != e; ++i) {
709 if (
int Res =
cmpNumbers(LIndices[i], RIndices[i]))
719 for (
size_t i = 0, e = LIndices.
size(); i != e; ++i) {
720 if (
int Res =
cmpNumbers(LIndices[i], RIndices[i]))
724 if (
const FenceInst *FI = dyn_cast<FenceInst>(L)) {
726 cmpOrderings(FI->getOrdering(), cast<FenceInst>(R)->getOrdering()))
729 cast<FenceInst>(R)->getSyncScopeID());
733 cast<AtomicCmpXchgInst>(R)->isVolatile()))
736 cmpNumbers(CXI->isWeak(), cast<AtomicCmpXchgInst>(R)->isWeak()))
739 cmpOrderings(CXI->getSuccessOrdering(),
740 cast<AtomicCmpXchgInst>(R)->getSuccessOrdering()))
743 cmpOrderings(CXI->getFailureOrdering(),
744 cast<AtomicCmpXchgInst>(R)->getFailureOrdering()))
747 cast<AtomicCmpXchgInst>(R)->getSyncScopeID());
749 if (
const AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(L)) {
750 if (
int Res =
cmpNumbers(RMWI->getOperation(),
751 cast<AtomicRMWInst>(R)->getOperation()))
754 cast<AtomicRMWInst>(R)->isVolatile()))
756 if (
int Res = cmpOrderings(RMWI->getOrdering(),
757 cast<AtomicRMWInst>(R)->getOrdering()))
760 cast<AtomicRMWInst>(R)->getSyncScopeID());
764 ArrayRef<int> RMask = cast<ShuffleVectorInst>(R)->getShuffleMask();
767 for (
size_t i = 0, e = LMask.
size(); i != e; ++i) {
772 if (
const PHINode *PNL = dyn_cast<PHINode>(L)) {
773 const PHINode *PNR = cast<PHINode>(R);
777 for (
unsigned i = 0, e = PNL->getNumIncomingValues(); i != e; ++i) {
788int FunctionComparator::cmpGEPs(
const GEPOperator *GEPL,
799 unsigned OffsetBitWidth =
DL.getIndexSizeInBits(ASL);
800 APInt OffsetL(OffsetBitWidth, 0), OffsetR(OffsetBitWidth, 0);
819int FunctionComparator::cmpInlineAsm(
const InlineAsm *L,
825 if (
int Res =
cmpTypes(
L->getFunctionType(),
R->getFunctionType()))
827 if (
int Res =
cmpMem(
L->getAsmString(),
R->getAsmString()))
829 if (
int Res =
cmpMem(
L->getConstraintString(),
R->getConstraintString()))
831 if (
int Res =
cmpNumbers(
L->hasSideEffects(),
R->hasSideEffects()))
833 if (
int Res =
cmpNumbers(
L->isAlignStack(),
R->isAlignStack()))
835 if (
int Res =
cmpNumbers(
L->getDialect(),
R->getDialect()))
837 assert(
L->getFunctionType() !=
R->getFunctionType());
858 const Constant *ConstL = dyn_cast<Constant>(L);
859 const Constant *ConstR = dyn_cast<Constant>(R);
860 if (ConstL && ConstR) {
873 if (MetadataValueL && MetadataValueR) {
874 if (MetadataValueL == MetadataValueR)
886 const InlineAsm *InlineAsmL = dyn_cast<InlineAsm>(L);
887 const InlineAsm *InlineAsmR = dyn_cast<InlineAsm>(R);
889 if (InlineAsmL && InlineAsmR)
890 return cmpInlineAsm(InlineAsmL, InlineAsmR);
896 auto LeftSN = sn_mapL.insert(std::make_pair(L, sn_mapL.size())),
897 RightSN = sn_mapR.insert(std::make_pair(R, sn_mapR.size()));
899 return cmpNumbers(LeftSN.first->second, RightSN.first->second);
909 bool needToCmpOperands =
true;
910 if (
int Res =
cmpOperations(&*InstL, &*InstR, needToCmpOperands))
912 if (needToCmpOperands) {
913 assert(InstL->getNumOperands() == InstR->getNumOperands());
915 for (
unsigned i = 0, e = InstL->getNumOperands(); i != e; ++i) {
916 Value *OpL = InstL->getOperand(i);
917 Value *OpR = InstR->getOperand(i);
927 }
while (InstL != InstLE && InstR != InstRE);
929 if (InstL != InstLE && InstR == InstRE)
931 if (InstL == InstLE && InstR != InstRE)
968 "Identically typed functions have different numbers of args!");
975 ArgLI != ArgLE; ++ArgLI, ++ArgRI) {
999 VisitedBBs.
insert(FnLBBs[0]);
1000 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...
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.
unsigned getPredicate() const
Return the ICMP or FCMP predicate value.
unsigned getOpcode() const
Return the opcode at the root of this constant expression.
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.