50#define DEBUG_TYPE "functioncomparator"
61 if (L.value() < R.value())
63 if (L.value() > R.value())
77 if (
int Res =
cmpNumbers(L.getBitWidth(), R.getBitWidth()))
88 if (
int Res =
cmpAPInts(L.getLower(), R.getLower()))
90 return cmpAPInts(L.getUpper(), R.getUpper());
96 const fltSemantics &SL = L.getSemantics(), &SR = R.getSemantics();
109 return cmpAPInts(L.bitcastToAPInt(), R.bitcastToAPInt());
119 return std::clamp(L.compare(R), -1, 1);
124 if (
int Res =
cmpNumbers(L.getNumAttrSets(), R.getNumAttrSets()))
127 for (
unsigned i : L.indexes()) {
132 for (; LI != LE && RI != RE; ++LI, ++RI) {
140 Type *TyR =
RA.getValueAsType();
153 RA.isConstantRangeAttribute()) {
161 RA.isConstantRangeListAttribute()) {
170 for (
const auto &[L, R] :
zip(CRL, CRR))
188int FunctionComparator::cmpMetadata(
const Metadata *L,
196 auto *MDStringL = dyn_cast<MDString>(L);
197 auto *MDStringR = dyn_cast<MDString>(R);
198 if (MDStringL && MDStringR) {
199 if (MDStringL == MDStringR)
201 return MDStringL->getString().compare(MDStringR->getString());
208 auto *CL = dyn_cast<ConstantAsMetadata>(L);
209 auto *CR = dyn_cast<ConstantAsMetadata>(R);
219int FunctionComparator::cmpMDNode(
const MDNode *L,
const MDNode *R)
const {
232 if (
int Res =
cmpNumbers(
L->getNumOperands(),
R->getNumOperands()))
234 for (
size_t I = 0;
I <
L->getNumOperands(); ++
I)
235 if (
int Res = cmpMetadata(
L->getOperand(
I),
R->getOperand(
I)))
240int FunctionComparator::cmpInstMetadata(
Instruction const *L,
246 L->getAllMetadataOtherThanDebugLoc(MDL);
247 R->getAllMetadataOtherThanDebugLoc(MDR);
252 for (
size_t I = 0,
N = MDL.
size();
I <
N; ++
I) {
253 auto const [KeyL,
ML] = MDL[
I];
254 auto const [KeyR, MR] = MDR[
I];
257 if (
int Res = cmpMDNode(
ML, MR))
263int FunctionComparator::cmpOperandBundlesSchema(
const CallBase &LCS,
275 if (
int Res = OBL.getTagName().compare(OBR.getTagName()))
278 if (
int Res =
cmpNumbers(OBL.Inputs.size(), OBR.Inputs.size()))
292 Type *TyL = L->getType();
293 Type *TyR = R->getType();
316 unsigned TyLWidth = 0;
317 unsigned TyRWidth = 0;
319 if (
auto *VecTyL = dyn_cast<VectorType>(TyL))
320 TyLWidth = VecTyL->getPrimitiveSizeInBits().getFixedValue();
321 if (
auto *VecTyR = dyn_cast<VectorType>(TyR))
322 TyRWidth = VecTyR->getPrimitiveSizeInBits().getFixedValue();
324 if (TyLWidth != TyRWidth)
334 if (
int Res =
cmpNumbers(AddrSpaceL, AddrSpaceR))
350 if (L->isNullValue() && R->isNullValue())
352 if (L->isNullValue() && !R->isNullValue())
354 if (!L->isNullValue() && R->isNullValue())
357 auto GlobalValueL =
const_cast<GlobalValue *
>(dyn_cast<GlobalValue>(L));
358 auto GlobalValueR =
const_cast<GlobalValue *
>(dyn_cast<GlobalValue>(R));
359 if (GlobalValueL && GlobalValueR) {
363 if (
int Res =
cmpNumbers(L->getValueID(), R->getValueID()))
366 if (
const auto *SeqL = dyn_cast<ConstantDataSequential>(L)) {
367 const auto *SeqR = cast<ConstantDataSequential>(R);
373 return cmpMem(SeqL->getRawDataValues(), SeqR->getRawDataValues());
376 switch (L->getValueID()) {
377 case Value::UndefValueVal:
378 case Value::PoisonValueVal:
379 case Value::ConstantTokenNoneVal:
381 case Value::ConstantIntVal: {
382 const APInt &LInt = cast<ConstantInt>(L)->getValue();
383 const APInt &RInt = cast<ConstantInt>(R)->getValue();
386 case Value::ConstantFPVal: {
387 const APFloat &LAPF = cast<ConstantFP>(L)->getValueAPF();
388 const APFloat &RAPF = cast<ConstantFP>(R)->getValueAPF();
391 case Value::ConstantArrayVal: {
394 uint64_t NumElementsL = cast<ArrayType>(TyL)->getNumElements();
395 uint64_t NumElementsR = cast<ArrayType>(TyR)->getNumElements();
396 if (
int Res =
cmpNumbers(NumElementsL, NumElementsR))
398 for (
uint64_t i = 0; i < NumElementsL; ++i) {
400 cast<Constant>(
RA->getOperand(i))))
405 case Value::ConstantStructVal: {
408 unsigned NumElementsL = cast<StructType>(TyL)->getNumElements();
409 unsigned NumElementsR = cast<StructType>(TyR)->getNumElements();
410 if (
int Res =
cmpNumbers(NumElementsL, NumElementsR))
412 for (
unsigned i = 0; i != NumElementsL; ++i) {
413 if (
int Res =
cmpConstants(cast<Constant>(LS->getOperand(i)),
419 case Value::ConstantVectorVal: {
422 unsigned NumElementsL = cast<FixedVectorType>(TyL)->getNumElements();
423 unsigned NumElementsR = cast<FixedVectorType>(TyR)->getNumElements();
424 if (
int Res =
cmpNumbers(NumElementsL, NumElementsR))
426 for (
uint64_t i = 0; i < NumElementsL; ++i) {
433 case Value::ConstantExprVal: {
438 unsigned NumOperandsL = LE->getNumOperands();
440 if (
int Res =
cmpNumbers(NumOperandsL, NumOperandsR))
442 for (
unsigned i = 0; i < NumOperandsL; ++i) {
443 if (
int Res =
cmpConstants(cast<Constant>(LE->getOperand(i)),
447 if (
auto *GEPL = dyn_cast<GEPOperator>(LE)) {
448 auto *GEPR = cast<GEPOperator>(RE);
449 if (
int Res =
cmpTypes(GEPL->getSourceElementType(),
450 GEPR->getSourceElementType()))
452 if (
int Res =
cmpNumbers(GEPL->getNoWrapFlags().getRaw(),
453 GEPR->getNoWrapFlags().getRaw()))
456 std::optional<ConstantRange> InRangeL = GEPL->getInRange();
457 std::optional<ConstantRange> InRangeR = GEPR->getInRange();
463 }
else if (InRangeR) {
467 if (
auto *
OBOL = dyn_cast<OverflowingBinaryOperator>(LE)) {
468 auto *OBOR = cast<OverflowingBinaryOperator>(RE);
478 case Value::BlockAddressVal: {
512 case Value::DSOLocalEquivalentVal: {
517 const auto *LEquiv = cast<DSOLocalEquivalent>(L);
518 const auto *REquiv = cast<DSOLocalEquivalent>(R);
519 return cmpGlobalValues(LEquiv->getGlobalValue(), REquiv->getGlobalValue());
522 LLVM_DEBUG(
dbgs() <<
"Looking at valueID " << L->getValueID() <<
"\n");
543 TyL =
DL.getIntPtrType(TyL);
545 TyR =
DL.getIntPtrType(TyR);
572 assert(PTyL && PTyR &&
"Both types must be pointers here.");
603 for (
unsigned i = 0, e = FTyL->
getNumParams(); i != e; ++i) {
611 auto *STyL = cast<ArrayType>(TyL);
612 auto *STyR = cast<ArrayType>(TyR);
613 if (STyL->getNumElements() != STyR->getNumElements())
614 return cmpNumbers(STyL->getNumElements(), STyR->getNumElements());
615 return cmpTypes(STyL->getElementType(), STyR->getElementType());
619 auto *STyL = cast<VectorType>(TyL);
620 auto *STyR = cast<VectorType>(TyR);
621 if (STyL->getElementCount().isScalable() !=
622 STyR->getElementCount().isScalable())
623 return cmpNumbers(STyL->getElementCount().isScalable(),
624 STyR->getElementCount().isScalable());
625 if (STyL->getElementCount() != STyR->getElementCount())
626 return cmpNumbers(STyL->getElementCount().getKnownMinValue(),
627 STyR->getElementCount().getKnownMinValue());
628 return cmpTypes(STyL->getElementType(), STyR->getElementType());
639 bool &needToCmpOperands)
const {
640 needToCmpOperands =
true;
648 if (
int Res =
cmpNumbers(L->getOpcode(), R->getOpcode()))
652 needToCmpOperands =
false;
657 return cmpGEPs(GEPL, GEPR);
660 if (
int Res =
cmpNumbers(L->getNumOperands(), R->getNumOperands()))
663 if (
int Res =
cmpTypes(L->getType(), R->getType()))
666 if (
int Res =
cmpNumbers(L->getRawSubclassOptionalData(),
667 R->getRawSubclassOptionalData()))
672 for (
unsigned i = 0, e = L->getNumOperands(); i != e; ++i) {
674 cmpTypes(L->getOperand(i)->getType(), R->getOperand(i)->getType()))
679 if (
const AllocaInst *AI = dyn_cast<AllocaInst>(L)) {
680 if (
int Res =
cmpTypes(AI->getAllocatedType(),
681 cast<AllocaInst>(R)->getAllocatedType()))
683 return cmpAligns(AI->getAlign(), cast<AllocaInst>(R)->getAlign());
685 if (
const LoadInst *LI = dyn_cast<LoadInst>(L)) {
686 if (
int Res =
cmpNumbers(LI->isVolatile(), cast<LoadInst>(R)->isVolatile()))
688 if (
int Res =
cmpAligns(LI->getAlign(), cast<LoadInst>(R)->getAlign()))
691 cmpOrderings(LI->getOrdering(), cast<LoadInst>(R)->getOrdering()))
693 if (
int Res =
cmpNumbers(LI->getSyncScopeID(),
694 cast<LoadInst>(R)->getSyncScopeID()))
696 return cmpInstMetadata(L, R);
698 if (
const StoreInst *SI = dyn_cast<StoreInst>(L)) {
700 cmpNumbers(SI->isVolatile(), cast<StoreInst>(R)->isVolatile()))
702 if (
int Res =
cmpAligns(SI->getAlign(), cast<StoreInst>(R)->getAlign()))
705 cmpOrderings(SI->getOrdering(), cast<StoreInst>(R)->getOrdering()))
708 cast<StoreInst>(R)->getSyncScopeID());
710 if (
const CmpInst *CI = dyn_cast<CmpInst>(L))
711 return cmpNumbers(CI->getPredicate(), cast<CmpInst>(R)->getPredicate());
712 if (
auto *CBL = dyn_cast<CallBase>(L)) {
713 auto *CBR = cast<CallBase>(R);
714 if (
int Res =
cmpNumbers(CBL->getCallingConv(), CBR->getCallingConv()))
716 if (
int Res = cmpAttrs(CBL->getAttributes(), CBR->getAttributes()))
718 if (
int Res = cmpOperandBundlesSchema(*CBL, *CBR))
720 if (
const CallInst *CI = dyn_cast<CallInst>(L))
721 if (
int Res =
cmpNumbers(CI->getTailCallKind(),
722 cast<CallInst>(R)->getTailCallKind()))
724 return cmpMDNode(L->getMetadata(LLVMContext::MD_range),
725 R->getMetadata(LLVMContext::MD_range));
732 for (
size_t i = 0, e = LIndices.
size(); i != e; ++i) {
733 if (
int Res =
cmpNumbers(LIndices[i], RIndices[i]))
743 for (
size_t i = 0, e = LIndices.
size(); i != e; ++i) {
744 if (
int Res =
cmpNumbers(LIndices[i], RIndices[i]))
748 if (
const FenceInst *FI = dyn_cast<FenceInst>(L)) {
750 cmpOrderings(FI->getOrdering(), cast<FenceInst>(R)->getOrdering()))
753 cast<FenceInst>(R)->getSyncScopeID());
757 cast<AtomicCmpXchgInst>(R)->isVolatile()))
760 cmpNumbers(CXI->isWeak(), cast<AtomicCmpXchgInst>(R)->isWeak()))
763 cmpOrderings(CXI->getSuccessOrdering(),
764 cast<AtomicCmpXchgInst>(R)->getSuccessOrdering()))
767 cmpOrderings(CXI->getFailureOrdering(),
768 cast<AtomicCmpXchgInst>(R)->getFailureOrdering()))
771 cast<AtomicCmpXchgInst>(R)->getSyncScopeID());
773 if (
const AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(L)) {
774 if (
int Res =
cmpNumbers(RMWI->getOperation(),
775 cast<AtomicRMWInst>(R)->getOperation()))
778 cast<AtomicRMWInst>(R)->isVolatile()))
780 if (
int Res = cmpOrderings(RMWI->getOrdering(),
781 cast<AtomicRMWInst>(R)->getOrdering()))
784 cast<AtomicRMWInst>(R)->getSyncScopeID());
788 ArrayRef<int> RMask = cast<ShuffleVectorInst>(R)->getShuffleMask();
791 for (
size_t i = 0, e = LMask.
size(); i != e; ++i) {
796 if (
const PHINode *PNL = dyn_cast<PHINode>(L)) {
797 const PHINode *PNR = cast<PHINode>(R);
801 for (
unsigned i = 0, e = PNL->getNumIncomingValues(); i != e; ++i) {
812int FunctionComparator::cmpGEPs(
const GEPOperator *GEPL,
823 unsigned OffsetBitWidth =
DL.getIndexSizeInBits(ASL);
824 APInt OffsetL(OffsetBitWidth, 0), OffsetR(OffsetBitWidth, 0);
843int FunctionComparator::cmpInlineAsm(
const InlineAsm *L,
849 if (
int Res =
cmpTypes(
L->getFunctionType(),
R->getFunctionType()))
851 if (
int Res =
cmpMem(
L->getAsmString(),
R->getAsmString()))
853 if (
int Res =
cmpMem(
L->getConstraintString(),
R->getConstraintString()))
855 if (
int Res =
cmpNumbers(
L->hasSideEffects(),
R->hasSideEffects()))
857 if (
int Res =
cmpNumbers(
L->isAlignStack(),
R->isAlignStack()))
859 if (
int Res =
cmpNumbers(
L->getDialect(),
R->getDialect()))
861 assert(
L->getFunctionType() !=
R->getFunctionType());
882 const Constant *ConstL = dyn_cast<Constant>(L);
883 const Constant *ConstR = dyn_cast<Constant>(R);
884 if (ConstL && ConstR) {
897 if (MetadataValueL && MetadataValueR) {
898 if (MetadataValueL == MetadataValueR)
910 const InlineAsm *InlineAsmL = dyn_cast<InlineAsm>(L);
911 const InlineAsm *InlineAsmR = dyn_cast<InlineAsm>(R);
913 if (InlineAsmL && InlineAsmR)
914 return cmpInlineAsm(InlineAsmL, InlineAsmR);
920 auto LeftSN = sn_mapL.insert(std::make_pair(L, sn_mapL.size())),
921 RightSN = sn_mapR.insert(std::make_pair(R, sn_mapR.size()));
923 return cmpNumbers(LeftSN.first->second, RightSN.first->second);
933 bool needToCmpOperands =
true;
934 if (
int Res =
cmpOperations(&*InstL, &*InstR, needToCmpOperands))
936 if (needToCmpOperands) {
937 assert(InstL->getNumOperands() == InstR->getNumOperands());
939 for (
unsigned i = 0, e = InstL->getNumOperands(); i != e; ++i) {
940 Value *OpL = InstL->getOperand(i);
941 Value *OpR = InstR->getOperand(i);
951 }
while (InstL != InstLE && InstR != InstRE);
953 if (InstL != InstLE && InstR == InstRE)
955 if (InstL == InstLE && InstR != InstRE)
992 "Identically typed functions have different numbers of args!");
999 ArgLI != ArgLE; ++ArgLI, ++ArgRI) {
1023 VisitedBBs.
insert(FnLBBs[0]);
1024 while (!FnLBBs.
empty()) {
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...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
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,...
const ConstantRange & getRange() const
Returns the value of the range attribute.
bool isConstantRangeAttribute() const
Return true if the attribute is a ConstantRange attribute.
Attribute::AttrKind getKindAsEnum() const
Return the attribute's kind as an enum (Attribute::AttrKind).
ArrayRef< ConstantRange > getValueAsConstantRangeList() const
Return the attribute's value as a ConstantRange array.
bool isTypeAttribute() const
Return true if the attribute is a type attribute.
bool isConstantRangeListAttribute() const
Return true if the attribute is a ConstantRangeList 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 getOpcode() const
Return the opcode at the root of this constant expression.
This class represents a range of 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 cmpConstantRanges(const ConstantRange &L, const ConstantRange &R) const
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.
const DataLayout & getDataLayout() const
Get the data layout of the module this function belongs to.
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.
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.
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.
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&...args)
zip iterator for two or more iteratable types.
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.