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
private DenseMap<const llvm::Value*, int> sn_mapL
2. Impossibility to use dominance properties of values. If we compare two instruction operands: first is usage of local variable AL from function FL, and second is usage of local variable AR from FR, we could compare their origins and check whether they are defined at the same place. But, we are still not able to compare operands of PHI nodes, since those could be operands from further BBs we didn't scan yet. So it's impossible to use dominance properties in general.
private DenseMap<const llvm::Value*, int> sn_mapR
2. Impossibility to use dominance properties of values. If we compare two instruction operands: first is usage of local variable AL from function FL, and second is usage of local variable AR from FR, we could compare their origins and check whether they are defined at the same place. But, we are still not able to compare operands of PHI nodes, since those could be operands from further BBs we didn't scan yet. So it's impossible to use dominance properties in general.
private llvm::GlobalNumberState* GlobalNumbers

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 cmpAligns(llvm::Align L, llvm::Align R) const
  • private int cmpAttrs(const llvm::AttributeList L, const llvm::AttributeList 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
  • private int cmpGEPs(const llvm::GetElementPtrInst * GEPL, const llvm::GetElementPtrInst * GEPR) const
  • private int cmpGEPs(const llvm::GEPOperator * GEPL, const llvm::GEPOperator * GEPR) const
  • protected int cmpGlobalValues(llvm::GlobalValue * L, llvm::GlobalValue * R) const
  • private int cmpInlineAsm(const llvm::InlineAsm * L, const llvm::InlineAsm * R) const
  • protected int cmpMem(llvm::StringRef L, llvm::StringRef R) const
  • protected int cmpNumbers(uint64_t L, uint64_t R) const
  • private int cmpOperandBundlesSchema(const llvm::CallBase & LCS, const llvm::CallBase & RCS) const
  • protected int cmpOperations(const llvm::Instruction * L, const llvm::Instruction * R, bool & needToCmpOperands) const
  • private int cmpOrderings(llvm::AtomicOrdering L, llvm::AtomicOrdering R) const
  • private int cmpRangeMetadata(const llvm::MDNode * L, const llvm::MDNode * R) 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)

Declared at: llvm/include/llvm/Transforms/Utils/FunctionComparator.h:95

Parameters

const llvm::Function* F1
const llvm::Function* F2
llvm::GlobalNumberState* GN

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

Declared at: llvm/include/llvm/Transforms/Utils/FunctionComparator.h:325

Parameters

const llvm::APFloat& L
const llvm::APFloat& R

int cmpAPInts(const llvm::APInt& L,
              const llvm::APInt& R) const

Declared at: llvm/include/llvm/Transforms/Utils/FunctionComparator.h:324

Parameters

const llvm::APInt& L
const llvm::APInt& R

int cmpAligns(llvm::Align L, llvm::Align R) const

Declared at: llvm/include/llvm/Transforms/Utils/FunctionComparator.h:323

Parameters

llvm::Align L
llvm::Align R

int cmpAttrs(const llvm::AttributeList L,
             const llvm::AttributeList R) const

Declared at: llvm/include/llvm/Transforms/Utils/FunctionComparator.h:334

Parameters

const llvm::AttributeList L
const llvm::AttributeList R

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

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 cmpGEPs(
    const llvm::GetElementPtrInst* GEPL,
    const llvm::GetElementPtrInst* GEPR) const

Declared at: llvm/include/llvm/Transforms/Utils/FunctionComparator.h:347

Parameters

const llvm::GetElementPtrInst* GEPL
const llvm::GetElementPtrInst* GEPR

int cmpGEPs(const llvm::GEPOperator* GEPL,
            const llvm::GEPOperator* GEPR) const

Description

Compare two GEPs for equivalent pointer arithmetic. Parts to be compared for each comparison stage, most significant stage first: 1. Address space. As numbers. 2. Constant offset, (using GEPOperator::accumulateConstantOffset method). 3. Pointer operand type (using cmpType method). 4. Number of operands. 5. Compare operands, using cmpValues method.

Declared at: llvm/include/llvm/Transforms/Utils/FunctionComparator.h:346

Parameters

const llvm::GEPOperator* GEPL
const llvm::GEPOperator* GEPR

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

llvm::GlobalValue* L
llvm::GlobalValue* R

int cmpInlineAsm(const llvm::InlineAsm* L,
                 const llvm::InlineAsm* R) const

Declared at: llvm/include/llvm/Transforms/Utils/FunctionComparator.h:333

Parameters

const llvm::InlineAsm* L
const llvm::InlineAsm* R

int cmpMem(llvm::StringRef L,
           llvm::StringRef R) const

Declared at: llvm/include/llvm/Transforms/Utils/FunctionComparator.h:326

Parameters

llvm::StringRef L
llvm::StringRef R

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 cmpOperandBundlesSchema(
    const llvm::CallBase& LCS,
    const llvm::CallBase& RCS) const

Declared at: llvm/include/llvm/Transforms/Utils/FunctionComparator.h:336

Parameters

const llvm::CallBase& LCS
const llvm::CallBase& RCS

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 cmpOrderings(llvm::AtomicOrdering L,
                 llvm::AtomicOrdering R) const

Declared at: llvm/include/llvm/Transforms/Utils/FunctionComparator.h:332

Parameters

llvm::AtomicOrdering L
llvm::AtomicOrdering R

int cmpRangeMetadata(const llvm::MDNode* L,
                     const llvm::MDNode* R) const

Declared at: llvm/include/llvm/Transforms/Utils/FunctionComparator.h:335

Parameters

const llvm::MDNode* L
const llvm::MDNode* R

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

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()

Description

Test whether the two functions have equivalent behaviour.

Declared at: llvm/include/llvm/Transforms/Utils/FunctionComparator.h:100

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&)

Declared at: llvm/include/llvm/Transforms/Utils/FunctionComparator.h:105

Parameters

llvm::Function&