diff --git a/llvm/include/llvm/IR/Instruction.h b/llvm/include/llvm/IR/Instruction.h --- a/llvm/include/llvm/IR/Instruction.h +++ b/llvm/include/llvm/IR/Instruction.h @@ -675,6 +675,12 @@ /// Determine if one instruction is the same operation as another. bool isSameOperationAs(const Instruction *I, unsigned flags = 0) const; + // This function checks if operands of two instructions are same. + // The Opcode and number of operands for both the instructions need + // to be the same. This method is made to assert false to avoid + // comparisions between instructions whose subclass is not known. + int hasSamePropertiesAs(const Instruction *I) const; + /// Return true if there are any uses of this instruction in blocks other than /// the specified block. Note that PHI nodes are considered to evaluate their /// operands in the corresponding predecessor block. diff --git a/llvm/include/llvm/IR/Instructions.h b/llvm/include/llvm/IR/Instructions.h --- a/llvm/include/llvm/IR/Instructions.h +++ b/llvm/include/llvm/IR/Instructions.h @@ -476,6 +476,11 @@ return isa(V) && classof(cast(V)); } + // This function checks if operands of two FenceInsts are same. + // The Opcode and number of operands for both the instructions need to + // be the same + int hasSamePropertiesAs(const Instruction *I) const; + private: // Shadow Instruction::setInstructionSubclassData with a private forwarding // method so that subclasses cannot accidentally use it. @@ -634,6 +639,11 @@ return isa(V) && classof(cast(V)); } + // This function checks if operands of two AtomicCmpXchgInsts are same. + // The Opcode and number of operands for both the instructions need to + // be the same + int hasSamePropertiesAs(const Instruction *I) const; + private: // Shadow Instruction::setInstructionSubclassData with a private forwarding // method so that subclasses cannot accidentally use it. diff --git a/llvm/lib/IR/Instruction.cpp b/llvm/lib/IR/Instruction.cpp --- a/llvm/lib/IR/Instruction.cpp +++ b/llvm/lib/IR/Instruction.cpp @@ -523,6 +523,13 @@ return haveSameSpecialState(this, I, IgnoreAlignment); } +int Instruction::hasSamePropertiesAs(const Instruction *I) const { + assert( + false && + "Cannot compare properties of instructions whose subclass is not known"); + llvm_unreachable("Properties to compare are not known"); +} + bool Instruction::isUsedOutsideOfBlock(const BasicBlock *BB) const { for (const Use &U : uses()) { // PHI nodes uses values in the corresponding predecessor block. For other diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp --- a/llvm/lib/IR/Instructions.cpp +++ b/llvm/lib/IR/Instructions.cpp @@ -45,6 +45,14 @@ using namespace llvm; +int cmpIntegers(uint64_t L, uint64_t R) { + if (L > R) + return 1; + if (L < R) + return -1; + return 0; +} + //===----------------------------------------------------------------------===// // AllocaInst Class //===----------------------------------------------------------------------===// @@ -1542,6 +1550,30 @@ Init(Ptr, Cmp, NewVal, SuccessOrdering, FailureOrdering, SSID); } +int AtomicCmpXchgInst::hasSamePropertiesAs(const Instruction *I) const { + assert(getOpcode() == I->getOpcode() && + "Cannot check properties of instructions with different Opcodes"); + assert(getNumOperands() = I->getNumOperands() && + "Cannot check properties of instructions " + "with different number of operands"); + if (int Res = cmpIntegers(this->isVolatile(), + cast(I)->isVolatile())) + return Res; + if (int Res = + cmpIntegers(this->isWeak(), cast(I)->isWeak())) + return Res; + if (int Res = + cmpIntegers(int(this->getSuccessOrdering()), + int(cast(I)->getSuccessOrdering()))) + return Res; + if (int Res = + cmpIntegers(int(this->getFailureOrdering()), + int(cast(I)->getFailureOrdering()))) + return Res; + return cmpIntegers(this->getSyncScopeID(), + cast(I)->getSyncScopeID()); +} + //===----------------------------------------------------------------------===// // AtomicRMWInst Implementation //===----------------------------------------------------------------------===// @@ -1636,13 +1668,25 @@ } FenceInst::FenceInst(LLVMContext &C, AtomicOrdering Ordering, - SyncScope::ID SSID, - BasicBlock *InsertAtEnd) - : Instruction(Type::getVoidTy(C), Fence, nullptr, 0, InsertAtEnd) { + SyncScope::ID SSID, BasicBlock *InsertAtEnd) + : Instruction(Type::getVoidTy(C), Fence, nullptr, 0, InsertAtEnd) { setOrdering(Ordering); setSyncScopeID(SSID); } +int FenceInst::hasSamePropertiesAs(const Instruction *I) const { + assert(getOpcode() == I->getOpcode() && + "Cannot check properties of instructions with different Opcodes"); + assert(getNumOperands() = I->getNumOperands() && + "Cannot check properties of instructions " + "with different number of operands"); + if (int Res = cmpIntegers(int(this->getOrdering()), + int(cast(I)->getOrdering()))) + return Res; + return cmpIntegers(this->getSyncScopeID(), + cast(I)->getSyncScopeID()); +} + //===----------------------------------------------------------------------===// // GetElementPtrInst Implementation //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Transforms/Utils/FunctionComparator.cpp b/llvm/lib/Transforms/Utils/FunctionComparator.cpp --- a/llvm/lib/Transforms/Utils/FunctionComparator.cpp +++ b/llvm/lib/Transforms/Utils/FunctionComparator.cpp @@ -619,29 +619,10 @@ } } if (const FenceInst *FI = dyn_cast(L)) { - if (int Res = - cmpOrderings(FI->getOrdering(), cast(R)->getOrdering())) - return Res; - return cmpNumbers(FI->getSyncScopeID(), - cast(R)->getSyncScopeID()); + return FI->hasSamePropertiesAs(R); } if (const AtomicCmpXchgInst *CXI = dyn_cast(L)) { - if (int Res = cmpNumbers(CXI->isVolatile(), - cast(R)->isVolatile())) - return Res; - if (int Res = - cmpNumbers(CXI->isWeak(), cast(R)->isWeak())) - return Res; - if (int Res = - cmpOrderings(CXI->getSuccessOrdering(), - cast(R)->getSuccessOrdering())) - return Res; - if (int Res = - cmpOrderings(CXI->getFailureOrdering(), - cast(R)->getFailureOrdering())) - return Res; - return cmpNumbers(CXI->getSyncScopeID(), - cast(R)->getSyncScopeID()); + return CXI->hasSamePropertiesAs(R); } if (const AtomicRMWInst *RMWI = dyn_cast(L)) { if (int Res = cmpNumbers(RMWI->getOperation(),