51#define DEBUG_TYPE "functioncomparator"
62 if (L.
value() < R.value())
64 if (L.
value() > R.value())
113 return std::clamp(L.
compare(R), -1, 1);
121 for (
unsigned i : L.
indexes()) {
126 for (; LI != LE && RI != RE; ++LI, ++RI) {
129 if (LA.isTypeAttribute() &&
RA.isTypeAttribute()) {
130 if (LA.getKindAsEnum() !=
RA.getKindAsEnum())
131 return cmpNumbers(LA.getKindAsEnum(),
RA.getKindAsEnum());
133 Type *TyL = LA.getValueAsType();
134 Type *TyR =
RA.getValueAsType();
160int FunctionComparator::cmpRangeMetadata(
const MDNode *L,
180 ConstantInt *RLow = mdconst::extract<ConstantInt>(
R->getOperand(
I));
187int FunctionComparator::cmpOperandBundlesSchema(
const CallBase &LCS,
199 if (
int Res = OBL.getTagName().compare(OBR.getTagName()))
202 if (
int Res =
cmpNumbers(OBL.Inputs.size(), OBR.Inputs.size()))
217 Type *TyR = R->getType();
240 unsigned TyLWidth = 0;
241 unsigned TyRWidth = 0;
243 if (
auto *VecTyL = dyn_cast<VectorType>(TyL))
244 TyLWidth = VecTyL->getPrimitiveSizeInBits().getFixedValue();
245 if (
auto *VecTyR = dyn_cast<VectorType>(TyR))
246 TyRWidth = VecTyR->getPrimitiveSizeInBits().getFixedValue();
248 if (TyLWidth != TyRWidth)
258 if (
int Res =
cmpNumbers(AddrSpaceL, AddrSpaceR))
281 auto GlobalValueL =
const_cast<GlobalValue *
>(dyn_cast<GlobalValue>(L));
282 auto GlobalValueR =
const_cast<GlobalValue *
>(dyn_cast<GlobalValue>(R));
283 if (GlobalValueL && GlobalValueR) {
290 if (
const auto *SeqL = dyn_cast<ConstantDataSequential>(L)) {
291 const auto *SeqR = cast<ConstantDataSequential>(R);
297 return cmpMem(SeqL->getRawDataValues(), SeqR->getRawDataValues());
301 case Value::UndefValueVal:
302 case Value::PoisonValueVal:
303 case Value::ConstantTokenNoneVal:
305 case Value::ConstantIntVal: {
306 const APInt &LInt = cast<ConstantInt>(L)->getValue();
307 const APInt &RInt = cast<ConstantInt>(R)->getValue();
310 case Value::ConstantFPVal: {
311 const APFloat &LAPF = cast<ConstantFP>(L)->getValueAPF();
312 const APFloat &RAPF = cast<ConstantFP>(R)->getValueAPF();
315 case Value::ConstantArrayVal: {
318 uint64_t NumElementsL = cast<ArrayType>(TyL)->getNumElements();
319 uint64_t NumElementsR = cast<ArrayType>(TyR)->getNumElements();
320 if (
int Res =
cmpNumbers(NumElementsL, NumElementsR))
322 for (
uint64_t i = 0; i < NumElementsL; ++i) {
323 if (
int Res =
cmpConstants(cast<Constant>(LA->getOperand(i)),
324 cast<Constant>(
RA->getOperand(i))))
329 case Value::ConstantStructVal: {
332 unsigned NumElementsL = cast<StructType>(TyL)->getNumElements();
333 unsigned NumElementsR = cast<StructType>(TyR)->getNumElements();
334 if (
int Res =
cmpNumbers(NumElementsL, NumElementsR))
336 for (
unsigned i = 0; i != NumElementsL; ++i) {
337 if (
int Res =
cmpConstants(cast<Constant>(LS->getOperand(i)),
343 case Value::ConstantVectorVal: {
346 unsigned NumElementsL = cast<FixedVectorType>(TyL)->getNumElements();
347 unsigned NumElementsR = cast<FixedVectorType>(TyR)->getNumElements();
348 if (
int Res =
cmpNumbers(NumElementsL, NumElementsR))
350 for (
uint64_t i = 0; i < NumElementsL; ++i) {
357 case Value::ConstantExprVal: {
360 unsigned NumOperandsL = LE->getNumOperands();
362 if (
int Res =
cmpNumbers(NumOperandsL, NumOperandsR))
364 for (
unsigned i = 0; i < NumOperandsL; ++i) {
365 if (
int Res =
cmpConstants(cast<Constant>(LE->getOperand(i)),
371 case Value::BlockAddressVal: {
405 case Value::DSOLocalEquivalentVal: {
410 const auto *LEquiv = cast<DSOLocalEquivalent>(L);
411 const auto *REquiv = cast<DSOLocalEquivalent>(R);
412 return cmpGlobalValues(LEquiv->getGlobalValue(), REquiv->getGlobalValue());
436 TyL =
DL.getIntPtrType(TyL);
438 TyR =
DL.getIntPtrType(TyR);
465 assert(PTyL && PTyR &&
"Both types must be pointers here.");
496 for (
unsigned i = 0, e = FTyL->
getNumParams(); i != e; ++i) {
504 auto *STyL = cast<ArrayType>(TyL);
505 auto *STyR = cast<ArrayType>(TyR);
506 if (STyL->getNumElements() != STyR->getNumElements())
507 return cmpNumbers(STyL->getNumElements(), STyR->getNumElements());
508 return cmpTypes(STyL->getElementType(), STyR->getElementType());
512 auto *STyL = cast<VectorType>(TyL);
513 auto *STyR = cast<VectorType>(TyR);
514 if (STyL->getElementCount().isScalable() !=
515 STyR->getElementCount().isScalable())
516 return cmpNumbers(STyL->getElementCount().isScalable(),
517 STyR->getElementCount().isScalable());
518 if (STyL->getElementCount() != STyR->getElementCount())
519 return cmpNumbers(STyL->getElementCount().getKnownMinValue(),
520 STyR->getElementCount().getKnownMinValue());
521 return cmpTypes(STyL->getElementType(), STyR->getElementType());
532 bool &needToCmpOperands)
const {
533 needToCmpOperands =
true;
545 needToCmpOperands =
false;
550 return cmpGEPs(GEPL, GEPR);
560 R->getRawSubclassOptionalData()))
572 if (
const AllocaInst *AI = dyn_cast<AllocaInst>(L)) {
573 if (
int Res =
cmpTypes(AI->getAllocatedType(),
574 cast<AllocaInst>(R)->getAllocatedType()))
576 return cmpAligns(AI->getAlign(), cast<AllocaInst>(R)->getAlign());
578 if (
const LoadInst *LI = dyn_cast<LoadInst>(L)) {
579 if (
int Res =
cmpNumbers(LI->isVolatile(), cast<LoadInst>(R)->isVolatile()))
581 if (
int Res =
cmpAligns(LI->getAlign(), cast<LoadInst>(R)->getAlign()))
584 cmpOrderings(LI->getOrdering(), cast<LoadInst>(R)->getOrdering()))
586 if (
int Res =
cmpNumbers(LI->getSyncScopeID(),
587 cast<LoadInst>(R)->getSyncScopeID()))
589 return cmpRangeMetadata(
590 LI->getMetadata(LLVMContext::MD_range),
591 cast<LoadInst>(R)->getMetadata(LLVMContext::MD_range));
593 if (
const StoreInst *
SI = dyn_cast<StoreInst>(L)) {
595 cmpNumbers(
SI->isVolatile(), cast<StoreInst>(R)->isVolatile()))
597 if (
int Res =
cmpAligns(
SI->getAlign(), cast<StoreInst>(R)->getAlign()))
600 cmpOrderings(
SI->getOrdering(), cast<StoreInst>(R)->getOrdering()))
603 cast<StoreInst>(R)->getSyncScopeID());
605 if (
const CmpInst *CI = dyn_cast<CmpInst>(L))
606 return cmpNumbers(CI->getPredicate(), cast<CmpInst>(R)->getPredicate());
607 if (
auto *CBL = dyn_cast<CallBase>(L)) {
608 auto *CBR = cast<CallBase>(R);
609 if (
int Res =
cmpNumbers(CBL->getCallingConv(), CBR->getCallingConv()))
611 if (
int Res = cmpAttrs(CBL->getAttributes(), CBR->getAttributes()))
613 if (
int Res = cmpOperandBundlesSchema(*CBL, *CBR))
615 if (
const CallInst *CI = dyn_cast<CallInst>(L))
616 if (
int Res =
cmpNumbers(CI->getTailCallKind(),
617 cast<CallInst>(R)->getTailCallKind()))
619 return cmpRangeMetadata(L->
getMetadata(LLVMContext::MD_range),
620 R->getMetadata(LLVMContext::MD_range));
627 for (
size_t i = 0, e = LIndices.
size(); i != e; ++i) {
628 if (
int Res =
cmpNumbers(LIndices[i], RIndices[i]))
638 for (
size_t i = 0, e = LIndices.
size(); i != e; ++i) {
639 if (
int Res =
cmpNumbers(LIndices[i], RIndices[i]))
643 if (
const FenceInst *FI = dyn_cast<FenceInst>(L)) {
645 cmpOrderings(FI->getOrdering(), cast<FenceInst>(R)->getOrdering()))
648 cast<FenceInst>(R)->getSyncScopeID());
652 cast<AtomicCmpXchgInst>(R)->isVolatile()))
655 cmpNumbers(CXI->isWeak(), cast<AtomicCmpXchgInst>(R)->isWeak()))
658 cmpOrderings(CXI->getSuccessOrdering(),
659 cast<AtomicCmpXchgInst>(R)->getSuccessOrdering()))
662 cmpOrderings(CXI->getFailureOrdering(),
663 cast<AtomicCmpXchgInst>(R)->getFailureOrdering()))
666 cast<AtomicCmpXchgInst>(R)->getSyncScopeID());
668 if (
const AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(L)) {
669 if (
int Res =
cmpNumbers(RMWI->getOperation(),
670 cast<AtomicRMWInst>(R)->getOperation()))
673 cast<AtomicRMWInst>(R)->isVolatile()))
675 if (
int Res = cmpOrderings(RMWI->getOrdering(),
676 cast<AtomicRMWInst>(R)->getOrdering()))
679 cast<AtomicRMWInst>(R)->getSyncScopeID());
683 ArrayRef<int> RMask = cast<ShuffleVectorInst>(R)->getShuffleMask();
686 for (
size_t i = 0, e = LMask.
size(); i != e; ++i) {
691 if (
const PHINode *PNL = dyn_cast<PHINode>(L)) {
692 const PHINode *PNR = cast<PHINode>(R);
696 for (
unsigned i = 0, e = PNL->getNumIncomingValues(); i != e; ++i) {
707int FunctionComparator::cmpGEPs(
const GEPOperator *GEPL,
718 unsigned BitWidth =
DL.getPointerSizeInBits(ASL);
738int FunctionComparator::cmpInlineAsm(
const InlineAsm *L,
777 const Constant *ConstL = dyn_cast<Constant>(L);
778 const Constant *ConstR = dyn_cast<Constant>(R);
779 if (ConstL && ConstR) {
790 const InlineAsm *InlineAsmL = dyn_cast<InlineAsm>(L);
791 const InlineAsm *InlineAsmR = dyn_cast<InlineAsm>(R);
793 if (InlineAsmL && InlineAsmR)
794 return cmpInlineAsm(InlineAsmL, InlineAsmR);
800 auto LeftSN = sn_mapL.insert(std::make_pair(L, sn_mapL.size())),
801 RightSN = sn_mapR.insert(std::make_pair(R, sn_mapR.size()));
803 return cmpNumbers(LeftSN.first->second, RightSN.first->second);
813 bool needToCmpOperands =
true;
814 if (
int Res =
cmpOperations(&*InstL, &*InstR, needToCmpOperands))
816 if (needToCmpOperands) {
817 assert(InstL->getNumOperands() == InstR->getNumOperands());
819 for (
unsigned i = 0, e = InstL->getNumOperands(); i != e; ++i) {
820 Value *OpL = InstL->getOperand(i);
821 Value *OpR = InstR->getOperand(i);
831 }
while (InstL != InstLE && InstR != InstRE);
833 if (InstL != InstLE && InstR == InstRE)
835 if (InstL == InstLE && InstR != InstRE)
872 "Identically typed functions have different numbers of args!");
879 ArgLI != ArgLE; ++ArgLI, ++ArgRI) {
903 VisitedBBs.
insert(FnLBBs[0]);
904 while (!FnLBBs.
empty()) {
938class HashAccumulator64 {
943 HashAccumulator64() { Hash = 0x6acaa36bef8325c5ULL; }
974 VisitedBBs.
insert(BBs[0]);
975 while (!BBs.
empty()) {
980 for (
const auto &Inst : *BB) {
981 H.add(Inst.getOpcode());
984 for (
unsigned i = 0, e = Term->getNumSuccessors(); i != e; ++i) {
985 if (!VisitedBBs.
insert(Term->getSuccessor(i)).second)
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.
const fltSemantics & getSemantics() const
APInt bitcastToAPInt() const
Class for arbitrary precision integers.
bool ugt(const APInt &RHS) const
Unsigned greater than comparison.
unsigned getBitWidth() const
Return the number of bits in the APInt.
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,...
index_iterator indexes() const
Use this to iterate over the valid attribute indexes.
unsigned getNumAttrSets() const
AttributeSet getAttributes(unsigned Index) const
The attributes for the specified index are returned.
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.
This is the shared class of boolean and integer constants.
const APInt & getValue() const
Return the constant as an APInt value reference.
Constant Vector Declarations.
This is an important base class in LLVM.
bool isNullValue() const
Return true if this is the value that would be returned by getNullValue.
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
static FunctionHash functionHash(Function &)
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...
const std::string & getConstraintString() const
const std::string & getAsmString() const
bool isAlignStack() const
AsmDialect getDialect() const
FunctionType * getFunctionType() const
getFunctionType - InlineAsm's are always pointers to functions.
bool hasSideEffects() const
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.
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this Instruction.
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 MDOperand & getOperand(unsigned I) const
unsigned getNumOperands() const
Return number of MDNode operands.
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.
constexpr size_t size() const
size - Get the string size.
int compare(StringRef RHS) const
compare - Compare two strings; the result is negative, zero, or positive if this string is lexicograp...
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.
unsigned getRawSubclassOptionalData() const
Return the raw optional flags value contained in this value.
unsigned getValueID() const
Return an ID for the concrete type of this object.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
uint64_t hash_16_bytes(uint64_t low, uint64_t high)
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.
constexpr unsigned BitWidth
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.
uint64_t value() const
This is a hole in the type system and should not be abused.