Fix premature deoptimization if the loop body isn't entered.
Add a test between initial_ and end_ to see if the loop body is entered.
If the loop body isn't entered at all, we jump to the loop header. Loop header is
still executed and is going to test the condition again and loop body won't be
entered. This makes sure no deoptimization is triggered if the loop body isn't
even entered.
Bug: 21034044
Change-Id: I2b6de1f22fbc4568ca419f76382ebd87806d9694
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 5f128a7..126b3b9 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -195,6 +195,10 @@
// Inline this graph in `outer_graph`, replacing the given `invoke` instruction.
void InlineInto(HGraph* outer_graph, HInvoke* invoke);
+ // Need to add a couple of blocks to test if the loop body is entered and
+ // put deoptimization instructions, etc.
+ void TransformLoopHeaderForBCE(HBasicBlock* header);
+
// Removes `block` from the graph.
void DeleteDeadBlock(HBasicBlock* block);
@@ -4264,6 +4268,39 @@
DISALLOW_COPY_AND_ASSIGN(HBlocksInLoopIterator);
};
+// Iterator over the blocks that art part of the loop. Includes blocks part
+// of an inner loop. The order in which the blocks are iterated is reverse
+// post order.
+class HBlocksInLoopReversePostOrderIterator : public ValueObject {
+ public:
+ explicit HBlocksInLoopReversePostOrderIterator(const HLoopInformation& info)
+ : blocks_in_loop_(info.GetBlocks()),
+ blocks_(info.GetHeader()->GetGraph()->GetReversePostOrder()),
+ index_(0) {
+ if (!blocks_in_loop_.IsBitSet(blocks_.Get(index_)->GetBlockId())) {
+ Advance();
+ }
+ }
+
+ bool Done() const { return index_ == blocks_.Size(); }
+ HBasicBlock* Current() const { return blocks_.Get(index_); }
+ void Advance() {
+ ++index_;
+ for (size_t e = blocks_.Size(); index_ < e; ++index_) {
+ if (blocks_in_loop_.IsBitSet(blocks_.Get(index_)->GetBlockId())) {
+ break;
+ }
+ }
+ }
+
+ private:
+ const BitVector& blocks_in_loop_;
+ const GrowableArray<HBasicBlock*>& blocks_;
+ size_t index_;
+
+ DISALLOW_COPY_AND_ASSIGN(HBlocksInLoopReversePostOrderIterator);
+};
+
inline int64_t Int64FromConstant(HConstant* constant) {
DCHECK(constant->IsIntConstant() || constant->IsLongConstant());
return constant->IsIntConstant() ? constant->AsIntConstant()->GetValue()