class FunctionComparator
Declaration
class FunctionComparator { /* full declaration omitted */ };
Description
FunctionComparator - Compares two functions to determine whether or not they will generate machine code with the same behaviour. DataLayout is used if available. The comparator always fails conservatively (erring on the side of claiming that two functions are different).
Declared at: llvm/include/llvm/Transforms/Utils/FunctionComparator.h:93
Member Variables
- protected const llvm::Function* FnL
- protected const llvm::Function* FnR
Method Overview
- public FunctionComparator(const llvm::Function * F1, const llvm::Function * F2, llvm::GlobalNumberState * GN)
- protected void beginCompare()
- protected int cmpAPFloats(const llvm::APFloat & L, const llvm::APFloat & R) const
- protected int cmpAPInts(const llvm::APInt & L, const llvm::APInt & R) const
- protected int cmpBasicBlocks(const llvm::BasicBlock * BBL, const llvm::BasicBlock * BBR) const
- protected int cmpConstants(const llvm::Constant * L, const llvm::Constant * R) const
- protected int cmpGlobalValues(llvm::GlobalValue * L, llvm::GlobalValue * R) const
- protected int cmpMem(llvm::StringRef L, llvm::StringRef R) const
- protected int cmpNumbers(uint64_t L, uint64_t R) const
- protected int cmpOperations(const llvm::Instruction * L, const llvm::Instruction * R, bool & needToCmpOperands) const
- protected int cmpTypes(llvm::Type * TyL, llvm::Type * TyR) const
- protected int cmpValues(const llvm::Value * L, const llvm::Value * R) const
- public int compare()
- protected int compareSignature() const
- public static llvm::FunctionComparator::FunctionHash functionHash(llvm::Function &)
Methods
¶FunctionComparator(const llvm::Function* F1,
const llvm::Function* F2,
llvm::GlobalNumberState* GN)
FunctionComparator(const llvm::Function* F1,
const llvm::Function* F2,
llvm::GlobalNumberState* GN)
Declared at: llvm/include/llvm/Transforms/Utils/FunctionComparator.h:95
Parameters
- const llvm::Function* F1
- const llvm::Function* F2
- llvm::GlobalNumberState* GN
¶void beginCompare()
void beginCompare()
Description
Start the comparison.
Declared at: llvm/include/llvm/Transforms/Utils/FunctionComparator.h:109
¶int cmpAPFloats(const llvm::APFloat& L,
const llvm::APFloat& R) const
int cmpAPFloats(const llvm::APFloat& L,
const llvm::APFloat& R) const
Declared at: llvm/include/llvm/Transforms/Utils/FunctionComparator.h:324
Parameters
- const llvm::APFloat& L
- const llvm::APFloat& R
¶int cmpAPInts(const llvm::APInt& L,
const llvm::APInt& R) const
int cmpAPInts(const llvm::APInt& L,
const llvm::APInt& R) const
Declared at: llvm/include/llvm/Transforms/Utils/FunctionComparator.h:323
Parameters
- const llvm::APInt& L
- const llvm::APInt& R
¶int cmpBasicBlocks(
const llvm::BasicBlock* BBL,
const llvm::BasicBlock* BBR) const
int cmpBasicBlocks(
const llvm::BasicBlock* BBL,
const llvm::BasicBlock* BBR) const
Description
Test whether two basic blocks have equivalent behaviour.
Declared at: llvm/include/llvm/Transforms/Utils/FunctionComparator.h:118
Parameters
- const llvm::BasicBlock* BBL
- const llvm::BasicBlock* BBR
¶int cmpConstants(const llvm::Constant* L,
const llvm::Constant* R) const
int cmpConstants(const llvm::Constant* L,
const llvm::Constant* R) const
Description
Constants comparison. Its analog to lexicographical comparison between hypothetical numbers of next format: <bitcastability -trait> <raw -bit-contents> 1. Bitcastability. Check whether L's type could be losslessly bitcasted to R's type. On this stage method, in case when lossless bitcast is not possible method returns -1 or 1, thus also defining which type is greater in context of bitcastability. Stage 0: If types are equal in terms of cmpTypes, then we can go straight to the contents comparison. If types differ, remember types comparison result and check whether we still can bitcast types. Stage 1: Types that satisfies isFirstClassType conditions are always greater then others. Stage 2: Vector is greater then non-vector. If both types are vectors, then vector with greater bitwidth is greater. If both types are vectors with the same bitwidth, then types are bitcastable, and we can skip other stages, and go to contents comparison. Stage 3: Pointer types are greater than non-pointers. If both types are pointers of the same address space - go to contents comparison. Different address spaces: pointer with greater address space is greater. Stage 4: Types are neither vectors, nor pointers. And they differ. We don't know how to bitcast them. So, we better don't do it, and return types comparison result (so it determines the relationship among constants we don't know how to bitcast). Just for clearance, let's see how the set of constants could look on single dimension axis: [NFCT], [FCT, "others"], [FCT, pointers], [FCT, vectors] Where: NFCT - Not a FirstClassType FCT - FirstClassTyp: 2. Compare raw contents. It ignores types on this stage and only compares bits from L and R. Returns 0, if L and R has equivalent contents. -1 or 1 if values are different. Pretty trivial: 2.1. If contents are numbers, compare numbers. Ints with greater bitwidth are greater. Ints with same bitwidths compared by their contents. 2.2. "And so on". Just to avoid discrepancies with comments perhaps it would be better to read the implementation itself. 3. And again about overall picture. Let's look back at how the ordered set of constants will look like: [NFCT], [FCT, "others"], [FCT, pointers], [FCT, vectors] Now look, what could be inside [FCT, "others"], for example: [FCT, "others"] = [ [double 0.1], [double 1.23], [i32 1], [i32 2], { double 1.0 }, ; StructTyID, NumElements = 1 { i32 1 }, ; StructTyID, NumElements = 1 { double 1, i32 1 }, ; StructTyID, NumElements = 2 { i32 1, double 1 } ; StructTyID, NumElements = 2 ] Let's explain the order. Float numbers will be less than integers, just because of cmpType terms: FloatTyID < IntegerTyID. Floats (with same fltSemantics) are sorted according to their value. Then you can see integers, and they are, like a floats, could be easy sorted among each others. The structures. Structures are grouped at the tail, again because of their TypeID: StructTyID > IntegerTyID > FloatTyID. Structures with greater number of elements are greater. Structures with greater elements going first are greater. The same logic with vectors, arrays and other possible complex types. Bitcastable constants. Let's assume, that some constant, belongs to some group of "so-called-equal" values with different types, and at the same time belongs to another group of constants with equal types and "really" equal values. Now, prove that this is impossible: If constant A with type TyA is bitcastable to B with type TyB, then: 1. All constants with equal types to TyA, are bitcastable to B. Since those should be vectors (if TyA is vector), pointers (if TyA is pointer), or else (if TyA equal to TyB), those types should be equal to TyB. 2. All constants with non-equal, but bitcastable types to TyA, are bitcastable to B. Once again, just because we allow it to vectors and pointers only. This statement could be expanded as below: 2.1. All vectors with equal bitwidth to vector A, has equal bitwidth to vector B, and thus bitcastable to B as well. 2.2. All pointers of the same address space, no matter what they point to, bitcastable. So if C is pointer, it could be bitcasted to A and to B. So any constant equal or bitcastable to A is equal or bitcastable to B. QED. In another words, for pointers and vectors, we ignore top-level type and look at their particular properties (bit-width for vectors, and address space for pointers). If these properties are equal - compare their contents.
Declared at: llvm/include/llvm/Transforms/Utils/FunctionComparator.h:222
Parameters
- const llvm::Constant* L
- const llvm::Constant* R
¶int cmpGlobalValues(llvm::GlobalValue* L,
llvm::GlobalValue* R) const
int cmpGlobalValues(llvm::GlobalValue* L,
llvm::GlobalValue* R) const
Description
Compares two global values by number. Uses the GlobalNumbersState to identify the same gobals across function calls.
Declared at: llvm/include/llvm/Transforms/Utils/FunctionComparator.h:226
Parameters
¶int cmpMem(llvm::StringRef L,
llvm::StringRef R) const
int cmpMem(llvm::StringRef L,
llvm::StringRef R) const
Declared at: llvm/include/llvm/Transforms/Utils/FunctionComparator.h:325
Parameters
¶int cmpNumbers(uint64_t L, uint64_t R) const
int cmpNumbers(uint64_t L, uint64_t R) const
Declared at: llvm/include/llvm/Transforms/Utils/FunctionComparator.h:322
Parameters
- uint64_t L
- uint64_t R
¶int cmpOperations(const llvm::Instruction* L,
const llvm::Instruction* R,
bool& needToCmpOperands) const
int cmpOperations(const llvm::Instruction* L,
const llvm::Instruction* R,
bool& needToCmpOperands) const
Description
Compare two Instructions for equivalence, similar to Instruction::isSameOperationAs. Stages are listed in "most significant stage first" order: On each stage below, we do comparison between some left and right operation parts. If parts are non-equal, we assign parts comparison result to the operation comparison result and exit from method. Otherwise we proceed to the next stage. Stages: 1. Operations opcodes. Compared as numbers. 2. Number of operands. 3. Operation types. Compared with cmpType method. 4. Compare operation subclass optional data as stream of bytes: just convert it to integers and call cmpNumbers. 5. Compare in operation operand types with cmpType in most significant operand first order. 6. Last stage. Check operations for some specific attributes. For example, for Load it would be: 6.1.Load: volatile (as boolean flag) 6.2.Load: alignment (as integer numbers) 6.3.Load: ordering (as underlying enum class value) 6.4.Load: synch-scope (as integer numbers) 6.5.Load: range metadata (as integer ranges) On this stage its better to see the code, since its not more than 10-15 strings for particular instruction, and could change sometimes. Sets \p needToCmpOperands to true if the operands of the instructions still must be compared afterwards. In this case it's already guaranteed that both instructions have the same number of operands.
Declared at: llvm/include/llvm/Transforms/Utils/FunctionComparator.h:277
Parameters
- const llvm::Instruction* L
- const llvm::Instruction* R
- bool& needToCmpOperands
¶int cmpTypes(llvm::Type* TyL,
llvm::Type* TyR) const
int cmpTypes(llvm::Type* TyL,
llvm::Type* TyR) const
Description
cmpType - compares two types, defines total ordering among the types set. Return values: 0 if types are equal, -1 if Left is less than Right, +1 if Left is greater than Right. Description: Comparison is broken onto stages. Like in lexicographical comparison stage coming first has higher priority. On each explanation stage keep in mind total ordering properties. 0. Before comparison we coerce pointer types of 0 address space to integer. We also don't bother with same type at left and right, so just return 0 in this case. 1. If types are of different kind (different type IDs). Return result of type IDs comparison, treating them as numbers. 2. If types are integers, check that they have the same width. If they are vectors, check that they have the same count and subtype. 3. Types have the same ID, so check whether they are one of: * Void * Float * Double * X86_FP80 * FP128 * PPC_FP128 * Label * Metadata We can treat these types as equal whenever their IDs are same. 4. If Left and Right are pointers, return result of address space comparison (numbers comparison). We can treat pointer types of same address space as equal. 5. If types are complex. Then both Left and Right are to be expanded and their element types will be checked with the same way. If we get Res != 0 on some stage, return it. Otherwise return 0. 6. For all other cases put llvm_unreachable.
Declared at: llvm/include/llvm/Transforms/Utils/FunctionComparator.h:320
Parameters
- llvm::Type* TyL
- llvm::Type* TyR
¶int cmpValues(const llvm::Value* L,
const llvm::Value* R) const
int cmpValues(const llvm::Value* L,
const llvm::Value* R) const
Description
Assign or look up previously assigned numbers for the two values, and return whether the numbers are equal. Numbers are assigned in the order visited. Comparison order: Stage 0: Value that is function itself is always greater then others. If left and right values are references to their functions, then they are equal. Stage 1: Constants are greater than non-constants. If both left and right are constants, then the result of cmpConstants is used as cmpValues result. Stage 2: InlineAsm instances are greater than others. If both left and right are InlineAsm instances, InlineAsm* pointers casted to integers and compared as numbers. Stage 3: For all other cases we compare order we meet these values in their functions. If right value was met first during scanning, then left value is greater. In another words, we compare serial numbers, for more details see comments for sn_mapL and sn_mapR.
Declared at: llvm/include/llvm/Transforms/Utils/FunctionComparator.h:246
Parameters
- const llvm::Value* L
- const llvm::Value* R
¶int compare()
int compare()
Description
Test whether the two functions have equivalent behaviour.
Declared at: llvm/include/llvm/Transforms/Utils/FunctionComparator.h:100
¶int compareSignature() const
int compareSignature() const
Description
Compares the signature and other general attributes of the two functions.
Declared at: llvm/include/llvm/Transforms/Utils/FunctionComparator.h:115
¶static llvm::FunctionComparator::FunctionHash
functionHash(llvm::Function&)
static llvm::FunctionComparator::FunctionHash
functionHash(llvm::Function&)
Declared at: llvm/include/llvm/Transforms/Utils/FunctionComparator.h:105