Subzero: Use register availability during lowering to improve the code.
The problem is that given code like this:
a = b + c
d = a + e
...
... (use of a) ...
Lowering may produce code like this, at least on x86:
T1 = b
T1 += c
a = T1
T2 = a
T2 += e
d = T2
...
... (use of a) ...
If "a" has a long live range, it may not get a register, resulting in clumsy code in the middle of the sequence like "a=reg; reg=a". Normally one might expect store forwarding to make the clumsy code fast, but it does presumably add an extra instruction-retirement cycle to the critical path in a pointer-chasing loop, and makes a big difference on some benchmarks.
The simple fix here is, at the end of lowering "a=b+c", keep track of the final "a=T1" assignment. Then, when lowering "d=a+e" and we look up "a", we can substitute "T1". This slightly increases the live range of T1, but it does a great job of avoiding the redundant reload of the register from the stack location.
A more general fix (in the future) might be to do live range splitting and let the register allocator handle it.
BUG= https://code.google.com/p/nativeclient/issues/detail?id=4095
R=kschimpf@google.com
Review URL: https://codereview.chromium.org/1385433002 .
diff --git a/src/IceCfgNode.cpp b/src/IceCfgNode.cpp
index 9339b79..f78c107 100644
--- a/src/IceCfgNode.cpp
+++ b/src/IceCfgNode.cpp
@@ -570,6 +570,7 @@
// Ensure target lowering actually moved the cursor.
assert(Context.getCur() != Orig);
}
+ Context.availabilityReset();
// Do preliminary lowering of the Phi instructions.
Target->prelowerPhis();
}
@@ -683,7 +684,7 @@
// Validate the integrity of the live ranges in this block. If there are any
// errors, it prints details and returns false. On success, it returns true.
-bool CfgNode::livenessValidateIntervals(Liveness *Liveness) {
+bool CfgNode::livenessValidateIntervals(Liveness *Liveness) const {
if (!BuildDefs::asserts())
return true;