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: }