summaryrefslogtreecommitdiff
path: root/src/jit/gentree.h
diff options
context:
space:
mode:
authorMike Danes <onemihaid@hotmail.com>2018-04-23 18:17:52 +0300
committerMike Danes <onemihaid@hotmail.com>2018-11-10 19:00:12 +0200
commit3b24ec21079c2c45c0186586ef17632e85875e39 (patch)
tree327189c5a46465b73097217133fd304900524098 /src/jit/gentree.h
parent54fba14273fe9b6f53d68c98920f0ee1ecb2dd04 (diff)
downloadcoreclr-3b24ec21079c2c45c0186586ef17632e85875e39.tar.gz
coreclr-3b24ec21079c2c45c0186586ef17632e85875e39.tar.bz2
coreclr-3b24ec21079c2c45c0186586ef17632e85875e39.zip
Introduce GenCondition
Diffstat (limited to 'src/jit/gentree.h')
-rw-r--r--src/jit/gentree.h212
1 files changed, 209 insertions, 3 deletions
diff --git a/src/jit/gentree.h b/src/jit/gentree.h
index c6c5841e98..099e399c10 100644
--- a/src/jit/gentree.h
+++ b/src/jit/gentree.h
@@ -5663,17 +5663,223 @@ struct GenTreeRuntimeLookup final : public GenTreeUnOp
}
};
+// Represents the condition of a GT_JCC or GT_SETCC node.
+
+struct GenCondition
+{
+ // clang-format off
+ enum Code : unsigned char
+ {
+ OperMask = 7,
+ Unsigned = 8,
+ Unordered = Unsigned,
+ Float = 16,
+
+ // 0 would be the encoding of "signed EQ" but since equality is sign insensitive
+ // we'll use 0 as invalid/uninitialized condition code. This will also leave 1
+ // as a spare code.
+ NONE = 0,
+
+ SLT = 2,
+ SLE = 3,
+ SGE = 4,
+ SGT = 5,
+ S = 6,
+ NS = 7,
+
+ EQ = Unsigned | 0, // = 8
+ NE = Unsigned | 1, // = 9
+ ULT = Unsigned | SLT, // = 10
+ ULE = Unsigned | SLE, // = 11
+ UGE = Unsigned | SGE, // = 12
+ UGT = Unsigned | SGT, // = 13
+ C = Unsigned | S, // = 14
+ NC = Unsigned | NS, // = 15
+
+ FEQ = Float | EQ, // = 16
+ FNE = Float | NE, // = 17
+ FLT = Float | SLT, // = 18
+ FLE = Float | SLE, // = 19
+ FGE = Float | SGE, // = 20
+ FGT = Float | SGT, // = 21
+ O = Float | S, // = 22
+ NO = Float | NS, // = 23
+
+ FEQU = Unordered | FEQ, // = 24
+ FNEU = Unordered | FNE, // = 25
+ FLTU = Unordered | FLT, // = 26
+ FLEU = Unordered | FLE, // = 27
+ FGEU = Unordered | FGE, // = 28
+ FGTU = Unordered | FGT, // = 29
+ P = Unordered | O, // = 30
+ NP = Unordered | NO, // = 31
+ };
+ // clang-format on
+
+private:
+ Code m_code;
+
+public:
+ Code GetCode() const
+ {
+ return m_code;
+ }
+
+ bool IsFlag() const
+ {
+ return (m_code & OperMask) >= S;
+ }
+
+ bool IsUnsigned() const
+ {
+ return (ULT <= m_code) && (m_code <= UGT);
+ }
+
+ bool IsFloat() const
+ {
+ return !IsFlag() && (m_code & Float) != 0;
+ }
+
+ bool IsUnordered() const
+ {
+ return !IsFlag() && (m_code & (Float | Unordered)) == (Float | Unordered);
+ }
+
+ bool Is(Code cond) const
+ {
+ return m_code == cond;
+ }
+
+ template <typename... TRest>
+ bool Is(Code c, TRest... rest) const
+ {
+ return Is(c) || Is(rest...);
+ }
+
+ const char* Name() const
+ {
+ // clang-format off
+ static const char* names[]
+ {
+ "NONE", "???", "SLT", "SLE", "SGE", "SGT", "S", "NS",
+ "UEQ", "UNE", "ULT", "ULE", "UGE", "UGT", "C", "NC",
+ "FEQ", "FNE", "FLT", "FLE", "FGE", "FGT", "O", "NO",
+ "FEQU", "FNEU", "FLTU", "FLEU", "FGEU", "FGTU", "P", "NP"
+ };
+ // clang-format on
+
+ assert(m_code < _countof(names));
+ return names[m_code];
+ }
+
+ GenCondition() : m_code()
+ {
+ }
+
+ GenCondition(Code cond) : m_code(cond)
+ {
+ }
+
+ static_assert((GT_NE - GT_EQ) == (NE & ~Unsigned), "bad relop");
+ static_assert((GT_LT - GT_EQ) == SLT, "bad relop");
+ static_assert((GT_LE - GT_EQ) == SLE, "bad relop");
+ static_assert((GT_GE - GT_EQ) == SGE, "bad relop");
+ static_assert((GT_GT - GT_EQ) == SGT, "bad relop");
+#ifndef LEGACY_BACKEND
+ static_assert((GT_TEST_NE - GT_TEST_EQ) == (NE & ~Unsigned), "bad relop");
+#endif
+
+ static GenCondition FromRelop(GenTree* relop)
+ {
+ assert(relop->OperIsCompare());
+
+ if (varTypeIsFloating(relop->gtGetOp1()))
+ {
+ return FromFloatRelop(relop);
+ }
+ else
+ {
+ return FromIntegralRelop(relop);
+ }
+ }
+
+ static GenCondition FromFloatRelop(GenTree* relop)
+ {
+ assert(varTypeIsFloating(relop->gtGetOp1()) && varTypeIsFloating(relop->gtGetOp2()));
+
+ return FromFloatRelop(relop->OperGet(), (relop->gtFlags & GTF_RELOP_NAN_UN) != 0);
+ }
+
+ static GenCondition FromFloatRelop(genTreeOps oper, bool isUnordered)
+ {
+ assert(GenTree::OperIsCompare(oper));
+
+ unsigned code = oper - GT_EQ;
+ assert(code <= SGT);
+ code |= Float;
+
+ if (isUnordered)
+ {
+ code |= Unordered;
+ }
+
+ return GenCondition(static_cast<Code>(code));
+ }
+
+ static GenCondition FromIntegralRelop(GenTree* relop)
+ {
+ assert(!varTypeIsFloating(relop->gtGetOp1()) && !varTypeIsFloating(relop->gtGetOp2()));
+
+ return FromIntegralRelop(relop->OperGet(), relop->IsUnsigned());
+ }
+
+ static GenCondition FromIntegralRelop(genTreeOps oper, bool isUnsigned)
+ {
+ assert(GenTree::OperIsCompare(oper));
+
+#ifndef LEGACY_BACKEND
+ // GT_TEST_EQ/NE are special, they need to be mapped as GT_EQ/NE
+ unsigned code = oper - ((oper >= GT_TEST_EQ) ? GT_TEST_EQ : GT_EQ);
+#else
+ unsigned code = oper - GT_EQ;
+#endif
+
+ if (isUnsigned || (code <= 1)) // EQ/NE are treated as unsigned
+ {
+ code |= Unsigned;
+ }
+
+ return GenCondition(static_cast<Code>(code));
+ }
+
+ static GenCondition Reverse(GenCondition condition)
+ {
+ // clang-format off
+ static const Code reverse[]
+ {
+ // EQ NE LT LE GE GT F NF
+ NONE, NONE, SGE, SGT, SLT, SLE, NS, S,
+ NE, EQ, UGE, UGT, ULT, ULE, NC, C,
+ FNEU, FEQU, FGEU, FGTU, FLTU, FLEU, NO, O,
+ FNE, FEQ, FGE, FGT, FLT, FGT, NP, P
+ };
+ // clang-format on
+
+ assert(condition.m_code < _countof(reverse));
+ return GenCondition(reverse[condition.m_code]);
+ }
+};
+
// Represents a GT_JCC or GT_SETCC node.
struct GenTreeCC final : public GenTree
{
- genTreeOps gtCondition; // any relop
+ GenCondition gtCondition;
- GenTreeCC(genTreeOps oper, genTreeOps condition, var_types type = TYP_VOID)
+ GenTreeCC(genTreeOps oper, GenCondition condition, var_types type = TYP_VOID)
: GenTree(oper, type DEBUGARG(/*largeNode*/ FALSE)), gtCondition(condition)
{
assert(OperIs(GT_JCC, GT_SETCC));
- assert(OperIsCompare(condition));
}
#if DEBUGGABLE_GENTREE