}
// We want to use the Normal ValueNumber when checking for constants.
- ValueNum vnCns = vnStore->VNConservativeNormalValue(tree->gtVNPair);
- ValueNum vnLib = vnStore->VNLiberalNormalValue(tree->gtVNPair);
+ ValueNumPair vnPair = tree->gtVNPair;
+ ValueNum vnCns = vnStore->VNConservativeNormalValue(vnPair);
// Check if node evaluates to a constant.
if (!vnStore->IsVNConstant(vnCns))
return nullptr;
}
- GenTree* newTree = tree;
+ GenTree* conValTree = nullptr;
switch (vnStore->TypeOfVN(vnCns))
{
case TYP_FLOAT:
if (tree->TypeGet() == TYP_INT)
{
// Same sized reinterpretation of bits to integer
- newTree = optPrepareTreeForReplacement(tree, tree);
- tree->ChangeOperConst(GT_CNS_INT);
- tree->gtIntCon.gtIconVal = *(reinterpret_cast<int*>(&value));
- tree->gtVNPair = ValueNumPair(vnLib, vnCns);
+ conValTree = gtNewIconNode(*(reinterpret_cast<int*>(&value)));
}
else
{
// Implicit assignment conversion to float or double
assert(varTypeIsFloating(tree->TypeGet()));
-
- newTree = optPrepareTreeForReplacement(tree, tree);
- tree->ChangeOperConst(GT_CNS_DBL);
- tree->gtDblCon.gtDconVal = value;
- tree->gtVNPair = ValueNumPair(vnLib, vnCns);
+ conValTree = gtNewDconNode(value, tree->TypeGet());
}
break;
}
if (tree->TypeGet() == TYP_LONG)
{
- // Same sized reinterpretation of bits to long
- newTree = optPrepareTreeForReplacement(tree, tree);
- tree->ChangeOperConst(GT_CNS_NATIVELONG);
- tree->gtIntConCommon.SetLngValue(*(reinterpret_cast<INT64*>(&value)));
- tree->gtVNPair = ValueNumPair(vnLib, vnCns);
+ conValTree = gtNewLconNode(*(reinterpret_cast<INT64*>(&value)));
}
else
{
// Implicit assignment conversion to float or double
assert(varTypeIsFloating(tree->TypeGet()));
-
- newTree = optPrepareTreeForReplacement(tree, tree);
- tree->ChangeOperConst(GT_CNS_DBL);
- tree->gtDblCon.gtDconVal = value;
- tree->gtVNPair = ValueNumPair(vnLib, vnCns);
+ conValTree = gtNewDconNode(value, tree->TypeGet());
}
break;
}
// to be recorded as a relocation with the VM.
if (!opts.compReloc)
{
- newTree = gtNewIconHandleNode(value, vnStore->GetHandleFlags(vnCns));
- newTree->gtVNPair = ValueNumPair(vnLib, vnCns);
- newTree = optPrepareTreeForReplacement(tree, newTree);
+ conValTree = gtNewIconHandleNode(value, vnStore->GetHandleFlags(vnCns));
}
}
else
{
case TYP_INT:
// Implicit assignment conversion to smaller integer
- newTree = optPrepareTreeForReplacement(tree, tree);
- tree->ChangeOperConst(GT_CNS_INT);
- tree->gtIntCon.gtIconVal = (int)value;
- tree->gtVNPair = ValueNumPair(vnLib, vnCns);
+ conValTree = gtNewIconNode(static_cast<int>(value));
break;
case TYP_LONG:
// Same type no conversion required
- newTree = optPrepareTreeForReplacement(tree, tree);
- tree->ChangeOperConst(GT_CNS_NATIVELONG);
- tree->gtIntConCommon.SetLngValue(value);
- tree->gtVNPair = ValueNumPair(vnLib, vnCns);
+ conValTree = gtNewLconNode(value);
break;
case TYP_FLOAT:
case TYP_DOUBLE:
// Same sized reinterpretation of bits to double
- newTree = optPrepareTreeForReplacement(tree, tree);
- tree->ChangeOperConst(GT_CNS_DBL);
- tree->gtDblCon.gtDconVal = *(reinterpret_cast<double*>(&value));
- tree->gtVNPair = ValueNumPair(vnLib, vnCns);
+ conValTree = gtNewDconNode(*(reinterpret_cast<double*>(&value)));
break;
default:
- return nullptr;
+ // Can't optimize.
+ break;
}
}
}
break;
case TYP_REF:
- if (tree->TypeGet() != TYP_REF)
+ {
+ if (tree->TypeGet() != TYP_REF) // TODO seandree: what are other cases here?
{
- return nullptr;
+ // Can't optimize.
+ break;
}
assert(vnStore->ConstantValue<size_t>(vnCns) == 0);
- newTree = optPrepareTreeForReplacement(tree, tree);
- tree->ChangeOperConst(GT_CNS_INT);
- tree->gtIntCon.gtIconVal = 0;
- tree->ClearIconHandleMask();
- tree->gtVNPair = ValueNumPair(vnLib, vnCns);
- break;
+
+ conValTree = gtNewIconNode(0, TYP_REF);
+ }
+ break;
case TYP_INT:
{
// to be recorded as a relocation with the VM.
if (!opts.compReloc)
{
- newTree = gtNewIconHandleNode(value, vnStore->GetHandleFlags(vnCns));
- newTree->gtVNPair = ValueNumPair(vnLib, vnCns);
- newTree = optPrepareTreeForReplacement(tree, newTree);
+ conValTree = gtNewIconHandleNode(value, vnStore->GetHandleFlags(vnCns));
}
}
else
case TYP_REF:
case TYP_INT:
// Same type no conversion required
- newTree = optPrepareTreeForReplacement(tree, tree);
- tree->ChangeOperConst(GT_CNS_INT);
- tree->gtIntCon.gtIconVal = value;
- tree->ClearIconHandleMask();
- tree->gtVNPair = ValueNumPair(vnLib, vnCns);
+ conValTree = gtNewIconNode(static_cast<int>(value));
break;
case TYP_LONG:
// Implicit assignment conversion to larger integer
- newTree = optPrepareTreeForReplacement(tree, tree);
- tree->ChangeOperConst(GT_CNS_NATIVELONG);
- tree->gtIntConCommon.SetLngValue(value);
- tree->gtVNPair = ValueNumPair(vnLib, vnCns);
+ conValTree = gtNewLconNode(static_cast<int>(value));
break;
case TYP_FLOAT:
// Same sized reinterpretation of bits to float
- newTree = optPrepareTreeForReplacement(tree, tree);
- tree->ChangeOperConst(GT_CNS_DBL);
- tree->gtDblCon.gtDconVal = *(reinterpret_cast<float*>(&value));
- tree->gtVNPair = ValueNumPair(vnLib, vnCns);
+ conValTree = gtNewDconNode(*(reinterpret_cast<float*>(&value)), TYP_FLOAT);
break;
case TYP_DOUBLE:
break;
default:
- return nullptr;
+ // Can't optimize.
+ break;
}
}
}
break;
default:
- return nullptr;
+ // Can't optimize.
+ break;
+ }
+
+ if (conValTree != nullptr)
+ {
+ // Were able to optimize, replace as COMMA(side_effects, const value tree);
+ conValTree->gtVNPair = vnPair;
+ return optPrepareTreeForReplacement(tree, conValTree);
+ }
+ else
+ {
+ // Was not able to optimize.
+ return nullptr;
}
- return newTree;
}
/*******************************************************************************************************