diff --git a/include/llvm/InstrTypes.h b/include/llvm/InstrTypes.h index 7ce43007311..627aad43040 100644 --- a/include/llvm/InstrTypes.h +++ b/include/llvm/InstrTypes.h @@ -243,6 +243,91 @@ public: } }; +//===----------------------------------------------------------------------===// +// CmpInst Class +//===----------------------------------------------------------------------===// + +/// This class is the base class for the comparison instructions. +/// @brief Abstract base class of comparison instructions. +class CmpInst: public Instruction { + CmpInst(); // do not implement +protected: + CmpInst(Instruction::OtherOps op, unsigned short pred, Value *LHS, Value *RHS, + const std::string &Name = "", Instruction *InsertBefore = 0); + + CmpInst(Instruction::OtherOps op, unsigned short pred, Value *LHS, Value *RHS, + const std::string &Name, BasicBlock *InsertAtEnd); + + Use Ops[2]; // CmpInst instructions always have 2 operands, optimize + +public: + /// Construct a compare instruction, given the opcode, the predicate and + /// the two operands. Optionally (if InstBefore is specified) insert the + /// instruction into a BasicBlock right before the specified instruction. + /// The specified Instruction is allowed to be a dereferenced end iterator. + /// @brief Create a CmpInst + static CmpInst *create(OtherOps Op, unsigned short predicate, Value *S1, + Value *S2, const std::string &Name = "", + Instruction *InsertBefore = 0); + + /// Construct a compare instruction, given the opcode, the predicate and the + /// two operands. Also automatically insert this instruction to the end of + /// the BasicBlock specified. + /// @brief Create a CmpInst + static CmpInst *create(OtherOps Op, unsigned short predicate, Value *S1, + Value *S2, const std::string &Name, + BasicBlock *InsertAtEnd); + + /// @brief Implement superclass method. + virtual CmpInst *clone() const; + + /// The predicate for CmpInst is defined by the subclasses but stored in + /// the SubclassData field (see Value.h). We allow it to be fetched here + /// as the predicate but there is no enum type for it, just the raw unsigned + /// short. This facilitates comparison of CmpInst instances without delving + /// into the subclasses since predicate values are distinct between the + /// CmpInst subclasses. + /// @brief Return the predicate for this instruction. + unsigned short getPredicate() const { + return SubclassData; + } + + /// @brief Provide more efficient getOperand methods. + Value *getOperand(unsigned i) const { + assert(i < 2 && "getOperand() out of range!"); + return Ops[i]; + } + void setOperand(unsigned i, Value *Val) { + assert(i < 2 && "setOperand() out of range!"); + Ops[i] = Val; + } + + /// @brief CmpInst instructions always have 2 operands. + unsigned getNumOperands() const { return 2; } + + /// This is just a convenience that dispatches to the subclasses. + /// @brief Swap the operands. + void swapOperands(); + + /// This is just a convenience that dispatches to the subclasses. + /// @brief Determine if this CmpInst is commutative. + bool isCommutative(); + + /// This is just a convenience that dispatches to the subclasses. + /// @brief Determine if this is an equals/not equals predicate. + bool isEquality(); + + /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const CmpInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::ICmp || + I->getOpcode() == Instruction::FCmp; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + } // End llvm namespace #endif diff --git a/include/llvm/Instruction.def b/include/llvm/Instruction.def index 96279b05a2a..55c668ab1a6 100644 --- a/include/llvm/Instruction.def +++ b/include/llvm/Instruction.def @@ -126,20 +126,22 @@ HANDLE_MEMORY_INST(30, GetElementPtr, GetElementPtrInst) // Other operators... FIRST_OTHER_INST(31) -HANDLE_OTHER_INST(31, PHI , PHINode ) // PHI node instruction -HANDLE_OTHER_INST(32, Cast , CastInst ) // Type cast -HANDLE_OTHER_INST(33, Call , CallInst ) // Call a function -HANDLE_OTHER_INST(34, Shl , ShiftInst ) // Shift Left operations (logical) -HANDLE_OTHER_INST(35, LShr , ShiftInst ) // Logical Shift right (unsigned) -HANDLE_OTHER_INST(36, AShr , ShiftInst ) // Arithmetic shift right (signed) -HANDLE_OTHER_INST(37, Select , SelectInst ) // select instruction -HANDLE_OTHER_INST(38, UserOp1, Instruction) // May be used internally in a pass -HANDLE_OTHER_INST(39, UserOp2, Instruction) // Internal to passes only -HANDLE_OTHER_INST(40, VAArg , VAArgInst ) // vaarg instruction -HANDLE_OTHER_INST(41, ExtractElement, ExtractElementInst)// extract from vector. -HANDLE_OTHER_INST(42, InsertElement, InsertElementInst) // insert into vector -HANDLE_OTHER_INST(43, ShuffleVector, ShuffleVectorInst) // shuffle two vectors. - LAST_OTHER_INST(43) +HANDLE_OTHER_INST(31, ICmp , ICmpInst ) // Integer comparison instruction +HANDLE_OTHER_INST(32, FCmp , FCmpInst ) // Floating point comparison instr. +HANDLE_OTHER_INST(33, PHI , PHINode ) // PHI node instruction +HANDLE_OTHER_INST(34, Cast , CastInst ) // Type cast +HANDLE_OTHER_INST(35, Call , CallInst ) // Call a function +HANDLE_OTHER_INST(36, Shl , ShiftInst ) // Shift Left operations (logical) +HANDLE_OTHER_INST(37, LShr , ShiftInst ) // Logical Shift right (unsigned) +HANDLE_OTHER_INST(38, AShr , ShiftInst ) // Arithmetic shift right (signed) +HANDLE_OTHER_INST(39, Select , SelectInst ) // select instruction +HANDLE_OTHER_INST(40, UserOp1, Instruction) // May be used internally in a pass +HANDLE_OTHER_INST(41, UserOp2, Instruction) // Internal to passes only +HANDLE_OTHER_INST(42, VAArg , VAArgInst ) // vaarg instruction +HANDLE_OTHER_INST(43, ExtractElement, ExtractElementInst)// extract from vector. +HANDLE_OTHER_INST(44, InsertElement, InsertElementInst) // insert into vector +HANDLE_OTHER_INST(45, ShuffleVector, ShuffleVectorInst) // shuffle two vectors. + LAST_OTHER_INST(45) #undef FIRST_TERM_INST #undef HANDLE_TERM_INST diff --git a/include/llvm/Instructions.h b/include/llvm/Instructions.h index d887c527e5e..8046567fdef 100644 --- a/include/llvm/Instructions.h +++ b/include/llvm/Instructions.h @@ -414,6 +414,239 @@ public: } }; +//===----------------------------------------------------------------------===// +// ICmpInst Class +//===----------------------------------------------------------------------===// + +/// This instruction compares its operands according to the predicate given +/// to the constructor. It only operates on integers, pointers, or packed +/// vectors of integrals. The two operands must be the same type. +/// @brief Represent an integer comparison operator. +class ICmpInst: public CmpInst { +public: + /// This enumeration lists the possible predicates for the ICmpInst. The + /// values in the range 0-31 are reserved for FCmpInst while values in the + /// range 32-64 are reserved for ICmpInst. This is necessary to ensure the + /// predicate values are not overlapping between the classes. + enum Predicate { + ICMP_EQ = 32, ///< equal + ICMP_NE = 33, ///< not equal + ICMP_UGT = 34, ///< unsigned greater than + ICMP_UGE = 35, ///< unsigned greater or equal + ICMP_ULT = 36, ///< unsigned less than + ICMP_ULE = 37, ///< unsigned less or equal + ICMP_SGT = 38, ///< signed greater than + ICMP_SGE = 39, ///< signed greater or equal + ICMP_SLT = 40, ///< signed less than + ICMP_SLE = 41, ///< signed less or equal + FIRST_ICMP_PREDICATE = ICMP_EQ, + LAST_ICMP_PREDICATE = ICMP_SLE + }; + + /// @brief Constructor with insert-before-instruction semantics. + ICmpInst( + Predicate pred, ///< The predicate to use for the comparison + Value *LHS, ///< The left-hand-side of the expression + Value *RHS, ///< The right-hand-side of the expression + const std::string &Name = "", ///< Name of the instruction + Instruction *InsertBefore = 0 ///< Where to insert + ) : CmpInst(Instruction::ICmp, pred, LHS, RHS, Name, InsertBefore) { + } + + /// @brief Constructor with insert-at-block-end semantics. + ICmpInst( + Predicate pred, ///< The predicate to use for the comparison + Value *LHS, ///< The left-hand-side of the expression + Value *RHS, ///< The right-hand-side of the expression + const std::string &Name, ///< Name of the instruction + BasicBlock *InsertAtEnd ///< Block to insert into. + ) : CmpInst(Instruction::ICmp, pred, LHS, RHS, Name, InsertAtEnd) { + } + + /// @brief Return the predicate for this instruction. + Predicate getPredicate() const { return Predicate(SubclassData); } + + /// For example, EQ -> NE, UGT -> ULE, SLT -> SGE, etc. + /// @returns the inverse predicate for the instruction's current predicate. + /// @brief Return the inverse of the instruction's predicate. + Predicate getInversePredicate() const { + return getInversePredicate(getPredicate()); + } + + /// For example, EQ -> NE, UGT -> ULE, SLT -> SGE, etc. + /// @returns the inverse predicate for predicate provided in \p pred. + /// @brief Return the inverse of a given predicate + static Predicate getInversePredicate(Predicate pred); + + /// For example, EQ->EQ, SLE->SGE, ULT->UGT, etc. + /// @returns the predicate that would be the result of exchanging the two + /// operands of the ICmpInst instruction without changing the result + /// produced. + /// @brief Return the predicate as if the operands were swapped + Predicate getSwappedPredicate() const { + return getSwappedPredicate(getPredicate()); + } + + /// This is a static version that you can use without an instruction + /// available. + /// @brief Return the predicate as if the operands were swapped. + static Predicate getSwappedPredicate(Predicate Opcode); + + /// This also tests for commutativity. If isEquality() returns true then + /// the predicate is also commutative. Only the equality predicates are + /// commutative. + /// @returns true if the predicate of this instruction is EQ or NE. + /// @brief Determine if this is an equality predicate. + bool isEquality() const { + return SubclassData == ICMP_EQ || SubclassData == ICMP_NE; + } + bool isCommutative() const { return isEquality(); } + + /// @returns true if the predicate is relational (not EQ or NE). + /// @brief Determine if this a relational predicate. + bool isRelational() const { + return !isEquality(); + } + + /// Exchange the two operands to this instruction in such a way that it does + /// not modify the semantics of the instruction. The predicate value may be + /// changed to retain the same result if the predicate is order dependent + /// (e.g. ult). + /// @brief Swap operands and adjust predicate. + void swapOperands() { + SubclassData = getSwappedPredicate(); + std::swap(Ops[0], Ops[1]); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ICmpInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::ICmp; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +//===----------------------------------------------------------------------===// +// FCmpInst Class +//===----------------------------------------------------------------------===// + +/// This instruction compares its operands according to the predicate given +/// to the constructor. It only operates on floating point values or packed +/// vectors of floating point values. The operands must be identical types. +/// @brief Represents a floating point comparison operator. +class FCmpInst: public CmpInst { +public: + /// This enumeration lists the possible predicates for the FCmpInst. Values + /// in the range 0-31 are reserved for FCmpInst. + enum Predicate { + // Opcode U L G E Intuitive operation + FCMP_FALSE = 0, ///< 0 0 0 0 Always false (always folded) + FCMP_OEQ = 1, ///< 0 0 0 1 True if ordered and equal + FCMP_OGT = 2, ///< 0 0 1 0 True if ordered and greater than + FCMP_OGE = 3, ///< 0 0 1 1 True if ordered and greater than or equal + FCMP_OLT = 4, ///< 0 1 0 0 True if ordered and less than + FCMP_OLE = 5, ///< 0 1 0 1 True if ordered and less than or equal + FCMP_ONE = 6, ///< 0 1 1 0 True if ordered and operands are unequal + FCMP_ORD = 7, ///< 0 1 1 1 True if ordered (no nans) + FCMP_UNO = 8, ///< 1 0 0 0 True if unordered: isnan(X) | isnan(Y) + FCMP_UEQ = 9, ///< 1 0 0 1 True if unordered or equal + FCMP_UGT =10, ///< 1 0 1 0 True if unordered or greater than + FCMP_UGE =11, ///< 1 0 1 1 True if unordered, greater than, or equal + FCMP_ULT =12, ///< 1 1 0 0 True if unordered or less than + FCMP_ULE =13, ///< 1 1 0 1 True if unordered, less than, or equal + FCMP_UNE =14, ///< 1 1 1 0 True if unordered or not equal + FCMP_TRUE =15, ///< 1 1 1 1 Always true (always folded) + FIRST_FCMP_PREDICATE = FCMP_FALSE, + LAST_FCMP_PREDICATE = FCMP_TRUE + }; + + /// @brief Constructor with insert-before-instruction semantics. + FCmpInst( + Predicate pred, ///< The predicate to use for the comparison + Value *LHS, ///< The left-hand-side of the expression + Value *RHS, ///< The right-hand-side of the expression + const std::string &Name = "", ///< Name of the instruction + Instruction *InsertBefore = 0 ///< Where to insert + ) : CmpInst(Instruction::FCmp, pred, LHS, RHS, Name, InsertBefore) { + } + + /// @brief Constructor with insert-at-block-end semantics. + FCmpInst( + Predicate pred, ///< The predicate to use for the comparison + Value *LHS, ///< The left-hand-side of the expression + Value *RHS, ///< The right-hand-side of the expression + const std::string &Name, ///< Name of the instruction + BasicBlock *InsertAtEnd ///< Block to insert into. + ) : CmpInst(Instruction::FCmp, pred, LHS, RHS, Name, InsertAtEnd) { + } + + /// @brief Return the predicate for this instruction. + Predicate getPredicate() const { return Predicate(SubclassData); } + + /// For example, OEQ -> UNE, UGT -> OLE, OLT -> UGE, etc. + /// @returns the inverse predicate for the instructions current predicate. + /// @brief Return the inverse of the predicate + Predicate getInversePredicate() const { + return getInversePredicate(getPredicate()); + } + + /// For example, OEQ -> UNE, UGT -> OLE, OLT -> UGE, etc. + /// @returns the inverse predicate for \p pred. + /// @brief Return the inverse of a given predicate + static Predicate getInversePredicate(Predicate pred); + + /// For example, OEQ->OEQ, ULE->UGE, OLT->OGT, etc. + /// @returns the predicate that would be the result of exchanging the two + /// operands of the ICmpInst instruction without changing the result + /// produced. + /// @brief Return the predicate as if the operands were swapped + Predicate getSwappedPredicate() const { + return getSwappedPredicate(getPredicate()); + } + + /// This is a static version that you can use without an instruction + /// available. + /// @brief Return the predicate as if the operands were swapped. + static Predicate getSwappedPredicate(Predicate Opcode); + + /// This also tests for commutativity. If isEquality() returns true then + /// the predicate is also commutative. Only the equality predicates are + /// commutative. + /// @returns true if the predicate of this instruction is EQ or NE. + /// @brief Determine if this is an equality predicate. + bool isEquality() const { + return SubclassData == FCMP_OEQ || SubclassData == FCMP_ONE || + SubclassData == FCMP_UEQ || SubclassData == FCMP_UNE; + } + bool isCommutative() const { return isEquality(); } + + /// @returns true if the predicate is relational (not EQ or NE). + /// @brief Determine if this a relational predicate. + bool isRelational() const { return !isEquality(); } + + /// Exchange the two operands to this instruction in such a way that it does + /// not modify the semantics of the instruction. The predicate value may be + /// changed to retain the same result if the predicate is order dependent + /// (e.g. ult). + /// @brief Swap operands and adjust predicate. + void swapOperands() { + SubclassData = getSwappedPredicate(); + std::swap(Ops[0], Ops[1]); + } + + /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const FCmpInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::FCmp; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + + //===----------------------------------------------------------------------===// // SetCondInst Class //===----------------------------------------------------------------------===// diff --git a/include/llvm/Support/InstVisitor.h b/include/llvm/Support/InstVisitor.h index ca45d4c5d6d..713980a86be 100644 --- a/include/llvm/Support/InstVisitor.h +++ b/include/llvm/Support/InstVisitor.h @@ -169,6 +169,8 @@ public: RetTy visitUnwindInst(UnwindInst &I) { DELEGATE(TerminatorInst);} RetTy visitUnreachableInst(UnreachableInst &I) { DELEGATE(TerminatorInst);} RetTy visitSetCondInst(SetCondInst &I) { DELEGATE(BinaryOperator);} + RetTy visitICmpInst(ICmpInst &I) { DELEGATE(CmpInst);} + RetTy visitFCmpInst(FCmpInst &I) { DELEGATE(CmpInst);} RetTy visitMallocInst(MallocInst &I) { DELEGATE(AllocationInst);} RetTy visitAllocaInst(AllocaInst &I) { DELEGATE(AllocationInst);} RetTy visitFreeInst(FreeInst &I) { DELEGATE(Instruction); } @@ -192,6 +194,7 @@ public: RetTy visitTerminatorInst(TerminatorInst &I) { DELEGATE(Instruction); } RetTy visitBinaryOperator(BinaryOperator &I) { DELEGATE(Instruction); } RetTy visitAllocationInst(AllocationInst &I) { DELEGATE(Instruction); } + RetTy visitCmpInst(CmpInst &I) { DELEGATE(Instruction); } // If the user wants a 'default' case, they can choose to override this // function. If this function is not overloaded in the users subclass, then diff --git a/lib/Analysis/ValueNumbering.cpp b/lib/Analysis/ValueNumbering.cpp index 0224a0132fd..03b9f6b3eae 100644 --- a/lib/Analysis/ValueNumbering.cpp +++ b/lib/Analysis/ValueNumbering.cpp @@ -75,6 +75,7 @@ namespace { void visitCastInst(CastInst &I); void visitGetElementPtrInst(GetElementPtrInst &I); + void visitCmpInst(CmpInst &I); void handleBinaryInst(Instruction &I); void visitBinaryOperator(Instruction &I) { handleBinaryInst(I); } @@ -124,6 +125,28 @@ void BVNImpl::visitCastInst(CastInst &CI) { } } +void BVNImpl::visitCmpInst(CmpInst &CI1) { + Value *LHS = CI1.getOperand(0); + for (Value::use_iterator UI = LHS->use_begin(), UE = LHS->use_end(); + UI != UE; ++UI) + if (CmpInst *CI2 = dyn_cast(*UI)) + // Check to see if this compare instruction is not CI, but same opcode, + // same predicate, and in the same function. + if (CI2 != &CI1 && CI2->getOpcode() == CI1.getOpcode() && + CI2->getPredicate() == CI1.getPredicate() && + CI2->getParent()->getParent() == CI1.getParent()->getParent()) + // If the operands are the same + if ((CI2->getOperand(0) == CI1.getOperand(0) && + CI2->getOperand(1) == CI1.getOperand(1)) || + // Or the compare is commutative and the operands are reversed + (CI1.isCommutative() && + CI2->getOperand(0) == CI1.getOperand(1) && + CI2->getOperand(1) == CI1.getOperand(0))) + // Then the instructiosn are identical, add to list. + RetVals.push_back(CI2); +} + + // isIdenticalBinaryInst - Return true if the two binary instructions are // identical. diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 11347f9e584..8b9fa863296 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -541,6 +541,8 @@ public: void visitShl(User &I) { visitShift(I, ISD::SHL); } void visitLShr(User &I) { visitShift(I, ISD::SRL); } void visitAShr(User &I) { visitShift(I, ISD::SRA); } + void visitICmp(User &I); + void visitFCmp(User &I); void visitSetCC(User &I, ISD::CondCode SignedOpc, ISD::CondCode UnsignedOpc, ISD::CondCode FPOpc); void visitSetEQ(User &I) { visitSetCC(I, ISD::SETEQ, ISD::SETEQ, @@ -1442,6 +1444,60 @@ void SelectionDAGLowering::visitShift(User &I, unsigned Opcode) { setValue(&I, DAG.getNode(Opcode, Op1.getValueType(), Op1, Op2)); } +void SelectionDAGLowering::visitICmp(User &I) { + ICmpInst *IC = cast(&I); + SDOperand Op1 = getValue(IC->getOperand(0)); + SDOperand Op2 = getValue(IC->getOperand(1)); + ISD::CondCode Opcode; + switch (IC->getPredicate()) { + case ICmpInst::ICMP_EQ : Opcode = ISD::SETEQ; break; + case ICmpInst::ICMP_NE : Opcode = ISD::SETNE; break; + case ICmpInst::ICMP_UGT : Opcode = ISD::SETUGT; break; + case ICmpInst::ICMP_UGE : Opcode = ISD::SETUGE; break; + case ICmpInst::ICMP_ULT : Opcode = ISD::SETULT; break; + case ICmpInst::ICMP_ULE : Opcode = ISD::SETULE; break; + case ICmpInst::ICMP_SGT : Opcode = ISD::SETGT; break; + case ICmpInst::ICMP_SGE : Opcode = ISD::SETGE; break; + case ICmpInst::ICMP_SLT : Opcode = ISD::SETLT; break; + case ICmpInst::ICMP_SLE : Opcode = ISD::SETLE; break; + default: + assert(!"Invalid ICmp predicate value"); + Opcode = ISD::SETEQ; + break; + } + setValue(&I, DAG.getSetCC(MVT::i1, Op1, Op2, Opcode)); +} + +void SelectionDAGLowering::visitFCmp(User &I) { + FCmpInst *FC = cast(&I); + SDOperand Op1 = getValue(FC->getOperand(0)); + SDOperand Op2 = getValue(FC->getOperand(1)); + ISD::CondCode Opcode; + switch (FC->getPredicate()) { + case FCmpInst::FCMP_FALSE : Opcode = ISD::SETFALSE; + case FCmpInst::FCMP_OEQ : Opcode = ISD::SETOEQ; + case FCmpInst::FCMP_OGT : Opcode = ISD::SETOGT; + case FCmpInst::FCMP_OGE : Opcode = ISD::SETOGE; + case FCmpInst::FCMP_OLT : Opcode = ISD::SETOLT; + case FCmpInst::FCMP_OLE : Opcode = ISD::SETOLE; + case FCmpInst::FCMP_ONE : Opcode = ISD::SETONE; + case FCmpInst::FCMP_ORD : Opcode = ISD::SETO; + case FCmpInst::FCMP_UNO : Opcode = ISD::SETUO; + case FCmpInst::FCMP_UEQ : Opcode = ISD::SETUEQ; + case FCmpInst::FCMP_UGT : Opcode = ISD::SETUGT; + case FCmpInst::FCMP_UGE : Opcode = ISD::SETUGE; + case FCmpInst::FCMP_ULT : Opcode = ISD::SETULT; + case FCmpInst::FCMP_ULE : Opcode = ISD::SETULE; + case FCmpInst::FCMP_UNE : Opcode = ISD::SETUNE; + case FCmpInst::FCMP_TRUE : Opcode = ISD::SETTRUE; + default: + assert(!"Invalid FCmp predicate value"); + Opcode = ISD::SETFALSE; + break; + } + setValue(&I, DAG.getSetCC(MVT::i1, Op1, Op2, Opcode)); +} + void SelectionDAGLowering::visitSetCC(User &I,ISD::CondCode SignedOpcode, ISD::CondCode UnsignedOpcode, ISD::CondCode FPOpcode) { diff --git a/lib/VMCore/Instruction.cpp b/lib/VMCore/Instruction.cpp index 70b375902dc..64a9e12f82d 100644 --- a/lib/VMCore/Instruction.cpp +++ b/lib/VMCore/Instruction.cpp @@ -11,10 +11,10 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Type.h" #include "llvm/Instructions.h" #include "llvm/Function.h" #include "llvm/SymbolTable.h" -#include "llvm/Type.h" #include "llvm/Support/LeakDetector.h" using namespace llvm; diff --git a/lib/VMCore/Instructions.cpp b/lib/VMCore/Instructions.cpp index 5ed07cfb7f7..f559c6324e4 100644 --- a/lib/VMCore/Instructions.cpp +++ b/lib/VMCore/Instructions.cpp @@ -1290,6 +1290,197 @@ Instruction::BinaryOps SetCondInst::getSwappedCondition(BinaryOps Opcode) { } } + +//===----------------------------------------------------------------------===// +// CmpInst Classes +//===----------------------------------------------------------------------===// + +CmpInst::CmpInst(OtherOps op, unsigned short predicate, Value *LHS, Value *RHS, + const std::string &Name, Instruction *InsertBefore) + : Instruction(Type::BoolTy, op, Ops, 2, Name, InsertBefore) { + Ops[0].init(LHS, this); + Ops[1].init(RHS, this); + SubclassData = predicate; + if (op == Instruction::ICmp) { + assert(predicate >= ICmpInst::FIRST_ICMP_PREDICATE && + predicate <= ICmpInst::LAST_ICMP_PREDICATE && + "Invalid ICmp predicate value"); + const Type* Op0Ty = getOperand(0)->getType(); + const Type* Op1Ty = getOperand(1)->getType(); + assert(Op0Ty == Op1Ty && + "Both operands to ICmp instruction are not of the same type!"); + // Check that the operands are the right type + assert(Op0Ty->isIntegral() || Op0Ty->getTypeID() == Type::PointerTyID || + (isa(Op0Ty) && + cast(Op0Ty)->getElementType()->isIntegral()) && + "Invalid operand types for ICmp instruction"); + return; + } + assert(op == Instruction::FCmp && "Invalid CmpInst opcode"); + assert(predicate <= FCmpInst::LAST_FCMP_PREDICATE && + "Invalid FCmp predicate value"); + const Type* Op0Ty = getOperand(0)->getType(); + const Type* Op1Ty = getOperand(1)->getType(); + assert(Op0Ty == Op1Ty && + "Both operands to FCmp instruction are not of the same type!"); + // Check that the operands are the right type + assert(Op0Ty->isFloatingPoint() || (isa(Op0Ty) && + cast(Op0Ty)->getElementType()->isFloatingPoint()) && + "Invalid operand types for FCmp instruction"); +} + +CmpInst::CmpInst(OtherOps op, unsigned short predicate, Value *LHS, Value *RHS, + const std::string &Name, BasicBlock *InsertAtEnd) + : Instruction(Type::BoolTy, op, Ops, 2, Name, InsertAtEnd) { + Ops[0].init(LHS, this); + Ops[1].init(RHS, this); + SubclassData = predicate; + if (op == Instruction::ICmp) { + assert(predicate >= ICmpInst::FIRST_ICMP_PREDICATE && + predicate <= ICmpInst::LAST_ICMP_PREDICATE && + "Invalid ICmp predicate value"); + + const Type* Op0Ty = getOperand(0)->getType(); + const Type* Op1Ty = getOperand(1)->getType(); + assert(Op0Ty == Op1Ty && + "Both operands to ICmp instruction are not of the same type!"); + // Check that the operands are the right type + assert(Op0Ty->isIntegral() || Op0Ty->getTypeID() == Type::PointerTyID || + (isa(Op0Ty) && + cast(Op0Ty)->getElementType()->isIntegral()) && + "Invalid operand types for ICmp instruction"); + return; + } + assert(op == Instruction::FCmp && "Invalid CmpInst opcode"); + assert(predicate <= FCmpInst::LAST_FCMP_PREDICATE && + "Invalid FCmp predicate value"); + const Type* Op0Ty = getOperand(0)->getType(); + const Type* Op1Ty = getOperand(1)->getType(); + assert(Op0Ty == Op1Ty && + "Both operands to FCmp instruction are not of the same type!"); + // Check that the operands are the right type + assert(Op0Ty->isFloatingPoint() || (isa(Op0Ty) && + cast(Op0Ty)->getElementType()->isFloatingPoint()) && + "Invalid operand types for FCmp instruction"); +} + +CmpInst * +CmpInst::create(OtherOps Op, unsigned short predicate, Value *S1, Value *S2, + const std::string &Name, Instruction *InsertBefore) { + if (Op == Instruction::ICmp) { + return new ICmpInst(ICmpInst::Predicate(predicate), S1, S2, Name, + InsertBefore); + } + return new FCmpInst(FCmpInst::Predicate(predicate), S1, S2, Name, + InsertBefore); +} + +CmpInst * +CmpInst::create(OtherOps Op, unsigned short predicate, Value *S1, Value *S2, + const std::string &Name, BasicBlock *InsertAtEnd) { + if (Op == Instruction::ICmp) { + return new ICmpInst(ICmpInst::Predicate(predicate), S1, S2, Name, + InsertAtEnd); + } + return new FCmpInst(FCmpInst::Predicate(predicate), S1, S2, Name, + InsertAtEnd); +} + +void CmpInst::swapOperands() { + if (ICmpInst *IC = dyn_cast(this)) + IC->swapOperands(); + else + cast(this)->swapOperands(); +} + +bool CmpInst::isCommutative() { + if (ICmpInst *IC = dyn_cast(this)) + return IC->isCommutative(); + return cast(this)->isCommutative(); +} + +bool CmpInst::isEquality() { + if (ICmpInst *IC = dyn_cast(this)) + return IC->isEquality(); + return cast(this)->isEquality(); +} + + +ICmpInst::Predicate ICmpInst::getInversePredicate(Predicate pred) { + switch (pred) { + default: + assert(!"Unknown icmp predicate!"); + case ICMP_EQ: return ICMP_NE; + case ICMP_NE: return ICMP_EQ; + case ICMP_UGT: return ICMP_ULE; + case ICMP_ULT: return ICMP_UGE; + case ICMP_UGE: return ICMP_ULT; + case ICMP_ULE: return ICMP_UGT; + case ICMP_SGT: return ICMP_SLE; + case ICMP_SLT: return ICMP_SGE; + case ICMP_SGE: return ICMP_SLT; + case ICMP_SLE: return ICMP_SGT; + } +} + +ICmpInst::Predicate ICmpInst::getSwappedPredicate(Predicate pred) { + switch (pred) { + default: assert(! "Unknown setcc instruction!"); + case ICMP_EQ: case ICMP_NE: + return pred; + case ICMP_SGT: return ICMP_SLT; + case ICMP_SLT: return ICMP_SGT; + case ICMP_SGE: return ICMP_SLE; + case ICMP_SLE: return ICMP_SGE; + case ICMP_UGT: return ICMP_ULT; + case ICMP_ULT: return ICMP_UGT; + case ICMP_UGE: return ICMP_ULE; + case ICMP_ULE: return ICMP_UGE; + } +} + +FCmpInst::Predicate FCmpInst::getInversePredicate(Predicate pred) { + switch (pred) { + default: + assert(!"Unknown icmp predicate!"); + case FCMP_OEQ: return FCMP_UNE; + case FCMP_ONE: return FCMP_UEQ; + case FCMP_OGT: return FCMP_ULE; + case FCMP_OLT: return FCMP_UGE; + case FCMP_OGE: return FCMP_ULT; + case FCMP_OLE: return FCMP_UGT; + case FCMP_UEQ: return FCMP_ONE; + case FCMP_UNE: return FCMP_OEQ; + case FCMP_UGT: return FCMP_OLE; + case FCMP_ULT: return FCMP_OGE; + case FCMP_UGE: return FCMP_OLT; + case FCMP_ULE: return FCMP_OGT; + case FCMP_ORD: return FCMP_UNO; + case FCMP_UNO: return FCMP_ORD; + case FCMP_TRUE: return FCMP_FALSE; + case FCMP_FALSE: return FCMP_TRUE; + } +} + +FCmpInst::Predicate FCmpInst::getSwappedPredicate(Predicate pred) { + switch (pred) { + default: assert(!"Unknown setcc instruction!"); + case FCMP_FALSE: case FCMP_TRUE: + case FCMP_OEQ: case FCMP_ONE: + case FCMP_UEQ: case FCMP_UNE: + case FCMP_ORD: case FCMP_UNO: + return pred; + case FCMP_OGT: return FCMP_OLT; + case FCMP_OLT: return FCMP_OGT; + case FCMP_OGE: return FCMP_OLE; + case FCMP_OLE: return FCMP_OGE; + case FCMP_UGT: return FCMP_ULT; + case FCMP_ULT: return FCMP_UGT; + case FCMP_UGE: return FCMP_ULE; + case FCMP_ULE: return FCMP_UGE; + } +} + //===----------------------------------------------------------------------===// // SwitchInst Implementation //===----------------------------------------------------------------------===// @@ -1412,6 +1603,11 @@ BinaryOperator *BinaryOperator::clone() const { return create(getOpcode(), Ops[0], Ops[1]); } +CmpInst* CmpInst::clone() const { + return create(Instruction::OtherOps(getOpcode()), getPredicate(), + Ops[0], Ops[1]); +} + MallocInst *MallocInst::clone() const { return new MallocInst(*this); } AllocaInst *AllocaInst::clone() const { return new AllocaInst(*this); } FreeInst *FreeInst::clone() const { return new FreeInst(getOperand(0)); } diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp index 868fc67d51f..065ac3b7750 100644 --- a/lib/VMCore/Verifier.cpp +++ b/lib/VMCore/Verifier.cpp @@ -179,6 +179,8 @@ namespace { // Anonymous namespace for class void visitBasicBlock(BasicBlock &BB); void visitPHINode(PHINode &PN); void visitBinaryOperator(BinaryOperator &B); + void visitICmpInst(ICmpInst &IC); + void visitFCmpInst(FCmpInst &FC); void visitShiftInst(ShiftInst &SI); void visitExtractElementInst(ExtractElementInst &EI); void visitInsertElementInst(InsertElementInst &EI); @@ -551,6 +553,33 @@ void Verifier::visitBinaryOperator(BinaryOperator &B) { visitInstruction(B); } +void Verifier::visitICmpInst(ICmpInst& IC) { + // Check that the operands are the same type + const Type* Op0Ty = IC.getOperand(0)->getType(); + const Type* Op1Ty = IC.getOperand(1)->getType(); + Assert1(Op0Ty == Op1Ty, + "Both operands to ICmp instruction are not of the same type!", &IC); + // Check that the operands are the right type + Assert1(Op0Ty->isIntegral() || Op0Ty->getTypeID() == Type::PointerTyID || + (isa(Op0Ty) && + cast(Op0Ty)->getElementType()->isIntegral()), + "Invalid operand types for ICmp instruction", &IC); + visitInstruction(IC); +} + +void Verifier::visitFCmpInst(FCmpInst& FC) { + // Check that the operands are the same type + const Type* Op0Ty = FC.getOperand(0)->getType(); + const Type* Op1Ty = FC.getOperand(1)->getType(); + Assert1(Op0Ty == Op1Ty, + "Both operands to FCmp instruction are not of the same type!", &FC); + // Check that the operands are the right type + Assert1(Op0Ty->isFloatingPoint() || (isa(Op0Ty) && + cast(Op0Ty)->getElementType()->isFloatingPoint()), + "Invalid operand types for FCmp instruction", &FC); + visitInstruction(FC); +} + void Verifier::visitShiftInst(ShiftInst &SI) { Assert1(SI.getType()->isInteger(), "Shift must return an integer result!", &SI);