Commit 83f9f0c1 by Karl Schimpf

Add icmp and fcmp instructions to Subzero bitcode reader.

parent dd30c81e
......@@ -33,7 +33,8 @@ void __attribute__((unused)) xIceTypeMacroIntegrityCheck() {
};
// 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 @@ void __attribute__((unused)) xIceTypeMacroIntegrityCheck() {
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 @@ void __attribute__((unused)) xIceTypeMacroIntegrityCheck() {
};
// 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 @@ struct TypePropertyFields {
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 @@ bool isVectorFloatingType(Type Ty) {
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) {
......
......@@ -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
......@@ -58,6 +58,11 @@ bool isFloatingType(Type Ty); // scalar or vector
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);
......
......@@ -1034,7 +1034,7 @@ private:
/// 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 @@ private:
}
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 @@ void FunctionParser::ProcessRecord() {
}
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 @@ void FunctionParser::ProcessRecord() {
}
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 @@ void FunctionParser::ProcessRecord() {
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;
......
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