Commit 83f9f0c1 by Karl Schimpf

Add icmp and fcmp instructions to Subzero bitcode reader.

parent dd30c81e
...@@ -33,7 +33,8 @@ void __attribute__((unused)) xIceTypeMacroIntegrityCheck() { ...@@ -33,7 +33,8 @@ void __attribute__((unused)) xIceTypeMacroIntegrityCheck() {
}; };
// Define a temporary set of enum values based on ICETYPE_PROPS_TABLE // Define a temporary set of enum values based on ICETYPE_PROPS_TABLE
enum { 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 ICETYPE_PROPS_TABLE
#undef X #undef X
_enum_props_table_tag_Names _enum_props_table_tag_Names
...@@ -44,7 +45,7 @@ void __attribute__((unused)) xIceTypeMacroIntegrityCheck() { ...@@ -44,7 +45,7 @@ void __attribute__((unused)) xIceTypeMacroIntegrityCheck() {
ICETYPE_TABLE; ICETYPE_TABLE;
#undef X #undef X
// Assert that tags in ICETYPE_PROPS_TABLE is in ICETYPE_TABLE. // 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); STATIC_ASSERT((unsigned)_table_tag_##tag == (unsigned)_props_table_tag_##tag);
ICETYPE_PROPS_TABLE; ICETYPE_PROPS_TABLE;
#undef X #undef X
...@@ -61,13 +62,13 @@ void __attribute__((unused)) xIceTypeMacroIntegrityCheck() { ...@@ -61,13 +62,13 @@ void __attribute__((unused)) xIceTypeMacroIntegrityCheck() {
}; };
// Define constants for boolean flag if vector in ICETYPE_PROPS_TABLE. // Define constants for boolean flag if vector in ICETYPE_PROPS_TABLE.
enum { enum {
#define X(tag, IsVec, IsInt, IsFloat, IsIntArith) \ #define X(tag, IsVec, IsInt, IsFloat, IsIntArith, CompareResult) \
_props_table_IsVec_##tag = IsVec, _props_table_IsVec_##tag = IsVec,
ICETYPE_PROPS_TABLE ICETYPE_PROPS_TABLE
#undef X #undef X
}; };
// Verify that the number of vector elements is consistent with IsVec. // 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); STATIC_ASSERT((_table_elts_##tag > 1) == _props_table_IsVec_##tag);
ICETYPE_PROPS_TABLE; ICETYPE_PROPS_TABLE;
#undef X #undef X
...@@ -98,13 +99,14 @@ struct TypePropertyFields { ...@@ -98,13 +99,14 @@ struct TypePropertyFields {
bool TypeIsFloatingType; bool TypeIsFloatingType;
bool TypeIsScalarFloatingType; bool TypeIsScalarFloatingType;
bool TypeIsVectorFloatingType; bool TypeIsVectorFloatingType;
Type CompareResultType;
}; };
const TypePropertyFields TypePropertiesTable[] = { 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, \ IsVec, IsInt, IsInt && !IsVec, IsInt && IsVec, IsIntArith, IsFloat, \
IsFloat && !IsVec, IsFloat && IsVec \ IsFloat && !IsVec, IsFloat && IsVec, CompareResult \
} \ } \
, ,
ICETYPE_PROPS_TABLE ICETYPE_PROPS_TABLE
...@@ -209,6 +211,14 @@ bool isVectorFloatingType(Type Ty) { ...@@ -209,6 +211,14 @@ bool isVectorFloatingType(Type Ty) {
return false; 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 ======================== // // ======================== Dump routines ======================== //
const char *typeString(Type Ty) { const char *typeString(Type Ty) {
......
...@@ -40,23 +40,25 @@ ...@@ -40,23 +40,25 @@
// I - Is integer value (scalar or vector). // I - Is integer value (scalar or vector).
// F - Is floating point value (scalar or vector). // F - Is floating point value (scalar or vector).
// IA - Is integer arithmetic type // IA - Is integer arithmetic type
// CR - Result type of compare instruction for argument type
// (IceType_void if disallowed)
#define ICETYPE_PROPS_TABLE \ #define ICETYPE_PROPS_TABLE \
/* Enum Value V I F IA */ \ /* Enum Value V I F IA CR */ \
X(IceType_void, 0, 0, 0, 0) \ X(IceType_void, 0, 0, 0, 0, IceType_void) \
X(IceType_i1, 0, 1, 0, 0) \ X(IceType_i1, 0, 1, 0, 0, IceType_i1) \
X(IceType_i8, 0, 1, 0, 1) \ X(IceType_i8, 0, 1, 0, 1, IceType_i1) \
X(IceType_i16, 0, 1, 0, 1) \ X(IceType_i16, 0, 1, 0, 1, IceType_i1) \
X(IceType_i32, 0, 1, 0, 1) \ X(IceType_i32, 0, 1, 0, 1, IceType_i1) \
X(IceType_i64, 0, 1, 0, 1) \ X(IceType_i64, 0, 1, 0, 1, IceType_i1) \
X(IceType_f32, 0, 0, 1, 0) \ X(IceType_f32, 0, 0, 1, 0, IceType_i1) \
X(IceType_f64, 0, 0, 1, 0) \ X(IceType_f64, 0, 0, 1, 0, IceType_i1) \
X(IceType_v4i1, 1, 1, 0, 0) \ X(IceType_v4i1, 1, 1, 0, 0, IceType_v4i1) \
X(IceType_v8i1, 1, 1, 0, 0) \ X(IceType_v8i1, 1, 1, 0, 0, IceType_v8i1) \
X(IceType_v16i1, 1, 1, 0, 0) \ X(IceType_v16i1, 1, 1, 0, 0, IceType_v16i1) \
X(IceType_v16i8, 1, 1, 0, 1) \ X(IceType_v16i8, 1, 1, 0, 1, IceType_v16i1) \
X(IceType_v8i16, 1, 1, 0, 1) \ X(IceType_v8i16, 1, 1, 0, 1, IceType_v8i1) \
X(IceType_v4i32, 1, 1, 0, 1) \ X(IceType_v4i32, 1, 1, 0, 1, IceType_v4i1) \
X(IceType_v4f32, 1, 0, 1, 0) \ X(IceType_v4f32, 1, 0, 1, 0, IceType_v4i1) \
//#define X(tag, IsVec, IsInt, IsFloat, IsIntArith) //#define X(tag, IsVec, IsInt, IsFloat, IsIntArith, CompareResult)
#endif // SUBZERO_SRC_ICETYPES_DEF #endif // SUBZERO_SRC_ICETYPES_DEF
...@@ -58,6 +58,11 @@ bool isFloatingType(Type Ty); // scalar or vector ...@@ -58,6 +58,11 @@ bool isFloatingType(Type Ty); // scalar or vector
bool isScalarFloatingType(Type Ty); bool isScalarFloatingType(Type Ty);
bool isVectorFloatingType(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> template <typename StreamType>
inline StreamType &operator<<(StreamType &Str, const Type &Ty) { inline StreamType &operator<<(StreamType &Str, const Type &Ty) {
Str << typeString(Ty); Str << typeString(Ty);
......
...@@ -1034,7 +1034,7 @@ private: ...@@ -1034,7 +1034,7 @@ private:
/// cast opcode and assigns to CastKind. Returns true if successful, /// cast opcode and assigns to CastKind. Returns true if successful,
/// false otherwise. /// false otherwise.
bool convertLLVMCastOpToIceOp(Instruction::CastOps LLVMCastOp, bool convertLLVMCastOpToIceOp(Instruction::CastOps LLVMCastOp,
Ice::InstCast::OpKind &CastKind) { Ice::InstCast::OpKind &CastKind) const {
switch (LLVMCastOp) { switch (LLVMCastOp) {
case Instruction::ZExt: case Instruction::ZExt:
CastKind = Ice::InstCast::Zext; CastKind = Ice::InstCast::Zext;
...@@ -1071,6 +1071,104 @@ private: ...@@ -1071,6 +1071,104 @@ private:
} }
return true; 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() { FunctionParser::~FunctionParser() {
...@@ -1238,6 +1336,8 @@ void FunctionParser::ProcessRecord() { ...@@ -1238,6 +1336,8 @@ void FunctionParser::ProcessRecord() {
} }
case naclbitc::FUNC_CODE_INST_EXTRACTELT: { case naclbitc::FUNC_CODE_INST_EXTRACTELT: {
// EXTRACTELT: [opval, opval] // EXTRACTELT: [opval, opval]
if (!isValidRecordSize(2, "function block extract element"))
return;
Ice::Operand *Vec = getRelativeOperand(Values[0]); Ice::Operand *Vec = getRelativeOperand(Values[0]);
Ice::Type VecType = Vec->getType(); Ice::Type VecType = Vec->getType();
if (!Ice::isVectorType(VecType)) { if (!Ice::isVectorType(VecType)) {
...@@ -1261,6 +1361,8 @@ void FunctionParser::ProcessRecord() { ...@@ -1261,6 +1361,8 @@ void FunctionParser::ProcessRecord() {
} }
case naclbitc::FUNC_CODE_INST_INSERTELT: { case naclbitc::FUNC_CODE_INST_INSERTELT: {
// INSERTELT: [opval, opval, opval] // INSERTELT: [opval, opval, opval]
if (!isValidRecordSize(3, "function block insert element"))
return;
Ice::Operand *Vec = getRelativeOperand(Values[0]); Ice::Operand *Vec = getRelativeOperand(Values[0]);
Ice::Type VecType = Vec->getType(); Ice::Type VecType = Vec->getType();
if (!Ice::isVectorType(VecType)) { if (!Ice::isVectorType(VecType)) {
...@@ -1291,6 +1393,66 @@ void FunctionParser::ProcessRecord() { ...@@ -1291,6 +1393,66 @@ void FunctionParser::ProcessRecord() {
Inst = Ice::InstInsertElement::create(Func, Dest, Vec, Elt, Index); Inst = Ice::InstInsertElement::create(Func, Dest, Vec, Elt, Index);
break; 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: { case naclbitc::FUNC_CODE_INST_RET: {
// RET: [opval?] // RET: [opval?]
InstIsTerminating = true; InstIsTerminating = true;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment