Today, a puzzle for you.
We’ve been talking about how the Roslyn C# compiler aggressively optimizes nested lifted unary operators and conversions by using a clever technique. The compiler realizes the inner operation as a conditional expression with a non-null nullable value on the consequence branch and a null nullable value on the alternative branch, distributes the outer operation to each branch, and then optimizes the branches independently. That then gives a conditional expression that can itself be the target of further optimizations if the nesting is deeper.
This works great for lifted conversions and unary operators. Does it also work for binary operators? It seems like it would be a lot harder to make this optimization work for a lifted binary operator where both operands are themselves lifted operations. But what if just one of the operands was a lifted operation, and the other operand was guaranteed to be non-null? There might be an opportunity to optimize such an expression. Let’s try it. Suppose X()
and Y()
are expressions of type int?
and that Z()
is an expression of type int
:
int? r = X() * Y() + Z();
We know from our previous episodes that operator overload resolution is going to choose lifted multiplication for the inner subexpression, and lifted addition for the outer subexpression. We know that the right operand of the lifted addition will be treated as though it was new int?(Z())
, but we can optimize away the unnecessary conversion to int?
. So the question is can the C# compiler legally code-generate that as though the user had written:
int? r;
int? tempX = X();
int? tempY = Y();
int tempZ = Z();
r = tempX.HasValue & tempY.HasValue ?
new int?(tempX.GetValueOrDefault() * tempY.GetValueOrDefault() + tempZ) :
new int?();
If you think the answer is “yes” then the follow-up question is: can the C# compiler legally make such an optimization for all nullable value types that have lifted addition and multiplication operators?
If you think the answer is “no” then the follow-up questions are: why not? and is there any scenario where this sort of optimization is valid?
Next time on FAIC we’ll be kind to our fine feathered friends; after that, we’ll find out the answer to today’s question.
Eric is crazy busy at Coverity’s head office; this posting was pre-recorded.