| Index: lib/compiler/implementation/ssa/codegen_helpers.dart
|
| ===================================================================
|
| --- lib/compiler/implementation/ssa/codegen_helpers.dart (revision 8386)
|
| +++ lib/compiler/implementation/ssa/codegen_helpers.dart (working copy)
|
| @@ -151,9 +151,10 @@
|
| if (instruction.block !== block) return block.last !== block.first;
|
|
|
| // If [instruction] is not the last instruction of the block
|
| - // before the control flow instruction, then we will have to emit
|
| - // a statement for that last instruction.
|
| - if (instruction !== block.last.previous) return true;
|
| + // before the control flow instruction, or the last instruction,
|
| + // then we will have to emit a statement for that last instruction.
|
| + if (instruction != block.last
|
| + && instruction !== block.last.previous) return true;
|
|
|
| // If one of the instructions in the block until [instruction] is
|
| // not generated at use site, then we will have to emit a
|
| @@ -186,23 +187,45 @@
|
| if (end == null) return;
|
| if (end.phis.isEmpty()) return;
|
| if (end.phis.first !== end.phis.last) return;
|
| - HBasicBlock thenBlock = startIf.thenBlock;
|
| HBasicBlock elseBlock = startIf.elseBlock;
|
| - if (end.predecessors[0] !== thenBlock) return;
|
| +
|
| if (end.predecessors[1] !== elseBlock) return;
|
| HPhi phi = end.phis.first;
|
| - if (!phi.inputs[1].isConstantBoolean()) return;
|
| + if (!phi.inputs[1].isConstantBoolean()) return;
|
| + if (elseBlock.first is !HGoto) return;
|
| + assert(elseBlock.successors.length == 1);
|
| + assert(end.predecessors.length == 2);
|
| +
|
| + HBasicBlock thenBlock = startIf.thenBlock;
|
| + // Skip trivial goto blocks.
|
| + while (thenBlock.successors[0] != end && thenBlock.first is HGoto) {
|
| + thenBlock = thenBlock.successors[0];
|
| + }
|
|
|
| HInstruction thenInput = phi.inputs[0];
|
| - if (hasStatement(thenBlock, thenInput)) return;
|
| - if (elseBlock.first !== elseBlock.last) return;
|
| -
|
| +
|
| + // If the [thenBlock] is already a logical operation, and does not
|
| + // have any statement, we can emit a sequence of logical operation.
|
| + if (logicalOperations.contains(thenBlock.last)) {
|
| + if (hasStatement(thenBlock, thenBlock.last)) return;
|
| + assert(thenInput.usedBy.length == 1);
|
| + generateAtUseSite.add(thenInput);
|
| + } else {
|
| + if (end.predecessors[0] !== thenBlock) return;
|
| + if (hasStatement(thenBlock, thenInput)) return;
|
| + // If [thenInput] is defined in [thenBlock], then it is only used
|
| + // by [phi] and can be generated at use site.
|
| + if (thenInput.block === thenBlock) {
|
| + // The instruction cannot be used by anyone else otherwise it
|
| + // would not be the last non control-flow instruction of [thenBlock].
|
| + assert(thenInput.usedBy.length == 1);
|
| + generateAtUseSite.add(thenInput);
|
| + }
|
| + assert(thenBlock.successors.length == 1);
|
| + }
|
| +
|
| // From now on, we have recognized a logical operation built from
|
| - // the builder. We don't expect the builder and the optimizers to
|
| - // generate the then and else branches with multiple successors,
|
| - // and the join branch to have more than two predecessors.
|
| -
|
| - // Mark the if instruction as a logical operation.
|
| + // the builder. Mark the if instruction as such.
|
| logicalOperations.add(startIf);
|
|
|
| // If the logical operation is only used by the first instruction
|
| @@ -210,13 +233,6 @@
|
| if (phi.usedBy.length == 1 && phi.usedBy[0] === phi.block.first) {
|
| generateAtUseSite.add(phi);
|
| }
|
| -
|
| - // If [thenInput] is defined in [thenBlock], then it is only used
|
| - // by [phi] and can be generated at use site.
|
| - if (thenInput.block === thenBlock) {
|
| - assert(thenInput.usedBy.length == 1);
|
| - generateAtUseSite.add(thenInput);
|
| - }
|
| }
|
| }
|
|
|
|
|