}
-#if FEATURE_STACK_FP_X87
-
-/*****************************************************************************/
-
-void Compiler::gtComputeFPlvls(GenTreePtr tree)
-{
- genTreeOps oper;
- unsigned kind;
- bool isflt;
- unsigned savFPstkLevel;
-
- noway_assert(tree);
- noway_assert(tree->gtOper != GT_STMT);
-
- /* Figure out what kind of a node we have */
-
- oper = tree->OperGet();
- kind = tree->OperKind();
- isflt = varTypeIsFloating(tree->TypeGet()) ? 1 : 0;
-
- /* Is this a constant or leaf node? */
-
- if (kind & (GTK_CONST|GTK_LEAF))
- {
- codeGen->genFPstkLevel += isflt;
- goto DONE;
- }
-
- /* Is it a 'simple' unary/binary operator? */
-
- if (kind & GTK_SMPOP)
- {
- GenTreePtr op1 = tree->gtOp.gtOp1;
- GenTreePtr op2 = tree->gtGetOp2();
-
- /* Check for some special cases */
-
- switch (oper)
- {
- case GT_IND:
-
- gtComputeFPlvls(op1);
-
- /* Indirect loads of FP values push a new value on the FP stack */
-
- codeGen->genFPstkLevel += isflt;
- goto DONE;
-
- case GT_CAST:
-
- gtComputeFPlvls(op1);
-
- /* Casts between non-FP and FP push on / pop from the FP stack */
-
- if (varTypeIsFloating(op1->TypeGet()))
- {
- if (isflt == false)
- codeGen->genFPstkLevel--;
- }
- else
- {
- if (isflt != false)
- codeGen->genFPstkLevel++;
- }
-
- goto DONE;
-
- case GT_LIST: /* GT_LIST presumably part of an argument list */
- case GT_COMMA: /* Comma tosses the result of the left operand */
-
- savFPstkLevel = codeGen->genFPstkLevel;
- gtComputeFPlvls(op1);
- codeGen->genFPstkLevel = savFPstkLevel;
-
- if (op2)
- gtComputeFPlvls(op2);
-
- goto DONE;
-
- default:
- break;
- }
-
- if (!op1)
- {
- if (!op2)
- goto DONE;
-
- gtComputeFPlvls(op2);
- goto DONE;
- }
-
- if (!op2)
- {
- gtComputeFPlvls(op1);
- if (oper == GT_ADDR)
- {
- /* If the operand was floating point pop the value from the stack */
- if (varTypeIsFloating(op1->TypeGet()))
- {
- noway_assert(codeGen->genFPstkLevel);
- codeGen->genFPstkLevel--;
- }
- }
-
- // This is a special case to handle the following
- // optimization: conv.i4(round.d(d)) -> round.i(d)
-
- if (oper== GT_INTRINSIC && tree->gtIntrinsic.gtIntrinsicId == CORINFO_INTRINSIC_Round &&
- tree->TypeGet()==TYP_INT)
- {
- codeGen->genFPstkLevel--;
- }
-
- goto DONE;
- }
-
- /* FP assignments need a bit special handling */
-
- if (isflt && (kind & GTK_ASGOP))
- {
- /* The target of the assignment won't get pushed */
-
- if (tree->gtFlags & GTF_REVERSE_OPS)
- {
- gtComputeFPlvls(op2);
- gtComputeFPlvls(op1);
- op1->gtFPlvl--;
- codeGen->genFPstkLevel--;
- }
- else
- {
- gtComputeFPlvls(op1);
- op1->gtFPlvl--;
- codeGen->genFPstkLevel--;
- gtComputeFPlvls(op2);
- }
-
- codeGen->genFPstkLevel--;
- goto DONE;
- }
-
- /* Here we have a binary operator; visit operands in proper order */
-
- if (tree->gtFlags & GTF_REVERSE_OPS)
- {
- gtComputeFPlvls(op2);
- gtComputeFPlvls(op1);
- }
- else
- {
- gtComputeFPlvls(op1);
- gtComputeFPlvls(op2);
- }
-
- /*
- Binary FP operators pop 2 operands and produce 1 result;
- assignments consume 1 value and don't produce any.
- */
-
- if (isflt)
- codeGen->genFPstkLevel--;
-
- /* Float compares remove both operands from the FP stack */
-
- if (kind & GTK_RELOP)
- {
- if (varTypeIsFloating(op1->TypeGet()))
- codeGen->genFPstkLevel -= 2;
- }
-
- goto DONE;
- }
-
- /* See what kind of a special operator we have here */
-
- switch (oper)
- {
- case GT_FIELD:
- gtComputeFPlvls(tree->gtField.gtFldObj);
- codeGen->genFPstkLevel += isflt;
- break;
-
- case GT_CALL:
-
- if (tree->gtCall.gtCallObjp)
- gtComputeFPlvls(tree->gtCall.gtCallObjp);
-
- if (tree->gtCall.gtCallArgs)
- {
- savFPstkLevel = codeGen->genFPstkLevel;
- gtComputeFPlvls(tree->gtCall.gtCallArgs);
- codeGen->genFPstkLevel = savFPstkLevel;
- }
-
- if (tree->gtCall.gtCallLateArgs)
- {
- savFPstkLevel = codeGen->genFPstkLevel;
- gtComputeFPlvls(tree->gtCall.gtCallLateArgs);
- codeGen->genFPstkLevel = savFPstkLevel;
- }
-
- codeGen->genFPstkLevel += isflt;
- break;
-
- case GT_ARR_ELEM:
-
- gtComputeFPlvls(tree->gtArrElem.gtArrObj);
-
- unsigned dim;
- for (dim = 0; dim < tree->gtArrElem.gtArrRank; dim++)
- gtComputeFPlvls(tree->gtArrElem.gtArrInds[dim]);
-
- /* Loads of FP values push a new value on the FP stack */
- codeGen->genFPstkLevel += isflt;
- break;
-
- case GT_CMPXCHG:
- //Evaluate the trees left to right
- gtComputeFPlvls(tree->gtCmpXchg.gtOpLocation);
- gtComputeFPlvls(tree->gtCmpXchg.gtOpValue);
- gtComputeFPlvls(tree->gtCmpXchg.gtOpComparand);
- noway_assert(!isflt);
- break;
-
- case GT_ARR_BOUNDS_CHECK:
- gtComputeFPlvls(tree->gtBoundsChk.gtArrLen);
- gtComputeFPlvls(tree->gtBoundsChk.gtIndex);
- noway_assert(!isflt);
- break;
-
-#ifdef DEBUG
- default:
- noway_assert(!"Unhandled special operator in gtComputeFPlvls()");
- break;
-#endif
- }
-
-DONE:
-
- noway_assert((unsigned char)codeGen->genFPstkLevel == codeGen->genFPstkLevel);
-
- tree->gtFPlvl = (unsigned char)codeGen->genFPstkLevel;
-}
-
-#endif // FEATURE_STACK_FP_X87
-
/*****************************************************************************/
/*****************************************************************************/
#pragma warning(pop)
#endif
+#if FEATURE_STACK_FP_X87
+
+/*****************************************************************************/
+void Compiler::gtComputeFPlvls(GenTreePtr tree)
+{
+ genTreeOps oper;
+ unsigned kind;
+ bool isflt;
+ unsigned savFPstkLevel;
+
+ noway_assert(tree);
+ noway_assert(tree->gtOper != GT_STMT);
+
+ /* Figure out what kind of a node we have */
+
+ oper = tree->OperGet();
+ kind = tree->OperKind();
+ isflt = varTypeIsFloating(tree->TypeGet()) ? 1 : 0;
+
+ /* Is this a constant or leaf node? */
+
+ if (kind & (GTK_CONST|GTK_LEAF))
+ {
+ codeGen->genFPstkLevel += isflt;
+ goto DONE;
+ }
+
+ /* Is it a 'simple' unary/binary operator? */
+
+ if (kind & GTK_SMPOP)
+ {
+ GenTreePtr op1 = tree->gtOp.gtOp1;
+ GenTreePtr op2 = tree->gtGetOp2();
+
+ /* Check for some special cases */
+
+ switch (oper)
+ {
+ case GT_IND:
+
+ gtComputeFPlvls(op1);
+
+ /* Indirect loads of FP values push a new value on the FP stack */
+
+ codeGen->genFPstkLevel += isflt;
+ goto DONE;
+
+ case GT_CAST:
+
+ gtComputeFPlvls(op1);
+
+ /* Casts between non-FP and FP push on / pop from the FP stack */
+
+ if (varTypeIsFloating(op1->TypeGet()))
+ {
+ if (isflt == false)
+ codeGen->genFPstkLevel--;
+ }
+ else
+ {
+ if (isflt != false)
+ codeGen->genFPstkLevel++;
+ }
+
+ goto DONE;
+
+ case GT_LIST: /* GT_LIST presumably part of an argument list */
+ case GT_COMMA: /* Comma tosses the result of the left operand */
+
+ savFPstkLevel = codeGen->genFPstkLevel;
+ gtComputeFPlvls(op1);
+ codeGen->genFPstkLevel = savFPstkLevel;
+
+ if (op2)
+ gtComputeFPlvls(op2);
+
+ goto DONE;
+
+ default:
+ break;
+ }
+
+ if (!op1)
+ {
+ if (!op2)
+ goto DONE;
+
+ gtComputeFPlvls(op2);
+ goto DONE;
+ }
+
+ if (!op2)
+ {
+ gtComputeFPlvls(op1);
+ if (oper == GT_ADDR)
+ {
+ /* If the operand was floating point pop the value from the stack */
+ if (varTypeIsFloating(op1->TypeGet()))
+ {
+ noway_assert(codeGen->genFPstkLevel);
+ codeGen->genFPstkLevel--;
+ }
+ }
+
+ // This is a special case to handle the following
+ // optimization: conv.i4(round.d(d)) -> round.i(d)
+
+ if (oper== GT_INTRINSIC && tree->gtIntrinsic.gtIntrinsicId == CORINFO_INTRINSIC_Round &&
+ tree->TypeGet()==TYP_INT)
+ {
+ codeGen->genFPstkLevel--;
+ }
+
+ goto DONE;
+ }
+
+ /* FP assignments need a bit special handling */
+
+ if (isflt && (kind & GTK_ASGOP))
+ {
+ /* The target of the assignment won't get pushed */
+
+ if (tree->gtFlags & GTF_REVERSE_OPS)
+ {
+ gtComputeFPlvls(op2);
+ gtComputeFPlvls(op1);
+ op1->gtFPlvl--;
+ codeGen->genFPstkLevel--;
+ }
+ else
+ {
+ gtComputeFPlvls(op1);
+ op1->gtFPlvl--;
+ codeGen->genFPstkLevel--;
+ gtComputeFPlvls(op2);
+ }
+
+ codeGen->genFPstkLevel--;
+ goto DONE;
+ }
+
+ /* Here we have a binary operator; visit operands in proper order */
+
+ if (tree->gtFlags & GTF_REVERSE_OPS)
+ {
+ gtComputeFPlvls(op2);
+ gtComputeFPlvls(op1);
+ }
+ else
+ {
+ gtComputeFPlvls(op1);
+ gtComputeFPlvls(op2);
+ }
+
+ /*
+ Binary FP operators pop 2 operands and produce 1 result;
+ assignments consume 1 value and don't produce any.
+ */
+
+ if (isflt)
+ codeGen->genFPstkLevel--;
+
+ /* Float compares remove both operands from the FP stack */
+
+ if (kind & GTK_RELOP)
+ {
+ if (varTypeIsFloating(op1->TypeGet()))
+ codeGen->genFPstkLevel -= 2;
+ }
+
+ goto DONE;
+ }
+
+ /* See what kind of a special operator we have here */
+
+ switch (oper)
+ {
+ case GT_FIELD:
+ gtComputeFPlvls(tree->gtField.gtFldObj);
+ codeGen->genFPstkLevel += isflt;
+ break;
+
+ case GT_CALL:
+
+ if (tree->gtCall.gtCallObjp)
+ gtComputeFPlvls(tree->gtCall.gtCallObjp);
+
+ if (tree->gtCall.gtCallArgs)
+ {
+ savFPstkLevel = codeGen->genFPstkLevel;
+ gtComputeFPlvls(tree->gtCall.gtCallArgs);
+ codeGen->genFPstkLevel = savFPstkLevel;
+ }
+
+ if (tree->gtCall.gtCallLateArgs)
+ {
+ savFPstkLevel = codeGen->genFPstkLevel;
+ gtComputeFPlvls(tree->gtCall.gtCallLateArgs);
+ codeGen->genFPstkLevel = savFPstkLevel;
+ }
+
+ codeGen->genFPstkLevel += isflt;
+ break;
+
+ case GT_ARR_ELEM:
+
+ gtComputeFPlvls(tree->gtArrElem.gtArrObj);
+
+ unsigned dim;
+ for (dim = 0; dim < tree->gtArrElem.gtArrRank; dim++)
+ gtComputeFPlvls(tree->gtArrElem.gtArrInds[dim]);
+
+ /* Loads of FP values push a new value on the FP stack */
+ codeGen->genFPstkLevel += isflt;
+ break;
+
+ case GT_CMPXCHG:
+ //Evaluate the trees left to right
+ gtComputeFPlvls(tree->gtCmpXchg.gtOpLocation);
+ gtComputeFPlvls(tree->gtCmpXchg.gtOpValue);
+ gtComputeFPlvls(tree->gtCmpXchg.gtOpComparand);
+ noway_assert(!isflt);
+ break;
+
+ case GT_ARR_BOUNDS_CHECK:
+ gtComputeFPlvls(tree->gtBoundsChk.gtArrLen);
+ gtComputeFPlvls(tree->gtBoundsChk.gtIndex);
+ noway_assert(!isflt);
+ break;
+
+#ifdef DEBUG
+ default:
+ noway_assert(!"Unhandled special operator in gtComputeFPlvls()");
+ break;
+#endif
+ }
+
+DONE:
+
+ noway_assert((unsigned char)codeGen->genFPstkLevel == codeGen->genFPstkLevel);
+
+ tree->gtFPlvl = (unsigned char)codeGen->genFPstkLevel;
+}
+
+#endif // FEATURE_STACK_FP_X87
+
/*****************************************************************************
*