Implement GT_NEG decomposition
authorMike Danes <onemihaid@hotmail.com>
Thu, 23 Jun 2016 19:02:50 +0000 (22:02 +0300)
committerMike Danes <onemihaid@hotmail.com>
Tue, 12 Jul 2016 04:24:05 +0000 (07:24 +0300)
src/jit/decomposelongs.cpp
src/jit/decomposelongs.h
src/jit/lower.cpp [changed mode: 0755->0644]

index f505ed0..988d071 100644 (file)
@@ -219,7 +219,7 @@ void DecomposeLongs::DecomposeNode(GenTree** ppTree, Compiler::fgWalkData* data)
         break;
 
     case GT_NEG:
-        NYI("GT_NEG of TYP_LONG");
+        DecomposeNeg(ppTree, data);
         break;
 
     // Binary operators. Those that require different computation for upper and lower half are
@@ -905,6 +905,56 @@ void DecomposeLongs::DecomposeNot(GenTree** ppTree, Compiler::fgWalkData* data)
     FinalizeDecomposition(ppTree, data, loResult, hiResult);
 }
 
+//------------------------------------------------------------------------
+// DecomposeNeg: Decompose GT_NEG.
+//
+// Arguments:
+//    ppTree - the tree to decompose
+//    data - tree walk context
+//
+// Return Value:
+//    None.
+//
+void DecomposeLongs::DecomposeNeg(GenTree** ppTree, Compiler::fgWalkData* data)
+{
+    assert(ppTree != nullptr);
+    assert(*ppTree != nullptr);
+    assert(data != nullptr);
+    assert((*ppTree)->OperGet() == GT_NEG);
+    assert(m_compiler->compCurStmt != nullptr);
+
+    GenTreeStmt* curStmt = m_compiler->compCurStmt->AsStmt();
+    GenTree* tree = *ppTree;
+    GenTree* op1 = tree->gtGetOp1();
+    noway_assert(op1->OperGet() == GT_LONG);
+
+    CreateTemporary(&(op1->gtOp.gtOp1));
+    CreateTemporary(&(op1->gtOp.gtOp2));
+    // Neither GT_NEG nor the introduced temporaries have side effects.
+    tree->gtFlags &= ~GTF_ALL_EFFECT;
+    GenTree* loOp1 = op1->gtGetOp1();
+    GenTree* hiOp1 = op1->gtGetOp2();
+    Compiler::fgSnipNode(curStmt, op1);
+
+    GenTree* loResult = tree;
+    loResult->gtType = TYP_INT;
+    loResult->gtOp.gtOp1 = loOp1;
+
+    GenTree* zero = m_compiler->gtNewZeroConNode(TYP_INT);
+    GenTree* hiAdjust = m_compiler->gtNewOperNode(GT_ADD_HI, TYP_INT, hiOp1, zero);
+    GenTree* hiResult = m_compiler->gtNewOperNode(GT_NEG, TYP_INT, hiAdjust);
+    hiResult->gtFlags = tree->gtFlags;
+
+    Compiler::fgSnipNode(curStmt, hiOp1);
+    // fgSnipNode doesn't clear gtNext/gtPrev...
+    hiOp1->gtNext = nullptr;
+    hiOp1->gtPrev = nullptr;
+    SimpleLinkNodeAfter(hiOp1, zero);
+    SimpleLinkNodeAfter(zero, hiAdjust);
+    SimpleLinkNodeAfter(hiAdjust, hiResult);
+
+    FinalizeDecomposition(ppTree, data, loResult, hiResult);
+}
 
 //------------------------------------------------------------------------
 // DecomposeArith: Decompose GT_ADD, GT_SUB, GT_OR, GT_XOR, GT_AND.
index 376f655..b4a48a0 100644 (file)
@@ -44,6 +44,7 @@ private:
     void DecomposeCall(GenTree** ppTree, Compiler::fgWalkData* data);
     void DecomposeStoreInd(GenTree** ppTree, Compiler::fgWalkData* data);
     void DecomposeNot(GenTree** ppTree, Compiler::fgWalkData* data);
+    void DecomposeNeg(GenTree** ppTree, Compiler::fgWalkData* data);
     void DecomposeArith(GenTree** ppTree, Compiler::fgWalkData* data);
 
     // Helper functions
old mode 100755 (executable)
new mode 100644 (file)
index 7a133f7..80b5f4c
@@ -1147,7 +1147,10 @@ void Lowering::LowerArg(GenTreeCall* call, GenTreePtr* ppArg)
             GenTreePtr argLo = arg->gtGetOp1();
             GenTreePtr argHi = arg->gtGetOp2();
 
-            NYI_IF(argHi->OperGet() == GT_ADD_HI || argHi->OperGet() == GT_SUB_HI, "Hi and Lo cannot be reordered");
+            NYI_IF((argHi->OperGet() == GT_ADD_HI) ||
+                   (argHi->OperGet() == GT_SUB_HI) ||
+                   (argHi->OperGet() == GT_NEG), 
+                   "Hi and Lo cannot be reordered");
             
             GenTreePtr putArgLo = NewPutArg(call, argLo, info, type);
             GenTreePtr putArgHi = NewPutArg(call, argHi, info, type);