LLVM 19.0.0git
Public Member Functions | Protected Member Functions | Protected Attributes | List of all members
llvm::FunctionComparator Class Reference

FunctionComparator - Compares two functions to determine whether or not they will generate machine code with the same behaviour. More...

#include "llvm/Transforms/Utils/FunctionComparator.h"

Public Member Functions

 FunctionComparator (const Function *F1, const Function *F2, GlobalNumberState *GN)
int compare ()
 Test whether the two functions have equivalent behaviour.

Protected Member Functions

void beginCompare ()
 Start the comparison.
int compareSignature () const
 Compares the signature and other general attributes of the two functions.
int cmpBasicBlocks (const BasicBlock *BBL, const BasicBlock *BBR) const
 Test whether two basic blocks have equivalent behaviour.
int cmpConstants (const Constant *L, const Constant *R) const
 Constants comparison.
int cmpGlobalValues (GlobalValue *L, GlobalValue *R) const
 Compares two global values by number.
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 equal.
int cmpOperations (const Instruction *L, const Instruction *R, bool &needToCmpOperands) const
 Compare two Instructions for equivalence, similar to Instruction::isSameOperationAs.
int cmpTypes (Type *TyL, Type *TyR) const
 cmpType - compares two types, defines total ordering among the types set.
int cmpNumbers (uint64_t L, uint64_t R) const
int cmpAligns (Align L, Align R) const
int cmpAPInts (const APInt &L, const APInt &R) const
int cmpAPFloats (const APFloat &L, const APFloat &R) const
int cmpMem (StringRef L, StringRef R) const

Protected Attributes

const FunctionFnL
const FunctionFnR

Detailed 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).

Definition at line 93 of file FunctionComparator.h.

Constructor & Destructor Documentation

◆ FunctionComparator()

llvm::FunctionComparator::FunctionComparator ( const Function F1,
const Function F2,
GlobalNumberState GN 

Definition at line 95 of file FunctionComparator.h.

Member Function Documentation

◆ beginCompare()

void llvm::FunctionComparator::beginCompare ( )

Start the comparison.

Definition at line 104 of file FunctionComparator.h.

Referenced by compare().

◆ cmpAligns()

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

Definition at line 61 of file FunctionComparator.cpp.

Referenced by cmpOperations().

◆ cmpAPFloats()

int FunctionComparator::cmpAPFloats ( const APFloat L,
const APFloat R 
) const

◆ cmpAPInts()

int FunctionComparator::cmpAPInts ( const APInt L,
const APInt R 
) const

Definition at line 77 of file FunctionComparator.cpp.

References cmpNumbers().

Referenced by cmpAPFloats(), and cmpConstants().

◆ cmpBasicBlocks()

int FunctionComparator::cmpBasicBlocks ( const BasicBlock BBL,
const BasicBlock BBR 
) const

Test whether two basic blocks have equivalent behaviour.

Definition at line 915 of file FunctionComparator.cpp.

References assert(), llvm::BasicBlock::begin(), cmpOperations(), cmpTypes(), cmpValues(), llvm::BasicBlock::end(), and llvm::Value::getType().

Referenced by compare().

◆ cmpConstants()

int FunctionComparator::cmpConstants ( const Constant L,
const Constant R 
) const

Constants comparison.

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:

  1. 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.
  2. 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.

  1. Check whether type of L constant could be losslessly bitcasted to R type.
  2. Compare constant contents. For more details see declaration comments.

Definition at line 274 of file FunctionComparator.cpp.

References assert(), cmpAPFloats(), cmpAPInts(), cmpConstants(), cmpGlobalValues(), cmpMem(), cmpNumbers(), cmpTypes(), cmpValues(), llvm::dbgs(), F, FnL, FnR, llvm::PointerType::getAddressSpace(), llvm::BlockAddress::getBasicBlock(), llvm::BlockAddress::getFunction(), llvm::User::getNumOperands(), llvm::ConstantExpr::getOpcode(), llvm::User::getOperand(), llvm::ConstantExpr::getPredicate(), llvm::Type::isFirstClassType(), LLVM_DEBUG, llvm_unreachable, OBOL, and RA.

Referenced by cmpConstants(), and cmpValues().

◆ cmpGlobalValues()

int FunctionComparator::cmpGlobalValues ( GlobalValue L,
GlobalValue R 
) const

Compares two global values by number.

Uses the GlobalNumbersState to identify the same gobals across function calls.

Definition at line 516 of file FunctionComparator.cpp.

References cmpNumbers(), and llvm::GlobalNumberState::getNumber().

Referenced by cmpConstants().

◆ cmpMem()

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

Definition at line 106 of file FunctionComparator.cpp.

References cmpNumbers().

Referenced by cmpConstants(), and compareSignature().

◆ cmpNumbers()

int FunctionComparator::cmpNumbers ( uint64_t  L,
uint64_t  R 
) const

◆ cmpOperations()

int FunctionComparator::cmpOperations ( const Instruction L,
const Instruction R,
bool needToCmpOperands 
) const

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 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.

Definition at line 625 of file FunctionComparator.cpp.

References cmpAligns(), cmpNumbers(), cmpTypes(), cmpValues(), llvm::PHINode::getIncomingBlock(), llvm::GetElementPtrInst::getPointerOperand(), and llvm::ArrayRef< T >::size().

Referenced by cmpBasicBlocks().

◆ cmpTypes()

int FunctionComparator::cmpTypes ( Type TyL,
Type TyR 
) const

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.
  1. 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.
  2. 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.
  3. For all other cases put llvm_unreachable.

See method declaration comments for more details.

Definition at line 525 of file FunctionComparator.cpp.

References llvm::Type::ArrayTyID, assert(), cmpNumbers(), cmpTypes(), DL, llvm::Type::DoubleTyID, llvm::Type::FixedVectorTyID, llvm::Type::FloatTyID, FnL, llvm::Type::FP128TyID, llvm::Type::FunctionTyID, llvm::PointerType::getAddressSpace(), getBitWidth(), llvm::Module::getDataLayout(), llvm::StructType::getElementType(), llvm::StructType::getNumElements(), llvm::FunctionType::getNumParams(), llvm::FunctionType::getParamType(), llvm::GlobalValue::getParent(), llvm::FunctionType::getReturnType(), llvm::Type::getTypeID(), llvm::Type::IntegerTyID, llvm::StructType::isPacked(), llvm::FunctionType::isVarArg(), llvm::Type::LabelTyID, llvm_unreachable, llvm::Type::MetadataTyID, llvm::Type::PointerTyID, llvm::Type::PPC_FP128TyID, llvm::Type::ScalableVectorTyID, llvm::Type::StructTyID, llvm::Type::TokenTyID, llvm::Type::VoidTyID, and llvm::Type::X86_FP80TyID.

Referenced by cmpBasicBlocks(), cmpConstants(), cmpOperations(), cmpTypes(), and compareSignature().

◆ cmpValues()

int FunctionComparator::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 equal.

Compare two values used by the two functions under pair-wise comparison.

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.

If this is the first time the values are seen, they're added to the mapping so that we will detect mismatches on next use. See comments in declaration for more details.

Definition at line 857 of file FunctionComparator.cpp.

References cmpConstants(), cmpNumbers(), FnL, FnR, and llvm::MetadataAsValue::getMetadata().

Referenced by cmpBasicBlocks(), cmpConstants(), cmpOperations(), compare(), and compareSignature().

◆ compare()

int FunctionComparator::compare ( )

◆ compareSignature()

int FunctionComparator::compareSignature ( ) const

Member Data Documentation

◆ FnL

const Function* llvm::FunctionComparator::FnL

Definition at line 324 of file FunctionComparator.h.

Referenced by cmpConstants(), cmpTypes(), cmpValues(), compare(), and compareSignature().

◆ FnR

const Function * llvm::FunctionComparator::FnR

Definition at line 324 of file FunctionComparator.h.

Referenced by cmpConstants(), cmpValues(), compare(), and compareSignature().

The documentation for this class was generated from the following files: