For PR950:
authorReid Spencer <rspencer@reidspencer.com>
Mon, 20 Nov 2006 01:22:35 +0000 (01:22 +0000)
committerReid Spencer <rspencer@reidspencer.com>
Mon, 20 Nov 2006 01:22:35 +0000 (01:22 +0000)
First in a series of patches to convert SetCondInst into ICmpInst and
FCmpInst using only two opcodes and having the instructions contain their
predicate value. Nothing uses these classes yet. More patches to follow.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@31867 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/InstrTypes.h
include/llvm/Instruction.def
include/llvm/Instructions.h
include/llvm/Support/InstVisitor.h
lib/Analysis/ValueNumbering.cpp
lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
lib/VMCore/Instruction.cpp
lib/VMCore/Instructions.cpp
lib/VMCore/Verifier.cpp

index 7ce430073113cec0c31867322a0ccde33a7462ec..627aad430403072c16592d54e46f8975aa9666bd 100644 (file)
@@ -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<Instruction>(V) && classof(cast<Instruction>(V));
+  }
+};
+
 } // End llvm namespace
 
 #endif
index 96279b05a2a87babce9dae7c61534b686d24bb4c..55c668ab1a6474181254ab1e22d15fa7624c1d46 100644 (file)
@@ -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
index d887c527e5ea8b7dbfa9b2b76b6d507cb28447c6..8046567fdefc245a91985498acc2254ba70ff53e 100644 (file)
@@ -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<Instruction>(V) && classof(cast<Instruction>(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<Instruction>(V) && classof(cast<Instruction>(V));
+  }
+};
+
+
 //===----------------------------------------------------------------------===//
 //                            SetCondInst Class
 //===----------------------------------------------------------------------===//
index ca45d4c5d6d3b33ed8ed6dee19ca655fc0597e0a..713980a86bede1155ba40f5ba0e7ff842e4d580a 100644 (file)
@@ -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
index 0224a0132fd86c6e98dd871d4bf66bdfab6f4765..03b9f6b3eaee7d667515d6864e3ca7427679db4d 100644 (file)
@@ -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<CmpInst>(*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.
index 11347f9e584a8dd6f8c5141c48f8873ea0c7f2ef..8b9fa863296a525cf68eb5b99d092bb380f69cba 100644 (file)
@@ -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<ICmpInst>(&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<FCmpInst>(&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) {
index 70b375902dc63e60fd8707109faf79f634f724a8..64a9e12f82d2d9169c5f2895e360ff7de5eae0b9 100644 (file)
 //
 //===----------------------------------------------------------------------===//
 
+#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;
 
index 5ed07cfb7f75f9f053f6ad074f9a5b3ef3cab984..f559c6324e4ccee332eccc62a078db71feeb790f 100644 (file)
@@ -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<PackedType>(Op0Ty) && 
+            cast<PackedType>(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<PackedType>(Op0Ty) &&
+         cast<PackedType>(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<PackedType>(Op0Ty) && 
+            cast<PackedType>(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<PackedType>(Op0Ty) &&
+         cast<PackedType>(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<ICmpInst>(this))
+    IC->swapOperands();
+  else
+    cast<FCmpInst>(this)->swapOperands();
+}
+
+bool CmpInst::isCommutative() {
+  if (ICmpInst *IC = dyn_cast<ICmpInst>(this))
+    return IC->isCommutative();
+  return cast<FCmpInst>(this)->isCommutative();
+}
+
+bool CmpInst::isEquality() {
+  if (ICmpInst *IC = dyn_cast<ICmpInst>(this))
+    return IC->isEquality();
+  return cast<FCmpInst>(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)); }
index 868fc67d51fe0939d56ec19b27cf323fa579573c..065ac3b775064dd705af07d1139cf8eeaa319b90 100644 (file)
@@ -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<PackedType>(Op0Ty) && 
+           cast<PackedType>(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<PackedType>(Op0Ty) &&
+           cast<PackedType>(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);