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();
147 RA.isConstantRangeAttribute()) {
172int FunctionComparator::cmpMetadata(
const Metadata *L,
180 auto *MDStringL = dyn_cast<MDString>(L);
181 auto *MDStringR = dyn_cast<MDString>(R);
182 if (MDStringL && MDStringR) {
183 if (MDStringL == MDStringR)
185 return MDStringL->getString().compare(MDStringR->getString());
192 auto *CL = dyn_cast<ConstantAsMetadata>(L);
193 auto *CR = dyn_cast<ConstantAsMetadata>(R);
203int FunctionComparator::cmpMDNode(
const MDNode *L,
const MDNode *R)
const {
216 if (
int Res =
cmpNumbers(
L->getNumOperands(),
R->getNumOperands()))
218 for (
size_t I = 0;
I <
L->getNumOperands(); ++
I)
219 if (
int Res = cmpMetadata(
L->getOperand(
I),
R->getOperand(
I)))
224int FunctionComparator::cmpInstMetadata(
Instruction const *L,
230 L->getAllMetadataOtherThanDebugLoc(MDL);
231 R->getAllMetadataOtherThanDebugLoc(MDR);
236 for (
size_t I = 0,
N = MDL.
size();
I <
N; ++
I) {
237 auto const [KeyL,
ML] = MDL[
I];
238 auto const [KeyR, MR] = MDR[
I];
241 if (
int Res = cmpMDNode(
ML, MR))
247int FunctionComparator::cmpOperandBundlesSchema(
const CallBase &LCS,
259 if (
int Res = OBL.getTagName().compare(OBR.getTagName()))
262 if (
int Res =
cmpNumbers(OBL.Inputs.size(), OBR.Inputs.size()))
276 Type *TyL = L->getType();
277 Type *TyR = R->getType();
300 unsigned TyLWidth = 0;
301 unsigned TyRWidth = 0;
303 if (
auto *VecTyL = dyn_cast<VectorType>(TyL))
304 TyLWidth = VecTyL->getPrimitiveSizeInBits().getFixedValue();
305 if (
auto *VecTyR = dyn_cast<VectorType>(TyR))
306 TyRWidth = VecTyR->getPrimitiveSizeInBits().getFixedValue();
308 if (TyLWidth != TyRWidth)
318 if (
int Res =
cmpNumbers(AddrSpaceL, AddrSpaceR))
334 if (L->isNullValue() && R->isNullValue())
336 if (L->isNullValue() && !R->isNullValue())
338 if (!L->isNullValue() && R->isNullValue())
341 auto GlobalValueL =
const_cast<GlobalValue *
>(dyn_cast<GlobalValue>(L));
342 auto GlobalValueR =
const_cast<GlobalValue *
>(dyn_cast<GlobalValue>(R));
343 if (GlobalValueL && GlobalValueR) {
347 if (
int Res =
cmpNumbers(L->getValueID(), R->getValueID()))
350 if (
const auto *SeqL = dyn_cast<ConstantDataSequential>(L)) {
351 const auto *SeqR = cast<ConstantDataSequential>(R);
357 return cmpMem(SeqL->getRawDataValues(), SeqR->getRawDataValues());
360 switch (L->getValueID()) {
361 case Value::UndefValueVal:
362 case Value::PoisonValueVal:
363 case Value::ConstantTokenNoneVal:
365 case Value::ConstantIntVal: {
366 const APInt &LInt = cast<ConstantInt>(L)->getValue();
367 const APInt &RInt = cast<ConstantInt>(R)->getValue();
370 case Value::ConstantFPVal: {
371 const APFloat &LAPF = cast<ConstantFP>(L)->getValueAPF();
372 const APFloat &RAPF = cast<ConstantFP>(R)->getValueAPF();
375 case Value::ConstantArrayVal: {
378 uint64_t NumElementsL = cast<ArrayType>(TyL)->getNumElements();
379 uint64_t NumElementsR = cast<ArrayType>(TyR)->getNumElements();
380 if (
int Res =
cmpNumbers(NumElementsL, NumElementsR))
382 for (
uint64_t i = 0; i < NumElementsL; ++i) {
384 cast<Constant>(
RA->getOperand(i))))
389 case Value::ConstantStructVal: {
392 unsigned NumElementsL = cast<StructType>(TyL)->getNumElements();
393 unsigned NumElementsR = cast<StructType>(TyR)->getNumElements();
394 if (
int Res =
cmpNumbers(NumElementsL, NumElementsR))
396 for (
unsigned i = 0; i != NumElementsL; ++i) {
397 if (
int Res =
cmpConstants(cast<Constant>(LS->getOperand(i)),
403 case Value::ConstantVectorVal: {
406 unsigned NumElementsL = cast<FixedVectorType>(TyL)->getNumElements();
407 unsigned NumElementsR = cast<FixedVectorType>(TyR)->getNumElements();
408 if (
int Res =
cmpNumbers(NumElementsL, NumElementsR))
410 for (
uint64_t i = 0; i < NumElementsL; ++i) {
417 case Value::ConstantExprVal: {
422 unsigned NumOperandsL = LE->getNumOperands();
424 if (
int Res =
cmpNumbers(NumOperandsL, NumOperandsR))
426 for (
unsigned i = 0; i < NumOperandsL; ++i) {
427 if (
int Res =
cmpConstants(cast<Constant>(LE->getOperand(i)),
434 if (
auto *GEPL = dyn_cast<GEPOperator>(LE)) {
435 auto *GEPR = cast<GEPOperator>(RE);
436 if (
int Res =
cmpTypes(GEPL->getSourceElementType(),
437 GEPR->getSourceElementType()))
439 if (
int Res =
cmpNumbers(GEPL->isInBounds(), GEPR->isInBounds()))
442 std::optional<ConstantRange> InRangeL = GEPL->getInRange();
443 std::optional<ConstantRange> InRangeR = GEPR->getInRange();
447 if (
int Res =
cmpAPInts(InRangeL->getLower(), InRangeR->getLower()))
449 if (
int Res =
cmpAPInts(InRangeL->getUpper(), InRangeR->getUpper()))
451 }
else if (InRangeR) {
455 if (
auto *
OBOL = dyn_cast<OverflowingBinaryOperator>(LE)) {
456 auto *OBOR = cast<OverflowingBinaryOperator>(RE);
466 case Value::BlockAddressVal: {
500 case Value::DSOLocalEquivalentVal: {
505 const auto *LEquiv = cast<DSOLocalEquivalent>(L);
506 const auto *REquiv = cast<DSOLocalEquivalent>(R);
507 return cmpGlobalValues(LEquiv->getGlobalValue(), REquiv->getGlobalValue());
510 LLVM_DEBUG(
dbgs() <<
"Looking at valueID " << L->getValueID() <<
"\n");
531 TyL =
DL.getIntPtrType(TyL);
533 TyR =
DL.getIntPtrType(TyR);
560 assert(PTyL && PTyR &&
"Both types must be pointers here.");
591 for (
unsigned i = 0, e = FTyL->
getNumParams(); i != e; ++i) {
599 auto *STyL = cast<ArrayType>(TyL);
600 auto *STyR = cast<ArrayType>(TyR);
601 if (STyL->getNumElements() != STyR->getNumElements())
602 return cmpNumbers(STyL->getNumElements(), STyR->getNumElements());
603 return cmpTypes(STyL->getElementType(), STyR->getElementType());
607 auto *STyL = cast<VectorType>(TyL);
608 auto *STyR = cast<VectorType>(TyR);
609 if (STyL->getElementCount().isScalable() !=
610 STyR->getElementCount().isScalable())
611 return cmpNumbers(STyL->getElementCount().isScalable(),
612 STyR->getElementCount().isScalable());
613 if (STyL->getElementCount() != STyR->getElementCount())
614 return cmpNumbers(STyL->getElementCount().getKnownMinValue(),
615 STyR->getElementCount().getKnownMinValue());
616 return cmpTypes(STyL->getElementType(), STyR->getElementType());
627 bool &needToCmpOperands)
const {
628 needToCmpOperands =
true;
636 if (
int Res =
cmpNumbers(L->getOpcode(), R->getOpcode()))
640 needToCmpOperands =
false;
645 return cmpGEPs(GEPL, GEPR);
648 if (
int Res =
cmpNumbers(L->getNumOperands(), R->getNumOperands()))
651 if (
int Res =
cmpTypes(L->getType(), R->getType()))
654 if (
int Res =
cmpNumbers(L->getRawSubclassOptionalData(),
655 R->getRawSubclassOptionalData()))
660 for (
unsigned i = 0, e = L->getNumOperands(); i != e; ++i) {
662 cmpTypes(L->getOperand(i)->getType(), R->getOperand(i)->getType()))
667 if (
const AllocaInst *AI = dyn_cast<AllocaInst>(L)) {
668 if (
int Res =
cmpTypes(AI->getAllocatedType(),
669 cast<AllocaInst>(R)->getAllocatedType()))
671 return cmpAligns(AI->getAlign(), cast<AllocaInst>(R)->getAlign());
673 if (
const LoadInst *LI = dyn_cast<LoadInst>(L)) {
674 if (
int Res =
cmpNumbers(LI->isVolatile(), cast<LoadInst>(R)->isVolatile()))
676 if (
int Res =
cmpAligns(LI->getAlign(), cast<LoadInst>(R)->getAlign()))
679 cmpOrderings(LI->getOrdering(), cast<LoadInst>(R)->getOrdering()))
681 if (
int Res =
cmpNumbers(LI->getSyncScopeID(),
682 cast<LoadInst>(R)->getSyncScopeID()))
684 return cmpInstMetadata(L, R);
686 if (
const StoreInst *SI = dyn_cast<StoreInst>(L)) {
688 cmpNumbers(SI->isVolatile(), cast<StoreInst>(R)->isVolatile()))
690 if (
int Res =
cmpAligns(SI->getAlign(), cast<StoreInst>(R)->getAlign()))
693 cmpOrderings(SI->getOrdering(), cast<StoreInst>(R)->getOrdering()))
696 cast<StoreInst>(R)->getSyncScopeID());
698 if (
const CmpInst *CI = dyn_cast<CmpInst>(L))
699 return cmpNumbers(CI->getPredicate(), cast<CmpInst>(R)->getPredicate());
700 if (
auto *CBL = dyn_cast<CallBase>(L)) {
701 auto *CBR = cast<CallBase>(R);
702 if (
int Res =
cmpNumbers(CBL->getCallingConv(), CBR->getCallingConv()))
704 if (
int Res = cmpAttrs(CBL->getAttributes(), CBR->getAttributes()))
706 if (
int Res = cmpOperandBundlesSchema(*CBL, *CBR))
708 if (
const CallInst *CI = dyn_cast<CallInst>(L))
709 if (
int Res =
cmpNumbers(CI->getTailCallKind(),
710 cast<CallInst>(R)->getTailCallKind()))
712 return cmpMDNode(L->getMetadata(LLVMContext::MD_range),
713 R->getMetadata(LLVMContext::MD_range));
720 for (
size_t i = 0, e = LIndices.
size(); i != e; ++i) {
721 if (
int Res =
cmpNumbers(LIndices[i], RIndices[i]))
731 for (
size_t i = 0, e = LIndices.
size(); i != e; ++i) {
732 if (
int Res =
cmpNumbers(LIndices[i], RIndices[i]))
736 if (
const FenceInst *FI = dyn_cast<FenceInst>(L)) {
738 cmpOrderings(FI->getOrdering(), cast<FenceInst>(R)->getOrdering()))
741 cast<FenceInst>(R)->getSyncScopeID());
745 cast<AtomicCmpXchgInst>(R)->isVolatile()))
748 cmpNumbers(CXI->isWeak(), cast<AtomicCmpXchgInst>(R)->isWeak()))
751 cmpOrderings(CXI->getSuccessOrdering(),
752 cast<AtomicCmpXchgInst>(R)->getSuccessOrdering()))
755 cmpOrderings(CXI->getFailureOrdering(),
756 cast<AtomicCmpXchgInst>(R)->getFailureOrdering()))
759 cast<AtomicCmpXchgInst>(R)->getSyncScopeID());
761 if (
const AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(L)) {
762 if (
int Res =
cmpNumbers(RMWI->getOperation(),
763 cast<AtomicRMWInst>(R)->getOperation()))
766 cast<AtomicRMWInst>(R)->isVolatile()))
768 if (
int Res = cmpOrderings(RMWI->getOrdering(),
769 cast<AtomicRMWInst>(R)->getOrdering()))
772 cast<AtomicRMWInst>(R)->getSyncScopeID());
776 ArrayRef<int> RMask = cast<ShuffleVectorInst>(R)->getShuffleMask();
779 for (
size_t i = 0, e = LMask.
size(); i != e; ++i) {
784 if (
const PHINode *PNL = dyn_cast<PHINode>(L)) {
785 const PHINode *PNR = cast<PHINode>(R);
789 for (
unsigned i = 0, e = PNL->getNumIncomingValues(); i != e; ++i) {
800int FunctionComparator::cmpGEPs(
const GEPOperator *GEPL,
811 unsigned OffsetBitWidth =
DL.getIndexSizeInBits(ASL);
812 APInt OffsetL(OffsetBitWidth, 0), OffsetR(OffsetBitWidth, 0);
831int FunctionComparator::cmpInlineAsm(
const InlineAsm *L,
837 if (
int Res =
cmpTypes(
L->getFunctionType(),
R->getFunctionType()))
839 if (
int Res =
cmpMem(
L->getAsmString(),
R->getAsmString()))
841 if (
int Res =
cmpMem(
L->getConstraintString(),
R->getConstraintString()))
843 if (
int Res =
cmpNumbers(
L->hasSideEffects(),
R->hasSideEffects()))
845 if (
int Res =
cmpNumbers(
L->isAlignStack(),
R->isAlignStack()))
847 if (
int Res =
cmpNumbers(
L->getDialect(),
R->getDialect()))
849 assert(
L->getFunctionType() !=
R->getFunctionType());
870 const Constant *ConstL = dyn_cast<Constant>(L);
871 const Constant *ConstR = dyn_cast<Constant>(R);
872 if (ConstL && ConstR) {
885 if (MetadataValueL && MetadataValueR) {
886 if (MetadataValueL == MetadataValueR)
898 const InlineAsm *InlineAsmL = dyn_cast<InlineAsm>(L);
899 const InlineAsm *InlineAsmR = dyn_cast<InlineAsm>(R);
901 if (InlineAsmL && InlineAsmR)
902 return cmpInlineAsm(InlineAsmL, InlineAsmR);
908 auto LeftSN = sn_mapL.insert(std::make_pair(L, sn_mapL.size())),
909 RightSN = sn_mapR.insert(std::make_pair(R, sn_mapR.size()));
911 return cmpNumbers(LeftSN.first->second, RightSN.first->second);
921 bool needToCmpOperands =
true;
922 if (
int Res =
cmpOperations(&*InstL, &*InstR, needToCmpOperands))
924 if (needToCmpOperands) {
925 assert(InstL->getNumOperands() == InstR->getNumOperands());
927 for (
unsigned i = 0, e = InstL->getNumOperands(); i != e; ++i) {
928 Value *OpL = InstL->getOperand(i);
929 Value *OpR = InstR->getOperand(i);
939 }
while (InstL != InstLE && InstR != InstRE);
941 if (InstL != InstLE && InstR == InstRE)
943 if (InstL == InstLE && InstR != InstRE)
980 "Identically typed functions have different numbers of args!");
987 ArgLI != ArgLE; ++ArgLI, ++ArgRI) {
1011 VisitedBBs.
insert(FnLBBs[0]);
1012 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,...
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).
bool isTypeAttribute() const
Return true if the attribute is a type attribute.
ConstantRange getRange() const
Returns the value of the range 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.
This class represents a range of values.
const APInt & getLower() const
Return the lower value for this range.
const APInt & getUpper() const
Return the upper value for this range.
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.