[llvm-commits] CVS: llvm/lib/Target/CBackend/Makefile Writer.cpp

Reid Spencer reid at x10sys.com
Fri Dec 22 22:06:59 PST 2006



Changes in directory llvm/lib/Target/CBackend:

Makefile updated: 1.8 -> 1.9
Writer.cpp updated: 1.300 -> 1.301
---
Log message:

For PR950: http://llvm.org/PR950 :
This patch removes the SetCC instructions and replaces them with the ICmp
and FCmp instructions. The SetCondInst instruction has been removed and 
been replaced with ICmpInst and FCmpInst.


---
Diffs of the changes:  (+289 -114)

 Makefile   |    2 
 Writer.cpp |  401 +++++++++++++++++++++++++++++++++++++++++++------------------
 2 files changed, 289 insertions(+), 114 deletions(-)


Index: llvm/lib/Target/CBackend/Makefile
diff -u llvm/lib/Target/CBackend/Makefile:1.8 llvm/lib/Target/CBackend/Makefile:1.9
--- llvm/lib/Target/CBackend/Makefile:1.8	Thu Nov  2 18:00:57 2006
+++ llvm/lib/Target/CBackend/Makefile	Sat Dec 23 00:05:41 2006
@@ -11,4 +11,4 @@
 LIBRARYNAME = LLVMCBackend
 include $(LEVEL)/Makefile.common
 
-CompileCommonOpts := $(CompileCommonOpts) -Wno-format
+CompileCommonOpts += -Wno-format


Index: llvm/lib/Target/CBackend/Writer.cpp
diff -u llvm/lib/Target/CBackend/Writer.cpp:1.300 llvm/lib/Target/CBackend/Writer.cpp:1.301
--- llvm/lib/Target/CBackend/Writer.cpp:1.300	Sun Dec 17 14:24:50 2006
+++ llvm/lib/Target/CBackend/Writer.cpp	Sat Dec 23 00:05:41 2006
@@ -116,6 +116,9 @@
     std::ostream &printType(std::ostream &Out, const Type *Ty,
                             const std::string &VariableName = "",
                             bool IgnoreName = false);
+    std::ostream &printPrimitiveType(std::ostream &Out, const Type *Ty, 
+                                     bool isSigned, 
+                                     const std::string &NameSoFar = "");
 
     void printStructReturnPointerFunctionType(std::ostream &Out,
                                               const PointerType *Ty);
@@ -124,6 +127,7 @@
     void writeOperandRaw(Value *Operand);
     void writeOperandInternal(Value *Operand);
     void writeOperandWithCast(Value* Operand, unsigned Opcode);
+    void writeOperandWithCast(Value* Operand, ICmpInst::Predicate predicate);
     bool writeInstructionCast(const Instruction &I);
 
   private :
@@ -154,9 +158,10 @@
     // printed and an extra copy of the expr is not emitted.
     //
     static bool isInlinableInst(const Instruction &I) {
-      // Always inline setcc instructions, even if they are shared by multiple
+      // Always inline cmp instructions, even if they are shared by multiple
       // expressions.  GCC generates horrible code if we don't.
-      if (isa<SetCondInst>(I)) return true;
+      if (isa<CmpInst>(I)) 
+        return true;
 
       // Must be an expression, must be used exactly once.  If it is dead, we
       // emit it inline where it would go.
@@ -211,6 +216,8 @@
 
     void visitPHINode(PHINode &I);
     void visitBinaryOperator(Instruction &I);
+    void visitICmpInst(ICmpInst &I);
+    void visitFCmpInst(FCmpInst &I);
 
     void visitCastInst (CastInst &I);
     void visitSelectInst(SelectInst &I);
@@ -351,6 +358,32 @@
   printType(Out, RetTy, tstr);
 }
 
+std::ostream &
+CWriter::printPrimitiveType(std::ostream &Out, const Type *Ty, bool isSigned,
+                            const std::string &NameSoFar) {
+  assert(Ty->isPrimitiveType() && "Invalid type for printPrimitiveType");
+  switch (Ty->getTypeID()) {
+  case Type::VoidTyID:   return Out << "void "               << NameSoFar;
+  case Type::BoolTyID:   return Out << "bool "               << NameSoFar;
+  case Type::UByteTyID:  
+  case Type::SByteTyID:
+    return Out << (isSigned?"signed":"unsigned") << " char " << NameSoFar;
+  case Type::UShortTyID: 
+  case Type::ShortTyID:  
+    return Out << (isSigned?"signed":"unsigned") << " short " << NameSoFar;
+  case Type::UIntTyID:   
+  case Type::IntTyID:    
+    return Out << (isSigned?"signed":"unsigned") << " int " << NameSoFar;
+  case Type::ULongTyID:  
+  case Type::LongTyID:   
+    return Out << (isSigned?"signed":"unsigned") << " long long " << NameSoFar;
+  case Type::FloatTyID:  return Out << "float "              << NameSoFar;
+  case Type::DoubleTyID: return Out << "double "             << NameSoFar;
+  default :
+    cerr << "Unknown primitive type: " << *Ty << "\n";
+    abort();
+  }
+}
 
 // Pass the Type* and the variable name and this prints out the variable
 // declaration.
@@ -358,24 +391,13 @@
 std::ostream &CWriter::printType(std::ostream &Out, const Type *Ty,
                                  const std::string &NameSoFar,
                                  bool IgnoreName) {
-  if (Ty->isPrimitiveType())
-    switch (Ty->getTypeID()) {
-    case Type::VoidTyID:   return Out << "void "               << NameSoFar;
-    case Type::BoolTyID:   return Out << "bool "               << NameSoFar;
-    case Type::UByteTyID:  return Out << "unsigned char "      << NameSoFar;
-    case Type::SByteTyID:  return Out << "signed char "        << NameSoFar;
-    case Type::UShortTyID: return Out << "unsigned short "     << NameSoFar;
-    case Type::ShortTyID:  return Out << "short "              << NameSoFar;
-    case Type::UIntTyID:   return Out << "unsigned "           << NameSoFar;
-    case Type::IntTyID:    return Out << "int "                << NameSoFar;
-    case Type::ULongTyID:  return Out << "unsigned long long " << NameSoFar;
-    case Type::LongTyID:   return Out << "signed long long "   << NameSoFar;
-    case Type::FloatTyID:  return Out << "float "              << NameSoFar;
-    case Type::DoubleTyID: return Out << "double "             << NameSoFar;
-    default :
-      cerr << "Unknown primitive type: " << *Ty << "\n";
-      abort();
-    }
+  if (Ty->isPrimitiveType()) {
+    // FIXME:Signedness. When integer types are signless, this should just
+    // always pass "false" for the sign of the primitive type. The instructions
+    // will figure out how the value is to be interpreted.
+    printPrimitiveType(Out, Ty, true, NameSoFar);
+    return Out;
+  }
 
   // Check to see if the type is named.
   if (!IgnoreName || isa<OpaqueType>(Ty)) {
@@ -578,41 +600,66 @@
 
 /// Print out the casting for a cast operation. This does the double casting
 /// necessary for conversion to the destination type, if necessary. 
-/// @returns true if a closing paren is necessary
 /// @brief Print a cast
 void CWriter::printCast(unsigned opc, const Type *SrcTy, const Type *DstTy) {
-  Out << '(';
-  printType(Out, DstTy);
-  Out << ')';
+  // Print the destination type cast
+  switch (opc) {
+    case Instruction::UIToFP:
+    case Instruction::SIToFP:
+    case Instruction::IntToPtr:
+    case Instruction::Trunc:
+    case Instruction::BitCast:
+    case Instruction::FPExt:
+    case Instruction::FPTrunc: // For these the DstTy sign doesn't matter
+      Out << '(';
+      printType(Out, DstTy);
+      Out << ')';
+      break;
+    case Instruction::ZExt:
+    case Instruction::PtrToInt:
+    case Instruction::FPToUI: // For these, make sure we get an unsigned dest
+      Out << '(';
+      printPrimitiveType(Out, DstTy, false);
+      Out << ')';
+      break;
+    case Instruction::SExt: 
+    case Instruction::FPToSI: // For these, make sure we get a signed dest
+      Out << '(';
+      printPrimitiveType(Out, DstTy, true);
+      Out << ')';
+      break;
+    default:
+      assert(0 && "Invalid cast opcode");
+  }
+
+  // Print the source type cast
   switch (opc) {
     case Instruction::UIToFP:
     case Instruction::ZExt:
-      if (SrcTy->isSigned()) {
-        Out << '(';
-        printType(Out, SrcTy->getUnsignedVersion());
-        Out << ')';
-      }
+      Out << '(';
+      printPrimitiveType(Out, SrcTy, false);
+      Out << ')';
       break;
     case Instruction::SIToFP:
     case Instruction::SExt:
-      if (SrcTy->isUnsigned()) {
-        Out << '(';
-        printType(Out, SrcTy->getSignedVersion());
-        Out << ')';
-      }
+      Out << '(';
+      printPrimitiveType(Out, SrcTy, true); 
+      Out << ')';
       break;
     case Instruction::IntToPtr:
     case Instruction::PtrToInt:
-        // Avoid "cast to pointer from integer of different size" warnings
-        Out << "(unsigned long)";
-        break;
+      // Avoid "cast to pointer from integer of different size" warnings
+      Out << "(unsigned long)";
+      break;
     case Instruction::Trunc:
     case Instruction::BitCast:
     case Instruction::FPExt:
     case Instruction::FPTrunc:
     case Instruction::FPToSI:
     case Instruction::FPToUI:
+      break; // These don't need a source cast.
     default:
+      assert(0 && "Invalid cast opcode");
       break;
   }
 }
@@ -679,12 +726,8 @@
     case Instruction::And:
     case Instruction::Or:
     case Instruction::Xor:
-    case Instruction::SetEQ:
-    case Instruction::SetNE:
-    case Instruction::SetLT:
-    case Instruction::SetLE:
-    case Instruction::SetGT:
-    case Instruction::SetGE:
+    case Instruction::ICmp:
+    case Instruction::FCmp:
     case Instruction::Shl:
     case Instruction::LShr:
     case Instruction::AShr:
@@ -705,15 +748,43 @@
       case Instruction::And: Out << " & "; break;
       case Instruction::Or:  Out << " | "; break;
       case Instruction::Xor: Out << " ^ "; break;
-      case Instruction::SetEQ: Out << " == "; break;
-      case Instruction::SetNE: Out << " != "; break;
-      case Instruction::SetLT: Out << " < "; break;
-      case Instruction::SetLE: Out << " <= "; break;
-      case Instruction::SetGT: Out << " > "; break;
-      case Instruction::SetGE: Out << " >= "; break;
       case Instruction::Shl: Out << " << "; break;
       case Instruction::LShr:
       case Instruction::AShr: Out << " >> "; break;
+      case Instruction::ICmp:
+        switch (CE->getPredicate()) {
+          case ICmpInst::ICMP_EQ: Out << " == "; break;
+          case ICmpInst::ICMP_NE: Out << " != "; break;
+          case ICmpInst::ICMP_SLT: 
+          case ICmpInst::ICMP_ULT: Out << " < "; break;
+          case ICmpInst::ICMP_SLE:
+          case ICmpInst::ICMP_ULE: Out << " <= "; break;
+          case ICmpInst::ICMP_SGT:
+          case ICmpInst::ICMP_UGT: Out << " > "; break;
+          case ICmpInst::ICMP_SGE:
+          case ICmpInst::ICMP_UGE: Out << " >= "; break;
+          default: assert(0 && "Illegal ICmp predicate");
+        }
+        break;
+      case Instruction::FCmp:
+        switch (CE->getPredicate()) {
+          case FCmpInst::FCMP_ORD: 
+          case FCmpInst::FCMP_UEQ: 
+          case FCmpInst::FCMP_OEQ: Out << " == "; break;
+          case FCmpInst::FCMP_UNO: 
+          case FCmpInst::FCMP_UNE: 
+          case FCmpInst::FCMP_ONE: Out << " != "; break;
+          case FCmpInst::FCMP_OLT:
+          case FCmpInst::FCMP_ULT: Out << " < "; break;
+          case FCmpInst::FCMP_OLE:
+          case FCmpInst::FCMP_ULE: Out << " <= "; break;
+          case FCmpInst::FCMP_OGT: 
+          case FCmpInst::FCMP_UGT: Out << " > "; break;
+          case FCmpInst::FCMP_OGE:
+          case FCmpInst::FCMP_UGE: Out << " >= "; break;
+          default: assert(0 && "Illegal FCmp predicate");
+        }
+        break;
       default: assert(0 && "Illegal opcode here!");
       }
       printConstantWithCast(CE->getOperand(1), CE->getOpcode());
@@ -730,7 +801,7 @@
     }
   } else if (isa<UndefValue>(CPV) && CPV->getType()->isFirstClassType()) {
     Out << "((";
-    printType(Out, CPV->getType());
+    printType(Out, CPV->getType()); // sign doesn't matter
     Out << ")/*UNDEF*/0)";
     return;
   }
@@ -740,9 +811,23 @@
     Out << (cast<ConstantBool>(CPV)->getValue() ? '1' : '0');
     break;
   case Type::SByteTyID:
+  case Type::UByteTyID:
+    Out << "((char)" << cast<ConstantInt>(CPV)->getSExtValue() << ")";
+    break;
   case Type::ShortTyID:
-    Out << cast<ConstantInt>(CPV)->getSExtValue();
+  case Type::UShortTyID:
+    Out << "((short)" << cast<ConstantInt>(CPV)->getSExtValue() << ")";
+    break;
+  case Type::IntTyID:
+  case Type::UIntTyID:
+    Out << "((int)" << cast<ConstantInt>(CPV)->getSExtValue() << ")";
+    break;
+  case Type::LongTyID:
+  case Type::ULongTyID:
+    Out << "((long long)" << cast<ConstantInt>(CPV)->getSExtValue() << "ll)";
     break;
+
+#if 0
   case Type::IntTyID:
     if ((int)cast<ConstantInt>(CPV)->getSExtValue() == (int)0x80000000)
       Out << "((int)0x80000000U)";   // Handle MININT specially to avoid warning
@@ -767,6 +852,7 @@
   case Type::ULongTyID:
     Out << cast<ConstantInt>(CPV)->getZExtValue() << "ull";
     break;
+#endif
 
   case Type::FloatTyID:
   case Type::DoubleTyID: {
@@ -890,7 +976,7 @@
   case Type::PointerTyID:
     if (isa<ConstantPointerNull>(CPV)) {
       Out << "((";
-      printType(Out, CPV->getType());
+      printType(Out, CPV->getType()); // sign doesn't matter
       Out << ")/*NULL*/0)";
       break;
     } else if (GlobalValue *GV = dyn_cast<GlobalValue>(CPV)) {
@@ -910,17 +996,20 @@
 bool CWriter::printConstExprCast(const ConstantExpr* CE) {
   bool NeedsExplicitCast = false;
   const Type *Ty = CE->getOperand(0)->getType();
+  bool TypeIsSigned = false;
   switch (CE->getOpcode()) {
   case Instruction::LShr:
   case Instruction::URem: 
-  case Instruction::UDiv: 
-    NeedsExplicitCast = Ty->isSigned(); break;
+  case Instruction::UDiv: NeedsExplicitCast = true; break;
   case Instruction::AShr:
   case Instruction::SRem: 
-  case Instruction::SDiv: 
-    NeedsExplicitCast = Ty->isUnsigned(); break;
-  case Instruction::ZExt:
+  case Instruction::SDiv: NeedsExplicitCast = true; TypeIsSigned = true; break;
   case Instruction::SExt:
+    Ty = CE->getType();
+    NeedsExplicitCast = true;
+    TypeIsSigned = true;
+    break;
+  case Instruction::ZExt:
   case Instruction::Trunc:
   case Instruction::FPTrunc:
   case Instruction::FPExt:
@@ -938,7 +1027,10 @@
   }
   if (NeedsExplicitCast) {
     Out << "((";
-    printType(Out, Ty);
+    if (Ty->isPrimitiveType())
+      printPrimitiveType(Out, Ty, TypeIsSigned);
+    else
+      printType(Out, Ty);
     Out << ")(";
   }
   return NeedsExplicitCast;
@@ -954,6 +1046,7 @@
 
   // Indicate whether to do the cast or not.
   bool shouldCast = false;
+  bool typeIsSigned = false;
 
   // Based on the Opcode for which this Constant is being written, determine
   // the new type to which the operand should be casted by setting the value
@@ -966,20 +1059,13 @@
     case Instruction::LShr:
     case Instruction::UDiv:
     case Instruction::URem:
-      // For UDiv/URem get correct type
-      if (OpTy->isSigned()) {
-        OpTy = OpTy->getUnsignedVersion();
-        shouldCast = true;
-      }
+      shouldCast = true;
       break;
     case Instruction::AShr:
     case Instruction::SDiv:
     case Instruction::SRem:
-      // For SDiv/SRem get correct type
-      if (OpTy->isUnsigned()) {
-        OpTy = OpTy->getSignedVersion();
-        shouldCast = true;
-      }
+      shouldCast = true;
+      typeIsSigned = true;
       break;
   }
 
@@ -987,13 +1073,12 @@
   // operand.
   if (shouldCast) {
     Out << "((";
-    printType(Out, OpTy);
+    printPrimitiveType(Out, OpTy, typeIsSigned);
     Out << ")";
     printConstant(CPV);
     Out << ")";
   } else 
-    writeOperand(CPV);
-
+    printConstant(CPV);
 }
 
 void CWriter::writeOperandInternal(Value *Operand) {
@@ -1038,40 +1123,25 @@
 // This function takes care of detecting that case and printing the cast 
 // for the Instruction.
 bool CWriter::writeInstructionCast(const Instruction &I) {
-  bool NeedsExplicitCast = false;
   const Type *Ty = I.getOperand(0)->getType();
   switch (I.getOpcode()) {
   case Instruction::LShr:
   case Instruction::URem: 
   case Instruction::UDiv: 
-    NeedsExplicitCast = Ty->isSigned(); break;
+    Out << "((";
+    printPrimitiveType(Out, Ty, false);
+    Out << ")(";
+    return true;
   case Instruction::AShr:
   case Instruction::SRem: 
   case Instruction::SDiv: 
-    NeedsExplicitCast = Ty->isUnsigned(); break;
-  case Instruction::ZExt:
-  case Instruction::SExt:
-  case Instruction::Trunc:
-  case Instruction::FPTrunc:
-  case Instruction::FPExt:
-  case Instruction::UIToFP:
-  case Instruction::SIToFP:
-  case Instruction::FPToUI:
-  case Instruction::FPToSI:
-  case Instruction::PtrToInt:
-  case Instruction::IntToPtr:
-  case Instruction::BitCast:
-    Ty = I.getType();
-    NeedsExplicitCast = true;
-    break;
-  default: break;
-  }
-  if (NeedsExplicitCast) {
     Out << "((";
-    printType(Out, Ty);
+    printPrimitiveType(Out, Ty, true);
     Out << ")(";
+    return true;
+  default: break;
   }
-  return NeedsExplicitCast;
+  return false;
 }
 
 // Write the operand with a cast to another type based on the Opcode being used.
@@ -1085,6 +1155,9 @@
   // Indicate whether to do the cast or not.
   bool shouldCast = false;
 
+  // Indicate whether the cast should be to a signed type or not.
+  bool castIsSigned = false;
+
   // Based on the Opcode for which this Operand is being written, determine
   // the new type to which the operand should be casted by setting the value
   // of OpTy. If we change OpTy, also set shouldCast to true.
@@ -1094,20 +1167,15 @@
       break; 
     case Instruction::LShr:
     case Instruction::UDiv:
-    case Instruction::URem:
-      // For UDiv to have unsigned operands
-      if (OpTy->isSigned()) {
-        OpTy = OpTy->getUnsignedVersion();
-        shouldCast = true;
-      }
+    case Instruction::URem: // Cast to unsigned first
+      shouldCast = true;
+      castIsSigned = false;
       break;
     case Instruction::AShr:
     case Instruction::SDiv:
-    case Instruction::SRem:
-      if (OpTy->isUnsigned()) {
-        OpTy = OpTy->getSignedVersion();
-        shouldCast = true;
-      }
+    case Instruction::SRem: // Cast to signed first
+      shouldCast = true;
+      castIsSigned = true;
       break;
   }
 
@@ -1115,13 +1183,62 @@
   // operand.
   if (shouldCast) {
     Out << "((";
-    printType(Out, OpTy);
+    printPrimitiveType(Out, OpTy, castIsSigned);
     Out << ")";
     writeOperand(Operand);
     Out << ")";
   } else 
     writeOperand(Operand);
+}
+
+// Write the operand with a cast to another type based on the icmp predicate 
+// being used. 
+void CWriter::writeOperandWithCast(Value* Operand, ICmpInst::Predicate predicate) {
+
+  // Extract the operand's type, we'll need it.
+  const Type* OpTy = Operand->getType();
+
+  // Indicate whether to do the cast or not.
+  bool shouldCast = false;
 
+  // Indicate whether the cast should be to a signed type or not.
+  bool castIsSigned = false;
+
+  // Based on the Opcode for which this Operand is being written, determine
+  // the new type to which the operand should be casted by setting the value
+  // of OpTy. If we change OpTy, also set shouldCast to true.
+  switch (predicate) {
+    default:
+      // for eq and ne, it doesn't matter
+      break; 
+    case ICmpInst::ICMP_UGT:
+    case ICmpInst::ICMP_UGE:
+    case ICmpInst::ICMP_ULT:
+    case ICmpInst::ICMP_ULE:
+      shouldCast = true;
+      break;
+    case ICmpInst::ICMP_SGT:
+    case ICmpInst::ICMP_SGE:
+    case ICmpInst::ICMP_SLT:
+    case ICmpInst::ICMP_SLE:
+      shouldCast = true;
+      castIsSigned = true;
+      break;
+  }
+
+  // Write out the casted operand if we should, otherwise just write the
+  // operand.
+  if (shouldCast) {
+    Out << "((";
+    if (OpTy->isPrimitiveType())
+      printPrimitiveType(Out, OpTy, castIsSigned);
+    else
+      printType(Out, OpTy);
+    Out << ")";
+    writeOperand(Operand);
+    Out << ")";
+  } else 
+    writeOperand(Operand);
 }
 
 // generateCompilerSpecificCode - This is where we add conditional compilation
@@ -1725,7 +1842,7 @@
       PrintedVar = true;
     }
     // We need a temporary for the BitCast to use so it can pluck a value out
-    // of a uniont to do the BitCast. This is separate from the need for a
+    // of a union to do the BitCast. This is separate from the need for a
     // variable to hold the result of the BitCast. 
     if (isFPIntBitCast(*I)) {
       Out << "  llvmBitCastUnion " << Mang->getValueName(&*I)
@@ -1992,12 +2109,6 @@
     case Instruction::And: Out << " & "; break;
     case Instruction::Or: Out << " | "; break;
     case Instruction::Xor: Out << " ^ "; break;
-    case Instruction::SetEQ: Out << " == "; break;
-    case Instruction::SetNE: Out << " != "; break;
-    case Instruction::SetLE: Out << " <= "; break;
-    case Instruction::SetGE: Out << " >= "; break;
-    case Instruction::SetLT: Out << " < "; break;
-    case Instruction::SetGT: Out << " > "; break;
     case Instruction::Shl : Out << " << "; break;
     case Instruction::LShr:
     case Instruction::AShr: Out << " >> "; break;
@@ -2014,6 +2125,70 @@
   }
 }
 
+void CWriter::visitICmpInst(ICmpInst &I) {
+  // We must cast the results of icmp which might be promoted.
+  bool needsCast = false;
+
+  // Write out the cast of the instruction's value back to the proper type
+  // if necessary.
+  bool NeedsClosingParens = writeInstructionCast(I);
+
+  // Certain icmp predicate require the operand to be forced to a specific type
+  // so we use writeOperandWithCast here instead of writeOperand. Similarly
+  // below for operand 1
+  writeOperandWithCast(I.getOperand(0), I.getPredicate());
+
+  switch (I.getPredicate()) {
+  case ICmpInst::ICMP_EQ:  Out << " == "; break;
+  case ICmpInst::ICMP_NE:  Out << " != "; break;
+  case ICmpInst::ICMP_ULE:
+  case ICmpInst::ICMP_SLE: Out << " <= "; break;
+  case ICmpInst::ICMP_UGE:
+  case ICmpInst::ICMP_SGE: Out << " >= "; break;
+  case ICmpInst::ICMP_ULT:
+  case ICmpInst::ICMP_SLT: Out << " < "; break;
+  case ICmpInst::ICMP_UGT:
+  case ICmpInst::ICMP_SGT: Out << " > "; break;
+  default: cerr << "Invalid icmp predicate!" << I; abort();
+  }
+
+  writeOperandWithCast(I.getOperand(1), I.getPredicate());
+  if (NeedsClosingParens)
+    Out << "))";
+
+  if (needsCast) {
+    Out << "))";
+  }
+}
+
+void CWriter::visitFCmpInst(FCmpInst &I) {
+  // Write the first operand
+  writeOperand(I.getOperand(0));
+
+  // Write the predicate
+  switch (I.getPredicate()) {
+  case FCmpInst::FCMP_FALSE: Out << " 0 "; break;
+  case FCmpInst::FCMP_ORD:
+  case FCmpInst::FCMP_OEQ: 
+  case FCmpInst::FCMP_UEQ:   Out << " == "; break;
+  case FCmpInst::FCMP_UNO:
+  case FCmpInst::FCMP_ONE: 
+  case FCmpInst::FCMP_UNE:   Out << " != "; break;
+  case FCmpInst::FCMP_ULE:
+  case FCmpInst::FCMP_OLE:   Out << " <= "; break;
+  case FCmpInst::FCMP_UGE:
+  case FCmpInst::FCMP_OGE:   Out << " >= "; break;
+  case FCmpInst::FCMP_ULT:
+  case FCmpInst::FCMP_OLT:   Out << " < "; break;
+  case FCmpInst::FCMP_UGT:
+  case FCmpInst::FCMP_OGT:   Out << " > "; break;
+  case FCmpInst::FCMP_TRUE:  Out << " 1 "; break;
+  default: cerr << "Invalid fcmp predicate!" << I; abort();
+  }
+  // Write the second operand
+  writeOperand(I.getOperand(1));
+}
+
 static const char * getFloatBitCastField(const Type *Ty) {
   switch (Ty->getTypeID()) {
     default: assert(0 && "Invalid Type");






More information about the llvm-commits mailing list