26 #define DEBUG_TYPE "functioncomparator"
35 if ((
int)L < (
int)R)
return -1;
36 if ((
int)L > (
int)R)
return 1;
43 if (L.
ugt(R))
return 1;
44 if (R.
ugt(L))
return -1;
85 for (; LI !=
LE && RI != RE; ++LI, ++RI) {
101 int FunctionComparator::cmpRangeMetadata(
const MDNode *L,
128 int FunctionComparator::cmpOperandBundlesSchema(
const Instruction *L,
133 assert(LCS && RCS &&
"Must be calls or invokes!");
134 assert(LCS.isCall() == RCS.isCall() &&
"Can't compare otherwise!");
137 cmpNumbers(LCS.getNumOperandBundles(), RCS.getNumOperandBundles()))
140 for (
unsigned i = 0, e = LCS.getNumOperandBundles();
i != e; ++
i) {
141 auto OBL = LCS.getOperandBundleAt(
i);
142 auto OBR = RCS.getOperandBundleAt(
i);
144 if (
int Res = OBL.getTagName().compare(OBR.getTagName()))
147 if (
int Res =
cmpNumbers(OBL.Inputs.size(), OBR.Inputs.size()))
186 unsigned TyLWidth = 0;
187 unsigned TyRWidth = 0;
189 if (
auto *VecTyL = dyn_cast<VectorType>(TyL))
190 TyLWidth = VecTyL->getBitWidth();
191 if (
auto *VecTyR = dyn_cast<VectorType>(TyR))
192 TyRWidth = VecTyR->getBitWidth();
194 if (TyLWidth != TyRWidth)
203 unsigned AddrSpaceR = PTyR->getAddressSpace();
204 if (
int Res =
cmpNumbers(AddrSpaceL, AddrSpaceR))
229 if (GlobalValueL && GlobalValueR) {
236 if (
const auto *SeqL = dyn_cast<ConstantDataSequential>(L)) {
237 const auto *SeqR = cast<ConstantDataSequential>(R);
243 return cmpMem(SeqL->getRawDataValues(), SeqR->getRawDataValues());
247 case Value::UndefValueVal:
248 case Value::ConstantTokenNoneVal:
250 case Value::ConstantIntVal: {
251 const APInt &LInt = cast<ConstantInt>(
L)->getValue();
252 const APInt &RInt = cast<ConstantInt>(R)->getValue();
255 case Value::ConstantFPVal: {
256 const APFloat &LAPF = cast<ConstantFP>(
L)->getValueAPF();
257 const APFloat &RAPF = cast<ConstantFP>(R)->getValueAPF();
260 case Value::ConstantArrayVal: {
263 uint64_t NumElementsL = cast<ArrayType>(TyL)->getNumElements();
264 uint64_t NumElementsR = cast<ArrayType>(TyR)->getNumElements();
265 if (
int Res =
cmpNumbers(NumElementsL, NumElementsR))
267 for (uint64_t
i = 0;
i < NumElementsL; ++
i) {
269 cast<Constant>(RA->getOperand(
i))))
274 case Value::ConstantStructVal: {
277 unsigned NumElementsL = cast<StructType>(TyL)->getNumElements();
278 unsigned NumElementsR = cast<StructType>(TyR)->getNumElements();
279 if (
int Res =
cmpNumbers(NumElementsL, NumElementsR))
281 for (
unsigned i = 0;
i != NumElementsL; ++
i) {
283 cast<Constant>(RS->getOperand(
i))))
288 case Value::ConstantVectorVal: {
291 unsigned NumElementsL = cast<VectorType>(TyL)->getNumElements();
292 unsigned NumElementsR = cast<VectorType>(TyR)->getNumElements();
293 if (
int Res =
cmpNumbers(NumElementsL, NumElementsR))
295 for (uint64_t
i = 0;
i < NumElementsL; ++
i) {
297 cast<Constant>(RV->getOperand(
i))))
302 case Value::ConstantExprVal: {
306 unsigned NumOperandsR = RE->getNumOperands();
307 if (
int Res =
cmpNumbers(NumOperandsL, NumOperandsR))
309 for (
unsigned i = 0;
i < NumOperandsL; ++
i) {
311 cast<Constant>(RE->getOperand(
i))))
316 case Value::BlockAddressVal: {
358 uint64_t LNumber = GlobalNumbers->
getNumber(L);
359 uint64_t RNumber = GlobalNumbers->
getNumber(R);
372 TyL = DL.getIntPtrType(TyL);
373 if (PTyR && PTyR->getAddressSpace() == 0)
374 TyR = DL.getIntPtrType(TyR);
403 assert(PTyL && PTyR &&
"Both types must be pointers here.");
413 if (STyL->
isPacked() != STyR->isPacked())
429 if (FTyL->
isVarArg() != FTyR->isVarArg())
444 auto *STyL = cast<SequentialType>(TyL);
445 auto *STyR = cast<SequentialType>(TyR);
446 if (STyL->getNumElements() != STyR->getNumElements())
447 return cmpNumbers(STyL->getNumElements(), STyR->getNumElements());
448 return cmpTypes(STyL->getElementType(), STyR->getElementType());
459 bool &needToCmpOperands)
const {
460 needToCmpOperands =
true;
472 needToCmpOperands =
false;
477 return cmpGEPs(GEPL, GEPR);
499 if (
const AllocaInst *AI = dyn_cast<AllocaInst>(L)) {
500 if (
int Res =
cmpTypes(AI->getAllocatedType(),
501 cast<AllocaInst>(R)->getAllocatedType()))
505 if (
const LoadInst *LI = dyn_cast<LoadInst>(L)) {
512 cmpOrderings(LI->getOrdering(), cast<LoadInst>(R)->getOrdering()))
515 cmpNumbers(LI->getSynchScope(), cast<LoadInst>(R)->getSynchScope()))
520 if (
const StoreInst *
SI = dyn_cast<StoreInst>(L)) {
528 cmpOrderings(
SI->getOrdering(), cast<StoreInst>(R)->getOrdering()))
530 return cmpNumbers(
SI->getSynchScope(), cast<StoreInst>(R)->getSynchScope());
532 if (
const CmpInst *CI = dyn_cast<CmpInst>(L))
533 return cmpNumbers(CI->getPredicate(), cast<CmpInst>(R)->getPredicate());
534 if (
const CallInst *CI = dyn_cast<CallInst>(L)) {
535 if (
int Res =
cmpNumbers(CI->getCallingConv(),
536 cast<CallInst>(R)->getCallingConv()))
539 cmpAttrs(CI->getAttributes(), cast<CallInst>(R)->
getAttributes()))
541 if (
int Res = cmpOperandBundlesSchema(CI, R))
543 return cmpRangeMetadata(
547 if (
const InvokeInst *II = dyn_cast<InvokeInst>(L)) {
548 if (
int Res =
cmpNumbers(II->getCallingConv(),
549 cast<InvokeInst>(R)->getCallingConv()))
552 cmpAttrs(II->getAttributes(), cast<InvokeInst>(R)->
getAttributes()))
554 if (
int Res = cmpOperandBundlesSchema(II, R))
556 return cmpRangeMetadata(
565 for (
size_t i = 0, e = LIndices.
size();
i != e; ++
i) {
566 if (
int Res =
cmpNumbers(LIndices[
i], RIndices[i]))
576 for (
size_t i = 0, e = LIndices.
size();
i != e; ++
i) {
577 if (
int Res =
cmpNumbers(LIndices[
i], RIndices[i]))
581 if (
const FenceInst *FI = dyn_cast<FenceInst>(L)) {
583 cmpOrderings(FI->getOrdering(), cast<FenceInst>(R)->getOrdering()))
585 return cmpNumbers(FI->getSynchScope(), cast<FenceInst>(R)->getSynchScope());
592 cast<AtomicCmpXchgInst>(R)->
isWeak()))
595 cmpOrderings(CXI->getSuccessOrdering(),
596 cast<AtomicCmpXchgInst>(R)->getSuccessOrdering()))
599 cmpOrderings(CXI->getFailureOrdering(),
600 cast<AtomicCmpXchgInst>(R)->getFailureOrdering()))
603 cast<AtomicCmpXchgInst>(R)->getSynchScope());
605 if (
const AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(L)) {
606 if (
int Res =
cmpNumbers(RMWI->getOperation(),
607 cast<AtomicRMWInst>(R)->getOperation()))
612 if (
int Res = cmpOrderings(RMWI->getOrdering(),
613 cast<AtomicRMWInst>(R)->getOrdering()))
616 cast<AtomicRMWInst>(R)->getSynchScope());
618 if (
const PHINode *PNL = dyn_cast<PHINode>(L)) {
619 const PHINode *PNR = cast<PHINode>(R);
623 for (
unsigned i = 0, e = PNL->getNumIncomingValues();
i != e; ++
i) {
634 int FunctionComparator::cmpGEPs(
const GEPOperator *GEPL,
647 APInt OffsetL(BitWidth, 0), OffsetR(BitWidth, 0);
666 int FunctionComparator::cmpInlineAsm(
const InlineAsm *L,
707 if (ConstL && ConstR) {
721 if (InlineAsmL && InlineAsmR)
722 return cmpInlineAsm(InlineAsmL, InlineAsmR);
728 auto LeftSN = sn_mapL.insert(std::make_pair(L, sn_mapL.size())),
729 RightSN = sn_mapR.insert(std::make_pair(R, sn_mapR.size()));
731 return cmpNumbers(LeftSN.first->second, RightSN.first->second);
741 bool needToCmpOperands =
true;
742 if (
int Res =
cmpOperations(&*InstL, &*InstR, needToCmpOperands))
744 if (needToCmpOperands) {
745 assert(InstL->getNumOperands() == InstR->getNumOperands());
747 for (
unsigned i = 0, e = InstL->getNumOperands();
i != e; ++
i) {
748 Value *OpL = InstL->getOperand(
i);
749 Value *OpR = InstR->getOperand(
i);
759 }
while (InstL != InstLE && InstR != InstRE);
761 if (InstL != InstLE && InstR == InstRE)
763 if (InstL == InstLE && InstR != InstRE)
800 "Identically typed functions have different numbers of args!");
807 ArgLI != ArgLE; ++ArgLI, ++ArgRI) {
831 VisitedBBs.
insert(FnLBBs[0]);
832 while (!FnLBBs.
empty()) {
866 class HashAccumulator64 {
870 HashAccumulator64() {
Hash = 0x6acaa36bef8325c5ULL; }
871 void add(uint64_t V) {
875 uint64_t getHash() {
return Hash; }
900 VisitedBBs.
insert(BBs[0]);
901 while (!BBs.
empty()) {
906 for (
auto &Inst : *BB) {
907 H.add(Inst.getOpcode());
static unsigned getBitWidth(Type *Ty, const DataLayout &DL)
Returns the bitwidth of the given scalar or pointer type (if unknown returns 0).
Type * getSourceElementType() const
void push_back(const T &Elt)
A parsed version of the target data layout string in and methods for querying it. ...
AsmDialect getDialect() const
Value * getPointerOperand()
This class is the base class for the comparison instructions.
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 ...
unsigned getNumParams() const
Return the number of fixed parameters this function type requires.
2: 32-bit floating point type
An instruction for ordering other memory operations.
an instruction that atomically checks whether a specified value is in a memory location, and, if it is, stores a new value there.
unsigned getNumOperands() const
unsigned getNumOperands() const
Return number of MDNode operands.
This class represents a function call, abstracting a target machine's calling convention.
const std::string & getAsmString() const
iterator begin(unsigned Slot) const
const std::string & getConstraintString() const
unsigned getAlignment() const
Returns the alignment field of an attribute as a byte alignment value.
4: 80-bit floating point type (X87)
unsigned getAddressSpace() const
Return the address space of the Pointer type.
An instruction for reading from memory.
an instruction that atomically reads a memory location, combines it with another value, and then stores the result back.
int cmpAPInts(const APInt &L, const APInt &R) const
int cmpOperations(const Instruction *L, const Instruction *R, bool &needToCmpOperands) const
Compare two Instructions for equivalence, similar to Instruction::isSameOperationAs.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
iterator begin()
Instruction iterator methods.
The address of a basic block.
int cmpGlobalValues(GlobalValue *L, GlobalValue *R) const
Compares two global values by number.
bool hasGC() const
hasGC/getGC/setGC/clearGC - The name of the garbage collection algorithm to use during code generatio...
const APInt & getValue() const
Return the constant as an APInt value reference.
Class to represent struct types.
APInt bitcastToAPInt() const
static ExponentType semanticsMaxExponent(const fltSemantics &)
LLVM_NODISCARD bool empty() const
AtomicOrdering
Atomic ordering for LLVM's memory model.
void beginCompare()
Start the comparison.
Class to represent function types.
A constant value that is initialized with an expression using other constant values.
static unsigned getAlignment(GlobalVariable *GV)
bool accumulateConstantOffset(const DataLayout &DL, APInt &Offset) const
Accumulate the constant address offset of this GEP if possible.
static unsigned int semanticsSizeInBits(const fltSemantics &)
static bool add(uint64_t *dest, const uint64_t *x, const uint64_t *y, unsigned len)
This function adds the integer array x to the integer array Y and places the result in dest...
bool isFirstClassType() const
Return true if the type is "first class", meaning it is a valid type for a Value. ...
StringRef getSection() const
Get the custom section of this global if it has one.
TypeID getTypeID() const
Return the type id for the type.
uint64_t hash_16_bytes(uint64_t low, uint64_t high)
An instruction for storing to memory.
uint64_t getNumber(GlobalValue *Global)
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE size_t size() const
size - Get the string size.
size_t size() const
size - Get the array size.
static ExponentType semanticsMinExponent(const fltSemantics &)
Class to represent pointers.
static FunctionHash functionHash(Function &)
11: Arbitrary bit width integers
bool hasSection() const
Check if this global has a custom object file section.
unsigned getNumSuccessors() const
Return the number of successors that this terminator has.
an instruction for type-safe pointer arithmetic to access elements of arrays and structs ...
unsigned getNumSlots() const
Return the number of slots used in this attribute list.
Type * getParamType(unsigned i) const
Parameter type accessors.
Subclasses of this class are all able to terminate a basic block.
bool hasSideEffects() const
LLVM Basic Block Representation.
The instances of the Type class are immutable: once they are created, they are never changed...
BasicBlock * getSuccessor(unsigned idx) const
Return the specified successor.
Type * getElementType(unsigned N) const
This is an important base class in LLVM.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
BasicBlock * getIncomingBlock(unsigned i) const
Return incoming basic block number i.
unsigned getBitWidth() const
Return the number of bits in the APInt.
unsigned getValueID() const
Return an ID for the concrete type of this object.
6: 128-bit floating point type (two 64-bits, PowerPC)
Value * getOperand(unsigned i) const
std::pair< NoneType, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
Constant Vector Declarations.
int cmpNumbers(uint64_t L, uint64_t R) const
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE int compare(StringRef RHS) const
compare - Compare two strings; the result is -1, 0, or 1 if this string is lexicographically less tha...
int cmpMem(StringRef L, StringRef R) const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
uint64_t FunctionHash
Hash a function.
bool ugt(const APInt &RHS) const
Unsigned greather than comparison.
int compareSignature() const
Compares the signature and other general attributes of the two functions.
const MDOperand & getOperand(unsigned I) const
FunctionType * getFunctionType() const
getFunctionType - InlineAsm's are always pointers to functions.
Iterator for intrusive lists based on ilist_node.
const BasicBlockListType & getBasicBlockList() const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
This is the shared class of boolean and integer constants.
int cmpTypes(Type *TyL, Type *TyR) const
cmpType - compares two types, defines total ordering among the types set.
16: SIMD 'packed' format, or other vector type
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Module.h This file contains the declarations for the Module class.
Type * getType() const
All values are typed, get the type of this value.
iterator end(unsigned Slot) const
LLVM_NODISCARD T pop_back_val()
BasicBlock * getBasicBlock() const
const BasicBlock & getEntryBlock() const
bool isNullValue() const
Return true if this is the value that would be returned by getNullValue.
static unsigned int semanticsPrecision(const fltSemantics &)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
AttributeSet getAttributes() const
Return the attribute list for this Function.
ConstantArray - Constant Array Declarations.
Class for arbitrary precision integers.
static bool isWeak(const MCSymbolELF &Sym)
int compare()
Test whether the two functions have equivalent behaviour.
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
int cmpConstants(const Constant *L, const Constant *R) const
Constants comparison.
unsigned getRawSubclassOptionalData() const
Return the raw optional flags value contained in this value.
ImmutableCallSite - establish a view to a call site for examination.
const std::string & getGC() const
TerminatorInst * getTerminator()
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
FunctionType * getFunctionType() const
Returns the FunctionType for me.
int cmpBasicBlocks(const BasicBlock *BBL, const BasicBlock *BBR) const
Test whether two basic blocks have equivalent behaviour.
unsigned getPointerSizeInBits(unsigned AS=0) const
Layout pointer size, in bits FIXME: The defaults need to be removed once all of the backends/clients ...
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
unsigned getPointerAddressSpace() const
Method to return the address space of the pointer operand.
AttributeSet getAttributes(LLVMContext &C, ID id)
Return the attributes for an intrinsic.
3: 64-bit floating point type
Type * getReturnType() const
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Function * getFunction() const
Module * getParent()
Get the module that this global value is contained inside of...
LLVM Value Representation.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
#define LLVM_FALLTHROUGH
LLVM_FALLTHROUGH - Mark fallthrough cases in switch statements.
int cmpAPFloats(const APFloat &L, const APFloat &R) const
std::string Hash(const Unit &U)
StringRef - Represent a constant reference to a string, i.e.
static bool isVolatile(Instruction *Inst)
unsigned getNumElements() const
Random access to the elements.
bool isAlignStack() const
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
const fltSemantics & getSemantics() const
an instruction to allocate memory on the stack
This instruction inserts a struct field of array element value into an aggregate value.
5: 128-bit floating point type (112-bit mantissa)