Add icmp and fcmp instructions to Subzero bitcode reader.

BUG= https://code.google.com/p/nativeclient/issues/detail?id=3894
R=jvoung@chromium.org, stichnot@chromium.org

Review URL: https://codereview.chromium.org/543793003
diff --git a/src/IceTypes.cpp b/src/IceTypes.cpp
index 21157d0..3a5b80a 100644
--- a/src/IceTypes.cpp
+++ b/src/IceTypes.cpp
@@ -33,7 +33,8 @@
   };
   // Define a temporary set of enum values based on ICETYPE_PROPS_TABLE
   enum {
-#define X(tag, IsVec, IsInt, IsFloat, IsIntArith) _props_table_tag_##tag,
+#define X(tag, IsVec, IsInt, IsFloat, IsIntArith, CompareResult)               \
+    _props_table_tag_##tag,
     ICETYPE_PROPS_TABLE
 #undef X
         _enum_props_table_tag_Names
@@ -44,7 +45,7 @@
   ICETYPE_TABLE;
 #undef X
 // Assert that tags in ICETYPE_PROPS_TABLE is in ICETYPE_TABLE.
-#define X(tag, IsVec, IsInt, IsFloat, IsIntArith)                              \
+#define X(tag, IsVec, IsInt, IsFloat, IsIntArith, CompareResult)               \
   STATIC_ASSERT((unsigned)_table_tag_##tag == (unsigned)_props_table_tag_##tag);
   ICETYPE_PROPS_TABLE;
 #undef X
@@ -61,13 +62,13 @@
   };
   // Define constants for boolean flag if vector in ICETYPE_PROPS_TABLE.
   enum {
-#define X(tag, IsVec, IsInt, IsFloat, IsIntArith)                              \
-  _props_table_IsVec_##tag = IsVec,
+#define X(tag, IsVec, IsInt, IsFloat, IsIntArith, CompareResult)               \
+    _props_table_IsVec_##tag = IsVec,
     ICETYPE_PROPS_TABLE
 #undef X
   };
 // Verify that the number of vector elements is consistent with IsVec.
-#define X(tag, IsVec, IsInt, IsFloat, IsIntArith)                              \
+#define X(tag, IsVec, IsInt, IsFloat, IsIntArith, CompareResult)               \
   STATIC_ASSERT((_table_elts_##tag > 1) == _props_table_IsVec_##tag);
   ICETYPE_PROPS_TABLE;
 #undef X
@@ -98,13 +99,14 @@
   bool TypeIsFloatingType;
   bool TypeIsScalarFloatingType;
   bool TypeIsVectorFloatingType;
+  Type CompareResultType;
 };
 
 const TypePropertyFields TypePropertiesTable[] = {
-#define X(tag, IsVec, IsInt, IsFloat, IsIntArith)                              \
+#define X(tag, IsVec, IsInt, IsFloat, IsIntArith, CompareResult)               \
   {                                                                            \
     IsVec, IsInt, IsInt && !IsVec, IsInt && IsVec, IsIntArith, IsFloat,        \
-        IsFloat && !IsVec, IsFloat && IsVec                                    \
+    IsFloat && !IsVec, IsFloat && IsVec, CompareResult                         \
   }                                                                            \
   ,
     ICETYPE_PROPS_TABLE
@@ -209,6 +211,14 @@
   return false;
 }
 
+Type getCompareResultType(Type Ty) {
+  size_t Index = static_cast<size_t>(Ty);
+  if (Index < IceType_NUM)
+    return TypePropertiesTable[Index].CompareResultType;
+  llvm_unreachable("Invalid type for getCompareResultType");
+  return IceType_void;
+}
+
 // ======================== Dump routines ======================== //
 
 const char *typeString(Type Ty) {
diff --git a/src/IceTypes.def b/src/IceTypes.def
index 6e1935b..26e9216 100644
--- a/src/IceTypes.def
+++ b/src/IceTypes.def
@@ -40,23 +40,25 @@
 //   I - Is integer value (scalar or vector).
 //   F - Is floating point value (scalar or vector).
 //   IA - Is integer arithmetic type
+//   CR - Result type of compare instruction for argument type
+//        (IceType_void if disallowed)
 #define ICETYPE_PROPS_TABLE                                              \
-  /* Enum Value    V  I  F IA */                                         \
-  X(IceType_void,  0, 0, 0, 0)                                           \
-  X(IceType_i1,    0, 1, 0, 0)                                           \
-  X(IceType_i8,    0, 1, 0, 1)                                           \
-  X(IceType_i16,   0, 1, 0, 1)                                           \
-  X(IceType_i32,   0, 1, 0, 1)                                           \
-  X(IceType_i64,   0, 1, 0, 1)                                           \
-  X(IceType_f32,   0, 0, 1, 0)                                           \
-  X(IceType_f64,   0, 0, 1, 0)                                           \
-  X(IceType_v4i1,  1, 1, 0, 0)                                           \
-  X(IceType_v8i1,  1, 1, 0, 0)                                           \
-  X(IceType_v16i1, 1, 1, 0, 0)                                           \
-  X(IceType_v16i8, 1, 1, 0, 1)                                           \
-  X(IceType_v8i16, 1, 1, 0, 1)                                           \
-  X(IceType_v4i32, 1, 1, 0, 1)                                           \
-  X(IceType_v4f32, 1, 0, 1, 0)                                           \
-//#define X(tag, IsVec, IsInt, IsFloat, IsIntArith)
+  /* Enum Value    V  I  F IA  CR */                                     \
+  X(IceType_void,  0, 0, 0, 0, IceType_void)                             \
+  X(IceType_i1,    0, 1, 0, 0, IceType_i1)                               \
+  X(IceType_i8,    0, 1, 0, 1, IceType_i1)                               \
+  X(IceType_i16,   0, 1, 0, 1, IceType_i1)                               \
+  X(IceType_i32,   0, 1, 0, 1, IceType_i1)                               \
+  X(IceType_i64,   0, 1, 0, 1, IceType_i1)                               \
+  X(IceType_f32,   0, 0, 1, 0, IceType_i1)                               \
+  X(IceType_f64,   0, 0, 1, 0, IceType_i1)                               \
+  X(IceType_v4i1,  1, 1, 0, 0, IceType_v4i1)                             \
+  X(IceType_v8i1,  1, 1, 0, 0, IceType_v8i1)                             \
+  X(IceType_v16i1, 1, 1, 0, 0, IceType_v16i1)                            \
+  X(IceType_v16i8, 1, 1, 0, 1, IceType_v16i1)                            \
+  X(IceType_v8i16, 1, 1, 0, 1, IceType_v8i1)                             \
+  X(IceType_v4i32, 1, 1, 0, 1, IceType_v4i1)                             \
+  X(IceType_v4f32, 1, 0, 1, 0, IceType_v4i1)                             \
+//#define X(tag, IsVec, IsInt, IsFloat, IsIntArith, CompareResult)
 
 #endif // SUBZERO_SRC_ICETYPES_DEF
diff --git a/src/IceTypes.h b/src/IceTypes.h
index 0c67e43..2ce8f35 100644
--- a/src/IceTypes.h
+++ b/src/IceTypes.h
@@ -58,6 +58,11 @@
 bool isScalarFloatingType(Type Ty);
 bool isVectorFloatingType(Type Ty);
 
+/// Returns type generated by applying the compare instructions (icmp and fcmp)
+/// to arguments of the given type. Returns IceType_void if compare is not
+/// allowed.
+Type getCompareResultType(Type Ty);
+
 template <typename StreamType>
 inline StreamType &operator<<(StreamType &Str, const Type &Ty) {
   Str << typeString(Ty);
diff --git a/src/PNaClTranslator.cpp b/src/PNaClTranslator.cpp
index 4d46d4d..2b92ad7 100644
--- a/src/PNaClTranslator.cpp
+++ b/src/PNaClTranslator.cpp
@@ -1034,7 +1034,7 @@
   /// cast opcode and assigns to CastKind. Returns true if successful,
   /// false otherwise.
   bool convertLLVMCastOpToIceOp(Instruction::CastOps LLVMCastOp,
-                                Ice::InstCast::OpKind &CastKind) {
+                                Ice::InstCast::OpKind &CastKind) const {
     switch (LLVMCastOp) {
     case Instruction::ZExt:
       CastKind = Ice::InstCast::Zext;
@@ -1071,6 +1071,104 @@
     }
     return true;
   }
+
+  // Converts PNaCl bitcode Icmp operator to corresponding ICE op.
+  // Returns true if able to convert, false otherwise.
+  bool convertNaClBitcICmpOpToIce(uint64_t Op,
+                                  Ice::InstIcmp::ICond &Cond) const {
+    switch (Op) {
+    case naclbitc::ICMP_EQ:
+      Cond = Ice::InstIcmp::Eq;
+      return true;
+    case naclbitc::ICMP_NE:
+      Cond = Ice::InstIcmp::Ne;
+      return true;
+    case naclbitc::ICMP_UGT:
+      Cond = Ice::InstIcmp::Ugt;
+      return true;
+    case naclbitc::ICMP_UGE:
+      Cond = Ice::InstIcmp::Uge;
+      return true;
+    case naclbitc::ICMP_ULT:
+      Cond = Ice::InstIcmp::Ult;
+      return true;
+    case naclbitc::ICMP_ULE:
+      Cond = Ice::InstIcmp::Ule;
+      return true;
+    case naclbitc::ICMP_SGT:
+      Cond = Ice::InstIcmp::Sgt;
+      return true;
+    case naclbitc::ICMP_SGE:
+      Cond = Ice::InstIcmp::Sge;
+      return true;
+    case naclbitc::ICMP_SLT:
+      Cond = Ice::InstIcmp::Slt;
+      return true;
+    case naclbitc::ICMP_SLE:
+      Cond = Ice::InstIcmp::Sle;
+      return true;
+    default:
+      return false;
+    }
+  }
+
+  // Converts PNaCl bitcode Fcmp operator to corresponding ICE op.
+  // Returns true if able to convert, false otherwise.
+  bool convertNaClBitcFCompOpToIce(uint64_t Op,
+                                   Ice::InstFcmp::FCond &Cond) const {
+    switch (Op) {
+    case naclbitc::FCMP_FALSE:
+      Cond = Ice::InstFcmp::False;
+      return true;
+    case naclbitc::FCMP_OEQ:
+      Cond = Ice::InstFcmp::Oeq;
+      return true;
+    case naclbitc::FCMP_OGT:
+      Cond = Ice::InstFcmp::Ogt;
+      return true;
+    case naclbitc::FCMP_OGE:
+      Cond = Ice::InstFcmp::Oge;
+      return true;
+    case naclbitc::FCMP_OLT:
+      Cond = Ice::InstFcmp::Olt;
+      return true;
+    case naclbitc::FCMP_OLE:
+      Cond = Ice::InstFcmp::Ole;
+      return true;
+    case naclbitc::FCMP_ONE:
+      Cond = Ice::InstFcmp::One;
+      return true;
+    case naclbitc::FCMP_ORD:
+      Cond = Ice::InstFcmp::Ord;
+      return true;
+    case naclbitc::FCMP_UNO:
+      Cond = Ice::InstFcmp::Uno;
+      return true;
+    case naclbitc::FCMP_UEQ:
+      Cond = Ice::InstFcmp::Ueq;
+      return true;
+    case naclbitc::FCMP_UGT:
+      Cond = Ice::InstFcmp::Ugt;
+      return true;
+    case naclbitc::FCMP_UGE:
+      Cond = Ice::InstFcmp::Uge;
+      return true;
+    case naclbitc::FCMP_ULT:
+      Cond = Ice::InstFcmp::Ult;
+      return true;
+    case naclbitc::FCMP_ULE:
+      Cond = Ice::InstFcmp::Ule;
+      return true;
+    case naclbitc::FCMP_UNE:
+      Cond = Ice::InstFcmp::Une;
+      return true;
+    case naclbitc::FCMP_TRUE:
+      Cond = Ice::InstFcmp::True;
+      return true;
+    default:
+      return false;
+    }
+  }
 };
 
 FunctionParser::~FunctionParser() {
@@ -1238,6 +1336,8 @@
   }
   case naclbitc::FUNC_CODE_INST_EXTRACTELT: {
     // EXTRACTELT: [opval, opval]
+    if (!isValidRecordSize(2, "function block extract element"))
+      return;
     Ice::Operand *Vec = getRelativeOperand(Values[0]);
     Ice::Type VecType = Vec->getType();
     if (!Ice::isVectorType(VecType)) {
@@ -1261,6 +1361,8 @@
   }
   case naclbitc::FUNC_CODE_INST_INSERTELT: {
     // INSERTELT: [opval, opval, opval]
+    if (!isValidRecordSize(3, "function block insert element"))
+      return;
     Ice::Operand *Vec = getRelativeOperand(Values[0]);
     Ice::Type VecType = Vec->getType();
     if (!Ice::isVectorType(VecType)) {
@@ -1291,6 +1393,66 @@
     Inst = Ice::InstInsertElement::create(Func, Dest, Vec, Elt, Index);
     break;
   }
+  case naclbitc::FUNC_CODE_INST_CMP2: {
+    // CMP2: [opval, opval, pred]
+    if (!isValidRecordSize(3, "function block compare"))
+      return;
+    Ice::Operand *Op1 = getRelativeOperand(Values[0]);
+    Ice::Operand *Op2 = getRelativeOperand(Values[1]);
+    Ice::Type Op1Type = Op1->getType();
+    Ice::Type Op2Type = Op2->getType();
+    if (Op1Type != Op2Type) {
+      std::string Buffer;
+      raw_string_ostream StrBuf(Buffer);
+      StrBuf << "Compare argument types differ: " << Op1Type
+             << " and " << Op2Type;
+      Error(StrBuf.str());
+      // TODO(kschimpf) Remove error recovery once implementation complete.
+      Op2 = Op1;
+    }
+    Ice::Type DestType = getCompareResultType(Op1Type);
+    if (DestType == Ice::IceType_void) {
+      std::string Buffer;
+      raw_string_ostream StrBuf(Buffer);
+      StrBuf << "Compare not defined for type " << Op1Type;
+      Error(StrBuf.str());
+      return;
+    }
+    Ice::Variable *Dest = NextInstVar(DestType);
+    if (isIntegerType(Op1Type)) {
+      Ice::InstIcmp::ICond Cond;
+      if (!convertNaClBitcICmpOpToIce(Values[2], Cond)) {
+        std::string Buffer;
+        raw_string_ostream StrBuf(Buffer);
+        StrBuf << "Compare record contains unknown integer predicate index: "
+               << Values[2];
+        Error(StrBuf.str());
+        // TODO(kschimpf) Remove error recovery once implementation complete.
+        Cond = Ice::InstIcmp::Eq;
+      }
+      Inst = Ice::InstIcmp::create(Func, Cond,  Dest, Op1, Op2);
+    } else if (isFloatingType(Op1Type)){
+      Ice::InstFcmp::FCond Cond;
+      if (!convertNaClBitcFCompOpToIce(Values[2], Cond)) {
+        std::string Buffer;
+        raw_string_ostream StrBuf(Buffer);
+        StrBuf << "Compare record contains unknown float predicate index: "
+               << Values[2];
+        Error(StrBuf.str());
+        // TODO(kschimpf) Remove error recovery once implementation complete.
+        Cond = Ice::InstFcmp::False;
+      }
+      Inst = Ice::InstFcmp::create(Func, Cond, Dest, Op1, Op2);
+    } else {
+      // Not sure this can happen, but be safe.
+      std::string Buffer;
+      raw_string_ostream StrBuf(Buffer);
+      StrBuf << "Compare on type not understood: " << Op1Type;
+      Error(StrBuf.str());
+      return;
+    }
+    break;
+  }
   case naclbitc::FUNC_CODE_INST_RET: {
     // RET: [opval?]
     InstIsTerminating = true;
diff --git a/tests_lit/reader_tests/compare.ll b/tests_lit/reader_tests/compare.ll
new file mode 100644
index 0000000..08267db
--- /dev/null
+++ b/tests_lit/reader_tests/compare.ll
@@ -0,0 +1,460 @@
+; Test if we can read compare instructions.
+
+; RUN: llvm-as < %s | pnacl-freeze \
+; RUN:              | %llvm2ice -notranslate -verbose=inst -build-on-read \
+; RUN:                -allow-pnacl-reader-error-recovery \
+; RUN:              | FileCheck %s
+
+define i1 @IcmpI1(i32 %p1, i32 %p2) {
+  %a1 = trunc i32 %p1 to i1
+  %a2 = trunc i32 %p2 to i1
+  %veq = icmp eq i1 %a1, %a2
+  %vne = icmp ne i1 %a1, %a2
+  %vugt = icmp ugt i1 %a1, %a2
+  %vuge = icmp uge i1 %a1, %a2
+  %vult = icmp ult i1 %a1, %a2
+  %vule = icmp ule i1 %a1, %a2
+  %vsgt = icmp sgt i1 %a1, %a2
+  %vsge = icmp sge i1 %a1, %a2
+  %vslt = icmp slt i1 %a1, %a2
+  %vsle = icmp sle i1 %a1, %a2
+  ret i1 %veq
+}
+
+; CHECK: define i1 @IcmpI1(i32 %__0, i32 %__1) {
+; CHECK-NEXT: __0:
+; CHECK-NEXT:   %__2 = trunc i32 %__0 to i1
+; CHECK-NEXT:   %__3 = trunc i32 %__1 to i1
+; CHECK-NEXT:   %__4 = icmp eq i1 %__2, %__3
+; CHECK-NEXT:   %__5 = icmp ne i1 %__2, %__3
+; CHECK-NEXT:   %__6 = icmp ugt i1 %__2, %__3
+; CHECK-NEXT:   %__7 = icmp uge i1 %__2, %__3
+; CHECK-NEXT:   %__8 = icmp ult i1 %__2, %__3
+; CHECK-NEXT:   %__9 = icmp ule i1 %__2, %__3
+; CHECK-NEXT:   %__10 = icmp sgt i1 %__2, %__3
+; CHECK-NEXT:   %__11 = icmp sge i1 %__2, %__3
+; CHECK-NEXT:   %__12 = icmp slt i1 %__2, %__3
+; CHECK-NEXT:   %__13 = icmp sle i1 %__2, %__3
+; CHECK-NEXT:   ret i1 %__4
+; CHECK-NEXT: }
+
+define i1 @IcmpI8(i32 %p1, i32 %p2) {
+  %a1 = trunc i32 %p1 to i8
+  %a2 = trunc i32 %p2 to i8
+  %veq = icmp eq i8 %a1, %a2
+  %vne = icmp ne i8 %a1, %a2
+  %vugt = icmp ugt i8 %a1, %a2
+  %vuge = icmp uge i8 %a1, %a2
+  %vult = icmp ult i8 %a1, %a2
+  %vule = icmp ule i8 %a1, %a2
+  %vsgt = icmp sgt i8 %a1, %a2
+  %vsge = icmp sge i8 %a1, %a2
+  %vslt = icmp slt i8 %a1, %a2
+  %vsle = icmp sle i8 %a1, %a2
+  ret i1 %veq
+}
+
+; CHECK-NEXT: define i1 @IcmpI8(i32 %__0, i32 %__1) {
+; CHECK-NEXT: __0:
+; CHECK-NEXT:   %__2 = trunc i32 %__0 to i8
+; CHECK-NEXT:   %__3 = trunc i32 %__1 to i8
+; CHECK-NEXT:   %__4 = icmp eq i8 %__2, %__3
+; CHECK-NEXT:   %__5 = icmp ne i8 %__2, %__3
+; CHECK-NEXT:   %__6 = icmp ugt i8 %__2, %__3
+; CHECK-NEXT:   %__7 = icmp uge i8 %__2, %__3
+; CHECK-NEXT:   %__8 = icmp ult i8 %__2, %__3
+; CHECK-NEXT:   %__9 = icmp ule i8 %__2, %__3
+; CHECK-NEXT:   %__10 = icmp sgt i8 %__2, %__3
+; CHECK-NEXT:   %__11 = icmp sge i8 %__2, %__3
+; CHECK-NEXT:   %__12 = icmp slt i8 %__2, %__3
+; CHECK-NEXT:   %__13 = icmp sle i8 %__2, %__3
+; CHECK-NEXT:   ret i1 %__4
+; CHECK-NEXT: }
+
+define i1 @IcmpI16(i32 %p1, i32 %p2) {
+  %a1 = trunc i32 %p1 to i16
+  %a2 = trunc i32 %p2 to i16
+  %veq = icmp eq i16 %a1, %a2
+  %vne = icmp ne i16 %a1, %a2
+  %vugt = icmp ugt i16 %a1, %a2
+  %vuge = icmp uge i16 %a1, %a2
+  %vult = icmp ult i16 %a1, %a2
+  %vule = icmp ule i16 %a1, %a2
+  %vsgt = icmp sgt i16 %a1, %a2
+  %vsge = icmp sge i16 %a1, %a2
+  %vslt = icmp slt i16 %a1, %a2
+  %vsle = icmp sle i16 %a1, %a2
+  ret i1 %veq
+}
+
+; CHECK-NEXT: define i1 @IcmpI16(i32 %__0, i32 %__1) {
+; CHECK-NEXT: __0:
+; CHECK-NEXT:   %__2 = trunc i32 %__0 to i16
+; CHECK-NEXT:   %__3 = trunc i32 %__1 to i16
+; CHECK-NEXT:   %__4 = icmp eq i16 %__2, %__3
+; CHECK-NEXT:   %__5 = icmp ne i16 %__2, %__3
+; CHECK-NEXT:   %__6 = icmp ugt i16 %__2, %__3
+; CHECK-NEXT:   %__7 = icmp uge i16 %__2, %__3
+; CHECK-NEXT:   %__8 = icmp ult i16 %__2, %__3
+; CHECK-NEXT:   %__9 = icmp ule i16 %__2, %__3
+; CHECK-NEXT:   %__10 = icmp sgt i16 %__2, %__3
+; CHECK-NEXT:   %__11 = icmp sge i16 %__2, %__3
+; CHECK-NEXT:   %__12 = icmp slt i16 %__2, %__3
+; CHECK-NEXT:   %__13 = icmp sle i16 %__2, %__3
+; CHECK-NEXT:   ret i1 %__4
+; CHECK-NEXT: }
+
+define i1 @IcmpI32(i32 %a1, i32 %a2) {
+  %veq = icmp eq i32 %a1, %a2
+  %vne = icmp ne i32 %a1, %a2
+  %vugt = icmp ugt i32 %a1, %a2
+  %vuge = icmp uge i32 %a1, %a2
+  %vult = icmp ult i32 %a1, %a2
+  %vule = icmp ule i32 %a1, %a2
+  %vsgt = icmp sgt i32 %a1, %a2
+  %vsge = icmp sge i32 %a1, %a2
+  %vslt = icmp slt i32 %a1, %a2
+  %vsle = icmp sle i32 %a1, %a2
+  ret i1 %veq
+}
+
+; CHECK-NEXT: define i1 @IcmpI32(i32 %__0, i32 %__1) {
+; CHECK-NEXT: __0:
+; CHECK-NEXT:   %__2 = icmp eq i32 %__0, %__1
+; CHECK-NEXT:   %__3 = icmp ne i32 %__0, %__1
+; CHECK-NEXT:   %__4 = icmp ugt i32 %__0, %__1
+; CHECK-NEXT:   %__5 = icmp uge i32 %__0, %__1
+; CHECK-NEXT:   %__6 = icmp ult i32 %__0, %__1
+; CHECK-NEXT:   %__7 = icmp ule i32 %__0, %__1
+; CHECK-NEXT:   %__8 = icmp sgt i32 %__0, %__1
+; CHECK-NEXT:   %__9 = icmp sge i32 %__0, %__1
+; CHECK-NEXT:   %__10 = icmp slt i32 %__0, %__1
+; CHECK-NEXT:   %__11 = icmp sle i32 %__0, %__1
+; CHECK-NEXT:   ret i1 %__2
+; CHECK-NEXT: }
+
+define i1 @IcmpI64(i64 %a1, i64 %a2) {
+  %veq = icmp eq i64 %a1, %a2
+  %vne = icmp ne i64 %a1, %a2
+  %vugt = icmp ugt i64 %a1, %a2
+  %vuge = icmp uge i64 %a1, %a2
+  %vult = icmp ult i64 %a1, %a2
+  %vule = icmp ule i64 %a1, %a2
+  %vsgt = icmp sgt i64 %a1, %a2
+  %vsge = icmp sge i64 %a1, %a2
+  %vslt = icmp slt i64 %a1, %a2
+  %vsle = icmp sle i64 %a1, %a2
+  ret i1 %veq
+}
+
+; CHECK-NEXT: define i1 @IcmpI64(i64 %__0, i64 %__1) {
+; CHECK-NEXT: __0:
+; CHECK-NEXT:   %__2 = icmp eq i64 %__0, %__1
+; CHECK-NEXT:   %__3 = icmp ne i64 %__0, %__1
+; CHECK-NEXT:   %__4 = icmp ugt i64 %__0, %__1
+; CHECK-NEXT:   %__5 = icmp uge i64 %__0, %__1
+; CHECK-NEXT:   %__6 = icmp ult i64 %__0, %__1
+; CHECK-NEXT:   %__7 = icmp ule i64 %__0, %__1
+; CHECK-NEXT:   %__8 = icmp sgt i64 %__0, %__1
+; CHECK-NEXT:   %__9 = icmp sge i64 %__0, %__1
+; CHECK-NEXT:   %__10 = icmp slt i64 %__0, %__1
+; CHECK-NEXT:   %__11 = icmp sle i64 %__0, %__1
+; CHECK-NEXT:   ret i1 %__2
+; CHECK-NEXT: }
+
+define <4 x i1> @IcmpV4xI1(<4 x i1> %a1, <4 x i1> %a2) {
+  %veq = icmp eq <4 x i1> %a1, %a2
+  %vne = icmp ne <4 x i1> %a1, %a2
+  %vugt = icmp ugt <4 x i1> %a1, %a2
+  %vuge = icmp uge <4 x i1> %a1, %a2
+  %vult = icmp ult <4 x i1> %a1, %a2
+  %vule = icmp ule <4 x i1> %a1, %a2
+  %vsgt = icmp sgt <4 x i1> %a1, %a2
+  %vsge = icmp sge <4 x i1> %a1, %a2
+  %vslt = icmp slt <4 x i1> %a1, %a2
+  %vsle = icmp sle <4 x i1> %a1, %a2
+  ret <4 x i1> %veq
+}
+
+; CHECK-NEXT: define <4 x i1> @IcmpV4xI1(<4 x i1> %__0, <4 x i1> %__1) {
+; CHECK-NEXT: __0:
+; CHECK-NEXT:   %__2 = icmp eq <4 x i1> %__0, %__1
+; CHECK-NEXT:   %__3 = icmp ne <4 x i1> %__0, %__1
+; CHECK-NEXT:   %__4 = icmp ugt <4 x i1> %__0, %__1
+; CHECK-NEXT:   %__5 = icmp uge <4 x i1> %__0, %__1
+; CHECK-NEXT:   %__6 = icmp ult <4 x i1> %__0, %__1
+; CHECK-NEXT:   %__7 = icmp ule <4 x i1> %__0, %__1
+; CHECK-NEXT:   %__8 = icmp sgt <4 x i1> %__0, %__1
+; CHECK-NEXT:   %__9 = icmp sge <4 x i1> %__0, %__1
+; CHECK-NEXT:   %__10 = icmp slt <4 x i1> %__0, %__1
+; CHECK-NEXT:   %__11 = icmp sle <4 x i1> %__0, %__1
+; CHECK-NEXT:   ret <4 x i1> %__2
+; CHECK-NEXT: }
+
+define <8 x i1> @IcmpV8xI1(<8 x i1> %a1, <8 x i1> %a2) {
+  %veq = icmp eq <8 x i1> %a1, %a2
+  %vne = icmp ne <8 x i1> %a1, %a2
+  %vugt = icmp ugt <8 x i1> %a1, %a2
+  %vuge = icmp uge <8 x i1> %a1, %a2
+  %vult = icmp ult <8 x i1> %a1, %a2
+  %vule = icmp ule <8 x i1> %a1, %a2
+  %vsgt = icmp sgt <8 x i1> %a1, %a2
+  %vsge = icmp sge <8 x i1> %a1, %a2
+  %vslt = icmp slt <8 x i1> %a1, %a2
+  %vsle = icmp sle <8 x i1> %a1, %a2
+  ret <8 x i1> %veq
+}
+
+; CHECK-NEXT: define <8 x i1> @IcmpV8xI1(<8 x i1> %__0, <8 x i1> %__1) {
+; CHECK-NEXT: __0:
+; CHECK-NEXT:   %__2 = icmp eq <8 x i1> %__0, %__1
+; CHECK-NEXT:   %__3 = icmp ne <8 x i1> %__0, %__1
+; CHECK-NEXT:   %__4 = icmp ugt <8 x i1> %__0, %__1
+; CHECK-NEXT:   %__5 = icmp uge <8 x i1> %__0, %__1
+; CHECK-NEXT:   %__6 = icmp ult <8 x i1> %__0, %__1
+; CHECK-NEXT:   %__7 = icmp ule <8 x i1> %__0, %__1
+; CHECK-NEXT:   %__8 = icmp sgt <8 x i1> %__0, %__1
+; CHECK-NEXT:   %__9 = icmp sge <8 x i1> %__0, %__1
+; CHECK-NEXT:   %__10 = icmp slt <8 x i1> %__0, %__1
+; CHECK-NEXT:   %__11 = icmp sle <8 x i1> %__0, %__1
+; CHECK-NEXT:   ret <8 x i1> %__2
+; CHECK-NEXT: }
+
+define <16 x i1> @IcmpV16xI1(<16 x i1> %a1, <16 x i1> %a2) {
+  %veq = icmp eq <16 x i1> %a1, %a2
+  %vne = icmp ne <16 x i1> %a1, %a2
+  %vugt = icmp ugt <16 x i1> %a1, %a2
+  %vuge = icmp uge <16 x i1> %a1, %a2
+  %vult = icmp ult <16 x i1> %a1, %a2
+  %vule = icmp ule <16 x i1> %a1, %a2
+  %vsgt = icmp sgt <16 x i1> %a1, %a2
+  %vsge = icmp sge <16 x i1> %a1, %a2
+  %vslt = icmp slt <16 x i1> %a1, %a2
+  %vsle = icmp sle <16 x i1> %a1, %a2
+  ret <16 x i1> %veq
+}
+
+; CHECK-NEXT: define <16 x i1> @IcmpV16xI1(<16 x i1> %__0, <16 x i1> %__1) {
+; CHECK-NEXT: __0:
+; CHECK-NEXT:   %__2 = icmp eq <16 x i1> %__0, %__1
+; CHECK-NEXT:   %__3 = icmp ne <16 x i1> %__0, %__1
+; CHECK-NEXT:   %__4 = icmp ugt <16 x i1> %__0, %__1
+; CHECK-NEXT:   %__5 = icmp uge <16 x i1> %__0, %__1
+; CHECK-NEXT:   %__6 = icmp ult <16 x i1> %__0, %__1
+; CHECK-NEXT:   %__7 = icmp ule <16 x i1> %__0, %__1
+; CHECK-NEXT:   %__8 = icmp sgt <16 x i1> %__0, %__1
+; CHECK-NEXT:   %__9 = icmp sge <16 x i1> %__0, %__1
+; CHECK-NEXT:   %__10 = icmp slt <16 x i1> %__0, %__1
+; CHECK-NEXT:   %__11 = icmp sle <16 x i1> %__0, %__1
+; CHECK-NEXT:   ret <16 x i1> %__2
+; CHECK-NEXT: }
+
+define <16 x i1> @IcmpV16xI8(<16 x i8> %a1, <16 x i8> %a2) {
+  %veq = icmp eq <16 x i8> %a1, %a2
+  %vne = icmp ne <16 x i8> %a1, %a2
+  %vugt = icmp ugt <16 x i8> %a1, %a2
+  %vuge = icmp uge <16 x i8> %a1, %a2
+  %vult = icmp ult <16 x i8> %a1, %a2
+  %vule = icmp ule <16 x i8> %a1, %a2
+  %vsgt = icmp sgt <16 x i8> %a1, %a2
+  %vsge = icmp sge <16 x i8> %a1, %a2
+  %vslt = icmp slt <16 x i8> %a1, %a2
+  %vsle = icmp sle <16 x i8> %a1, %a2
+  ret <16 x i1> %veq
+}
+
+; CHECK-NEXT: define <16 x i1> @IcmpV16xI8(<16 x i8> %__0, <16 x i8> %__1) {
+; CHECK-NEXT: __0:
+; CHECK-NEXT:   %__2 = icmp eq <16 x i8> %__0, %__1
+; CHECK-NEXT:   %__3 = icmp ne <16 x i8> %__0, %__1
+; CHECK-NEXT:   %__4 = icmp ugt <16 x i8> %__0, %__1
+; CHECK-NEXT:   %__5 = icmp uge <16 x i8> %__0, %__1
+; CHECK-NEXT:   %__6 = icmp ult <16 x i8> %__0, %__1
+; CHECK-NEXT:   %__7 = icmp ule <16 x i8> %__0, %__1
+; CHECK-NEXT:   %__8 = icmp sgt <16 x i8> %__0, %__1
+; CHECK-NEXT:   %__9 = icmp sge <16 x i8> %__0, %__1
+; CHECK-NEXT:   %__10 = icmp slt <16 x i8> %__0, %__1
+; CHECK-NEXT:   %__11 = icmp sle <16 x i8> %__0, %__1
+; CHECK-NEXT:   ret <16 x i1> %__2
+; CHECK-NEXT: }
+
+define <8 x i1> @IcmpV8xI16(<8 x i16> %a1, <8 x i16> %a2) {
+  %veq = icmp eq <8 x i16> %a1, %a2
+  %vne = icmp ne <8 x i16> %a1, %a2
+  %vugt = icmp ugt <8 x i16> %a1, %a2
+  %vuge = icmp uge <8 x i16> %a1, %a2
+  %vult = icmp ult <8 x i16> %a1, %a2
+  %vule = icmp ule <8 x i16> %a1, %a2
+  %vsgt = icmp sgt <8 x i16> %a1, %a2
+  %vsge = icmp sge <8 x i16> %a1, %a2
+  %vslt = icmp slt <8 x i16> %a1, %a2
+  %vsle = icmp sle <8 x i16> %a1, %a2
+  ret <8 x i1> %veq
+}
+
+; CHECK-NEXT: define <8 x i1> @IcmpV8xI16(<8 x i16> %__0, <8 x i16> %__1) {
+; CHECK-NEXT: __0:
+; CHECK-NEXT:   %__2 = icmp eq <8 x i16> %__0, %__1
+; CHECK-NEXT:   %__3 = icmp ne <8 x i16> %__0, %__1
+; CHECK-NEXT:   %__4 = icmp ugt <8 x i16> %__0, %__1
+; CHECK-NEXT:   %__5 = icmp uge <8 x i16> %__0, %__1
+; CHECK-NEXT:   %__6 = icmp ult <8 x i16> %__0, %__1
+; CHECK-NEXT:   %__7 = icmp ule <8 x i16> %__0, %__1
+; CHECK-NEXT:   %__8 = icmp sgt <8 x i16> %__0, %__1
+; CHECK-NEXT:   %__9 = icmp sge <8 x i16> %__0, %__1
+; CHECK-NEXT:   %__10 = icmp slt <8 x i16> %__0, %__1
+; CHECK-NEXT:   %__11 = icmp sle <8 x i16> %__0, %__1
+; CHECK-NEXT:   ret <8 x i1> %__2
+; CHECK-NEXT: }
+
+define <4 x i1> @IcmpV4xI32(<4 x i32> %a1, <4 x i32> %a2) {
+  %veq = icmp eq <4 x i32> %a1, %a2
+  %vne = icmp ne <4 x i32> %a1, %a2
+  %vugt = icmp ugt <4 x i32> %a1, %a2
+  %vuge = icmp uge <4 x i32> %a1, %a2
+  %vult = icmp ult <4 x i32> %a1, %a2
+  %vule = icmp ule <4 x i32> %a1, %a2
+  %vsgt = icmp sgt <4 x i32> %a1, %a2
+  %vsge = icmp sge <4 x i32> %a1, %a2
+  %vslt = icmp slt <4 x i32> %a1, %a2
+  %vsle = icmp sle <4 x i32> %a1, %a2
+  ret <4 x i1> %veq
+}
+
+; CHECK-NEXT: define <4 x i1> @IcmpV4xI32(<4 x i32> %__0, <4 x i32> %__1) {
+; CHECK-NEXT: __0:
+; CHECK-NEXT:   %__2 = icmp eq <4 x i32> %__0, %__1
+; CHECK-NEXT:   %__3 = icmp ne <4 x i32> %__0, %__1
+; CHECK-NEXT:   %__4 = icmp ugt <4 x i32> %__0, %__1
+; CHECK-NEXT:   %__5 = icmp uge <4 x i32> %__0, %__1
+; CHECK-NEXT:   %__6 = icmp ult <4 x i32> %__0, %__1
+; CHECK-NEXT:   %__7 = icmp ule <4 x i32> %__0, %__1
+; CHECK-NEXT:   %__8 = icmp sgt <4 x i32> %__0, %__1
+; CHECK-NEXT:   %__9 = icmp sge <4 x i32> %__0, %__1
+; CHECK-NEXT:   %__10 = icmp slt <4 x i32> %__0, %__1
+; CHECK-NEXT:   %__11 = icmp sle <4 x i32> %__0, %__1
+; CHECK-NEXT:   ret <4 x i1> %__2
+; CHECK-NEXT: }
+
+define i1 @FcmpFloat(float %a1, float %a2) {
+  %vfalse = fcmp false float %a1, %a2
+  %voeq = fcmp oeq float %a1, %a2
+  %vogt = fcmp ogt float %a1, %a2
+  %voge = fcmp oge float %a1, %a2
+  %volt = fcmp olt float %a1, %a2
+  %vole = fcmp ole float %a1, %a2
+  %vone = fcmp one float %a1, %a2
+  %ord = fcmp ord float %a1, %a2
+  %vueq = fcmp ueq float %a1, %a2
+  %vugt = fcmp ugt float %a1, %a2
+  %vuge = fcmp uge float %a1, %a2
+  %vult = fcmp ult float %a1, %a2
+  %vule = fcmp ule float %a1, %a2
+  %vune = fcmp une float %a1, %a2
+  %vuno = fcmp uno float %a1, %a2
+  %vtrue = fcmp true float %a1, %a2
+  ret i1 %voeq
+}
+
+; CHECK-NEXT: define i1 @FcmpFloat(float %__0, float %__1) {
+; CHECK-NEXT: __0:
+; CHECK-NEXT:   %__2 = fcmp false float %__0, %__1
+; CHECK-NEXT:   %__3 = fcmp oeq float %__0, %__1
+; CHECK-NEXT:   %__4 = fcmp ogt float %__0, %__1
+; CHECK-NEXT:   %__5 = fcmp oge float %__0, %__1
+; CHECK-NEXT:   %__6 = fcmp olt float %__0, %__1
+; CHECK-NEXT:   %__7 = fcmp ole float %__0, %__1
+; CHECK-NEXT:   %__8 = fcmp one float %__0, %__1
+; CHECK-NEXT:   %__9 = fcmp ord float %__0, %__1
+; CHECK-NEXT:   %__10 = fcmp ueq float %__0, %__1
+; CHECK-NEXT:   %__11 = fcmp ugt float %__0, %__1
+; CHECK-NEXT:   %__12 = fcmp uge float %__0, %__1
+; CHECK-NEXT:   %__13 = fcmp ult float %__0, %__1
+; CHECK-NEXT:   %__14 = fcmp ule float %__0, %__1
+; CHECK-NEXT:   %__15 = fcmp une float %__0, %__1
+; CHECK-NEXT:   %__16 = fcmp uno float %__0, %__1
+; CHECK-NEXT:   %__17 = fcmp true float %__0, %__1
+; CHECK-NEXT:   ret i1 %__3
+; CHECK-NEXT: }
+
+define i1 @FcmpDouble(double %a1, double %a2) {
+  %vfalse = fcmp false double %a1, %a2
+  %voeq = fcmp oeq double %a1, %a2
+  %vogt = fcmp ogt double %a1, %a2
+  %voge = fcmp oge double %a1, %a2
+  %volt = fcmp olt double %a1, %a2
+  %vole = fcmp ole double %a1, %a2
+  %vone = fcmp one double %a1, %a2
+  %ord = fcmp ord double %a1, %a2
+  %vueq = fcmp ueq double %a1, %a2
+  %vugt = fcmp ugt double %a1, %a2
+  %vuge = fcmp uge double %a1, %a2
+  %vult = fcmp ult double %a1, %a2
+  %vule = fcmp ule double %a1, %a2
+  %vune = fcmp une double %a1, %a2
+  %vuno = fcmp uno double %a1, %a2
+  %vtrue = fcmp true double %a1, %a2
+  ret i1 %voeq
+}
+
+; CHECK-NEXT: define i1 @FcmpDouble(double %__0, double %__1) {
+; CHECK-NEXT: __0:
+; CHECK-NEXT:   %__2 = fcmp false double %__0, %__1
+; CHECK-NEXT:   %__3 = fcmp oeq double %__0, %__1
+; CHECK-NEXT:   %__4 = fcmp ogt double %__0, %__1
+; CHECK-NEXT:   %__5 = fcmp oge double %__0, %__1
+; CHECK-NEXT:   %__6 = fcmp olt double %__0, %__1
+; CHECK-NEXT:   %__7 = fcmp ole double %__0, %__1
+; CHECK-NEXT:   %__8 = fcmp one double %__0, %__1
+; CHECK-NEXT:   %__9 = fcmp ord double %__0, %__1
+; CHECK-NEXT:   %__10 = fcmp ueq double %__0, %__1
+; CHECK-NEXT:   %__11 = fcmp ugt double %__0, %__1
+; CHECK-NEXT:   %__12 = fcmp uge double %__0, %__1
+; CHECK-NEXT:   %__13 = fcmp ult double %__0, %__1
+; CHECK-NEXT:   %__14 = fcmp ule double %__0, %__1
+; CHECK-NEXT:   %__15 = fcmp une double %__0, %__1
+; CHECK-NEXT:   %__16 = fcmp uno double %__0, %__1
+; CHECK-NEXT:   %__17 = fcmp true double %__0, %__1
+; CHECK-NEXT:   ret i1 %__3
+; CHECK-NEXT: }
+
+define <4 x i1> @FcmpV4xFloat(<4 x float> %a1, <4 x float> %a2) {
+  %vfalse = fcmp false <4 x float> %a1, %a2
+  %voeq = fcmp oeq <4 x float> %a1, %a2
+  %vogt = fcmp ogt <4 x float> %a1, %a2
+  %voge = fcmp oge <4 x float> %a1, %a2
+  %volt = fcmp olt <4 x float> %a1, %a2
+  %vole = fcmp ole <4 x float> %a1, %a2
+  %vone = fcmp one <4 x float> %a1, %a2
+  %ord = fcmp ord <4 x float> %a1, %a2
+  %vueq = fcmp ueq <4 x float> %a1, %a2
+  %vugt = fcmp ugt <4 x float> %a1, %a2
+  %vuge = fcmp uge <4 x float> %a1, %a2
+  %vult = fcmp ult <4 x float> %a1, %a2
+  %vule = fcmp ule <4 x float> %a1, %a2
+  %vune = fcmp une <4 x float> %a1, %a2
+  %vuno = fcmp uno <4 x float> %a1, %a2
+  %vtrue = fcmp true <4 x float> %a1, %a2
+  ret <4 x i1> %voeq
+}
+
+; CHECK-NEXT: define <4 x i1> @FcmpV4xFloat(<4 x float> %__0, <4 x float> %__1) {
+; CHECK-NEXT: __0:
+; CHECK-NEXT:   %__2 = fcmp false <4 x float> %__0, %__1
+; CHECK-NEXT:   %__3 = fcmp oeq <4 x float> %__0, %__1
+; CHECK-NEXT:   %__4 = fcmp ogt <4 x float> %__0, %__1
+; CHECK-NEXT:   %__5 = fcmp oge <4 x float> %__0, %__1
+; CHECK-NEXT:   %__6 = fcmp olt <4 x float> %__0, %__1
+; CHECK-NEXT:   %__7 = fcmp ole <4 x float> %__0, %__1
+; CHECK-NEXT:   %__8 = fcmp one <4 x float> %__0, %__1
+; CHECK-NEXT:   %__9 = fcmp ord <4 x float> %__0, %__1
+; CHECK-NEXT:   %__10 = fcmp ueq <4 x float> %__0, %__1
+; CHECK-NEXT:   %__11 = fcmp ugt <4 x float> %__0, %__1
+; CHECK-NEXT:   %__12 = fcmp uge <4 x float> %__0, %__1
+; CHECK-NEXT:   %__13 = fcmp ult <4 x float> %__0, %__1
+; CHECK-NEXT:   %__14 = fcmp ule <4 x float> %__0, %__1
+; CHECK-NEXT:   %__15 = fcmp une <4 x float> %__0, %__1
+; CHECK-NEXT:   %__16 = fcmp uno <4 x float> %__0, %__1
+; CHECK-NEXT:   %__17 = fcmp true <4 x float> %__0, %__1
+; CHECK-NEXT:   ret <4 x i1> %__3
+; CHECK-NEXT: }