diff options
author | 2022-08-09 11:54:19 +0000 | |
---|---|---|
committer | 2022-08-09 13:21:11 +0000 | |
commit | fa1034c563b44c4f557814c50e2678e14dcd1d13 (patch) | |
tree | 6353ca19b0f193183310ad7cd77c199bce64eb18 | |
parent | 6981ef9238ce2d4ea3f7a86d3faf5d720c8c4641 (diff) |
Revert "Propagating values from if clauses to its successors"
This reverts commit c6b816ceb2b35300c937ef2e7d008598b6afba21.
Reason for revert: Broke libcore test https://ci.chromium.org/ui/p/art/builders/ci/angler-armv7-ndebug/3179/overview
Change-Id: I4f238bd20cc485e49078104e0225c373cac23415
19 files changed, 66 insertions, 589 deletions
diff --git a/compiler/optimizing/constant_folding.cc b/compiler/optimizing/constant_folding.cc index 862abd345d..2031707759 100644 --- a/compiler/optimizing/constant_folding.cc +++ b/compiler/optimizing/constant_folding.cc @@ -16,19 +16,14 @@ #include "constant_folding.h" -#include <algorithm> - -#include "optimizing/data_type.h" -#include "optimizing/nodes.h" - namespace art { // This visitor tries to simplify instructions that can be evaluated // as constants. class HConstantFoldingVisitor : public HGraphDelegateVisitor { public: - explicit HConstantFoldingVisitor(HGraph* graph, OptimizingCompilerStats* stats) - : HGraphDelegateVisitor(graph, stats) {} + explicit HConstantFoldingVisitor(HGraph* graph) + : HGraphDelegateVisitor(graph) {} private: void VisitBasicBlock(HBasicBlock* block) override; @@ -38,9 +33,6 @@ class HConstantFoldingVisitor : public HGraphDelegateVisitor { void VisitTypeConversion(HTypeConversion* inst) override; void VisitDivZeroCheck(HDivZeroCheck* inst) override; - void VisitIf(HIf* inst) override; - - void PropagateValue(HBasicBlock* starting_block, HInstruction* variable, HConstant* constant); DISALLOW_COPY_AND_ASSIGN(HConstantFoldingVisitor); }; @@ -77,7 +69,7 @@ class InstructionWithAbsorbingInputSimplifier : public HGraphVisitor { bool HConstantFolding::Run() { - HConstantFoldingVisitor visitor(graph_, stats_); + HConstantFoldingVisitor visitor(graph_); // Process basic blocks in reverse post-order in the dominator tree, // so that an instruction turned into a constant, used as input of // another instruction, may possibly be used to turn that second @@ -138,122 +130,6 @@ void HConstantFoldingVisitor::VisitDivZeroCheck(HDivZeroCheck* inst) { } } -void HConstantFoldingVisitor::PropagateValue(HBasicBlock* starting_block, - HInstruction* variable, - HConstant* constant) { - const bool recording_stats = stats_ != nullptr; - size_t uses_before = 0; - size_t uses_after = 0; - if (recording_stats) { - uses_before = variable->GetUses().SizeSlow(); - } - - variable->ReplaceUsesDominatedBy( - starting_block->GetFirstInstruction(), constant, /* strictly_dominated= */ false); - - if (recording_stats) { - uses_after = variable->GetUses().SizeSlow(); - DCHECK_GE(uses_after, 1u) << "we must at least have the use in the if clause."; - DCHECK_GE(uses_before, uses_after); - MaybeRecordStat(stats_, MethodCompilationStat::kPropagatedIfValue, uses_before - uses_after); - } -} - -void HConstantFoldingVisitor::VisitIf(HIf* inst) { - // Consistency check: the true and false successors do not dominate each other. - DCHECK(!inst->IfTrueSuccessor()->Dominates(inst->IfFalseSuccessor()) && - !inst->IfFalseSuccessor()->Dominates(inst->IfTrueSuccessor())); - - HInstruction* if_input = inst->InputAt(0); - - // Already a constant. - if (if_input->IsConstant()) { - return; - } - - // if (variable) { - // SSA `variable` guaranteed to be true - // } else { - // and here false - // } - PropagateValue(inst->IfTrueSuccessor(), if_input, GetGraph()->GetIntConstant(1)); - PropagateValue(inst->IfFalseSuccessor(), if_input, GetGraph()->GetIntConstant(0)); - - // If the input is a condition, we can propagate the information of the condition itself. - if (!if_input->IsCondition()) { - return; - } - HCondition* condition = if_input->AsCondition(); - - // We want either `==` or `!=`, since we cannot make assumptions for other conditions e.g. `>` - if (!condition->IsEqual() && !condition->IsNotEqual()) { - return; - } - - HInstruction* left = condition->GetLeft(); - HInstruction* right = condition->GetRight(); - - // We want one of them to be a constant and not the other. - if (left->IsConstant() == right->IsConstant()) { - return; - } - - // At this point we have something like: - // if (variable == constant) { - // SSA `variable` guaranteed to be equal to constant here - // } else { - // No guarantees can be made here (usually, see boolean case below). - // } - // Similarly with variable != constant, except that we can make guarantees in the else case. - - HConstant* constant = left->IsConstant() ? left->AsConstant() : right->AsConstant(); - HInstruction* variable = left->IsConstant() ? right : left; - - // Sometimes we have an HCompare flowing into an Equals/NonEquals, which can act as a proxy. For - // example: `Equals(Compare(var, constant), 0)`. This is common for long, float, and double. - if (variable->IsCompare()) { - // We only care about equality comparisons so we skip if it is a less or greater comparison. - if (!constant->IsArithmeticZero()) { - return; - } - - // Update left and right to be the ones from the HCompare. - left = variable->AsCompare()->GetLeft(); - right = variable->AsCompare()->GetRight(); - - // Re-check that one of them to be a constant and not the other. - if (left->IsConstant() == right->IsConstant()) { - return; - } - - constant = left->IsConstant() ? left->AsConstant() : right->AsConstant(); - variable = left->IsConstant() ? right : left; - } - - // From this block forward we want to replace the SSA value. We use `starting_block` and not the - // `if` block as we want to update one of the branches but not the other. - HBasicBlock* starting_block = - condition->IsEqual() ? inst->IfTrueSuccessor() : inst->IfFalseSuccessor(); - - PropagateValue(starting_block, variable, constant); - - // Special case for booleans since they have only two values so we know what to propagate in the - // other branch. However, sometimes our boolean values are not compared to 0 or 1. In those cases - // we cannot make an assumption for the `else` branch. - if (variable->GetType() == DataType::Type::kBool && - constant->IsIntConstant() && - (constant->AsIntConstant()->IsTrue() || constant->AsIntConstant()->IsFalse())) { - HBasicBlock* other_starting_block = - condition->IsEqual() ? inst->IfFalseSuccessor() : inst->IfTrueSuccessor(); - DCHECK_NE(other_starting_block, starting_block); - - HConstant* other_constant = constant->AsIntConstant()->IsTrue() ? - GetGraph()->GetIntConstant(0) : - GetGraph()->GetIntConstant(1); - DCHECK_NE(other_constant, constant); - PropagateValue(other_starting_block, variable, other_constant); - } -} void InstructionWithAbsorbingInputSimplifier::VisitShift(HBinaryOperation* instruction) { DCHECK(instruction->IsShl() || instruction->IsShr() || instruction->IsUShr()); diff --git a/compiler/optimizing/constant_folding.h b/compiler/optimizing/constant_folding.h index 07388d2e8c..72bd95b3cb 100644 --- a/compiler/optimizing/constant_folding.h +++ b/compiler/optimizing/constant_folding.h @@ -19,7 +19,6 @@ #include "nodes.h" #include "optimization.h" -#include "optimizing/optimizing_compiler_stats.h" namespace art { @@ -40,8 +39,7 @@ namespace art { */ class HConstantFolding : public HOptimization { public: - HConstantFolding(HGraph* graph, OptimizingCompilerStats* stats, const char* name) - : HOptimization(graph, name, stats) {} + HConstantFolding(HGraph* graph, const char* name) : HOptimization(graph, name) {} bool Run() override; diff --git a/compiler/optimizing/constant_folding_test.cc b/compiler/optimizing/constant_folding_test.cc index 3bcdc1ce40..74d9d3a993 100644 --- a/compiler/optimizing/constant_folding_test.cc +++ b/compiler/optimizing/constant_folding_test.cc @@ -58,7 +58,7 @@ class ConstantFoldingTest : public OptimizingUnitTest { std::string actual_before = printer_before.str(); EXPECT_EQ(expected_before, actual_before); - HConstantFolding(graph_, /* stats= */ nullptr, "constant_folding").Run(); + HConstantFolding(graph_, "constant_folding").Run(); GraphChecker graph_checker_cf(graph_); graph_checker_cf.Run(); ASSERT_TRUE(graph_checker_cf.IsValid()); diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc index cdd8fb2638..3a2f7f2903 100644 --- a/compiler/optimizing/inliner.cc +++ b/compiler/optimizing/inliner.cc @@ -2104,7 +2104,7 @@ void HInliner::RunOptimizations(HGraph* callee_graph, // Note: if the outermost_graph_ is being compiled OSR, we should not run any // optimization that could lead to a HDeoptimize. The following optimizations do not. HDeadCodeElimination dce(callee_graph, inline_stats_, "dead_code_elimination$inliner"); - HConstantFolding fold(callee_graph, inline_stats_, "constant_folding$inliner"); + HConstantFolding fold(callee_graph, "constant_folding$inliner"); InstructionSimplifier simplify(callee_graph, codegen_, inline_stats_); HOptimization* optimizations[] = { diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc index 4fbb033c2f..6ac4e07ca7 100644 --- a/compiler/optimizing/nodes.cc +++ b/compiler/optimizing/nodes.cc @@ -1477,10 +1477,6 @@ bool HInstructionList::FoundBefore(const HInstruction* instruction1, UNREACHABLE(); } -bool HInstruction::Dominates(HInstruction* other_instruction) const { - return other_instruction == this || StrictlyDominates(other_instruction); -} - bool HInstruction::StrictlyDominates(HInstruction* other_instruction) const { if (other_instruction == this) { // An instruction does not strictly dominate itself. @@ -1540,19 +1536,14 @@ void HInstruction::ReplaceWith(HInstruction* other) { DCHECK(env_uses_.empty()); } -void HInstruction::ReplaceUsesDominatedBy(HInstruction* dominator, - HInstruction* replacement, - bool strictly_dominated) { +void HInstruction::ReplaceUsesDominatedBy(HInstruction* dominator, HInstruction* replacement) { const HUseList<HInstruction*>& uses = GetUses(); for (auto it = uses.begin(), end = uses.end(); it != end; /* ++it below */) { HInstruction* user = it->GetUser(); size_t index = it->GetIndex(); // Increment `it` now because `*it` may disappear thanks to user->ReplaceInput(). ++it; - const bool dominated = - strictly_dominated ? dominator->StrictlyDominates(user) : dominator->Dominates(user); - - if (dominated) { + if (dominator->StrictlyDominates(user)) { user->ReplaceInput(replacement, index); } else if (user->IsPhi() && !user->AsPhi()->IsCatchPhi()) { // If the input flows from a block dominated by `dominator`, we can replace it. diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index 103d318710..39cb9275fb 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -2444,12 +2444,9 @@ class HInstruction : public ArenaObject<kArenaAllocInstruction> { return IsRemovable() && !HasUses(); } - // Does this instruction dominate `other_instruction`? - // Aborts if this instruction and `other_instruction` are different phis. - bool Dominates(HInstruction* other_instruction) const; - - // Same but with `strictly dominates` i.e. returns false if this instruction and - // `other_instruction` are the same. + // Does this instruction strictly dominate `other_instruction`? + // Returns false if this instruction and `other_instruction` are the same. + // Aborts if this instruction and `other_instruction` are both phis. bool StrictlyDominates(HInstruction* other_instruction) const; int GetId() const { return id_; } @@ -2514,9 +2511,7 @@ class HInstruction : public ArenaObject<kArenaAllocInstruction> { void SetLocations(LocationSummary* locations) { locations_ = locations; } void ReplaceWith(HInstruction* instruction); - void ReplaceUsesDominatedBy(HInstruction* dominator, - HInstruction* replacement, - bool strictly_dominated = true); + void ReplaceUsesDominatedBy(HInstruction* dominator, HInstruction* replacement); void ReplaceEnvUsesDominatedBy(HInstruction* dominator, HInstruction* replacement); void ReplaceInput(HInstruction* replacement, size_t index); diff --git a/compiler/optimizing/optimization.cc b/compiler/optimizing/optimization.cc index 7bf6dbb741..2cac38b715 100644 --- a/compiler/optimizing/optimization.cc +++ b/compiler/optimizing/optimization.cc @@ -221,7 +221,7 @@ ArenaVector<HOptimization*> ConstructOptimizations( // Regular passes. // case OptimizationPass::kConstantFolding: - opt = new (allocator) HConstantFolding(graph, stats, pass_name); + opt = new (allocator) HConstantFolding(graph, pass_name); break; case OptimizationPass::kDeadCodeElimination: opt = new (allocator) HDeadCodeElimination(graph, stats, pass_name); diff --git a/compiler/optimizing/optimizing_compiler_stats.h b/compiler/optimizing/optimizing_compiler_stats.h index 5e316ba403..d458e42608 100644 --- a/compiler/optimizing/optimizing_compiler_stats.h +++ b/compiler/optimizing/optimizing_compiler_stats.h @@ -73,7 +73,6 @@ enum class MethodCompilationStat { kLoopVectorizedIdiom, kSelectGenerated, kRemovedInstanceOf, - kPropagatedIfValue, kInlinedInvokeVirtualOrInterface, kInlinedLastInvokeVirtualOrInterface, kImplicitNullCheckGenerated, diff --git a/test/2042-checker-dce-always-throw/src/Main.java b/test/2042-checker-dce-always-throw/src/Main.java index bc2e7a11a1..b601f20ebb 100644 --- a/test/2042-checker-dce-always-throw/src/Main.java +++ b/test/2042-checker-dce-always-throw/src/Main.java @@ -27,11 +27,11 @@ public class Main { // Try catch tests assertEquals(0, $noinline$testDoNotSimplifyInTry(1)); assertEquals(0, $noinline$testSimplifyInCatch(1)); - assertEquals(0, $noinline$testDoNotSimplifyInCatchInOuterTry(1, 1)); + assertEquals(0, $noinline$testDoNotSimplifyInCatchInOuterTry(1)); // Test that we update the phis correctly after simplifying an always throwing method, and // recomputing dominance. - assertEquals(0, $noinline$UpdatePhisCorrectly(1, 1)); + assertEquals(0, $noinline$UpdatePhisCorrectly(1)); } private static void alwaysThrows() throws Error { @@ -251,25 +251,25 @@ public class Main { } } - /// CHECK-START: int Main.$noinline$testDoNotSimplifyInCatchInOuterTry(int, int) dead_code_elimination$after_inlining (before) + /// CHECK-START: int Main.$noinline$testDoNotSimplifyInCatchInOuterTry(int) dead_code_elimination$after_inlining (before) /// CHECK-DAG: InvokeStaticOrDirect block:<<InvokeBlock:B\d+>> method_name:Main.alwaysThrows always_throws:true /// CHECK-DAG: Exit block:<<ExitBlock:B\d+>> /// CHECK-DAG: Goto block:<<InvokeBlock>> target:<<TargetBlock:B\d+>> /// CHECK-EVAL: "<<ExitBlock>>" != "<<TargetBlock>>" - /// CHECK-START: int Main.$noinline$testDoNotSimplifyInCatchInOuterTry(int, int) dead_code_elimination$after_inlining (after) + /// CHECK-START: int Main.$noinline$testDoNotSimplifyInCatchInOuterTry(int) dead_code_elimination$after_inlining (after) /// CHECK-DAG: InvokeStaticOrDirect block:<<InvokeBlock:B\d+>> method_name:Main.alwaysThrows always_throws:true /// CHECK-DAG: Exit block:<<ExitBlock:B\d+>> /// CHECK-DAG: Goto block:<<InvokeBlock>> target:<<TargetBlock:B\d+>> /// CHECK-EVAL: "<<ExitBlock>>" != "<<TargetBlock>>" // Consistency check to make sure we have the try catches in the graph at this stage. - /// CHECK-START: int Main.$noinline$testDoNotSimplifyInCatchInOuterTry(int, int) dead_code_elimination$after_inlining (before) + /// CHECK-START: int Main.$noinline$testDoNotSimplifyInCatchInOuterTry(int) dead_code_elimination$after_inlining (before) /// CHECK-DAG: TryBoundary kind:entry /// CHECK-DAG: TryBoundary kind:entry // Consistency check to that we do not simplify it by the last DCE pass either - /// CHECK-START: int Main.$noinline$testDoNotSimplifyInCatchInOuterTry(int, int) dead_code_elimination$final (after) + /// CHECK-START: int Main.$noinline$testDoNotSimplifyInCatchInOuterTry(int) dead_code_elimination$final (after) /// CHECK-DAG: InvokeStaticOrDirect block:<<InvokeBlock:B\d+>> method_name:Main.alwaysThrows always_throws:true /// CHECK-DAG: Exit block:<<ExitBlock:B\d+>> /// CHECK-DAG: Goto block:<<InvokeBlock>> target:<<TargetBlock:B\d+>> @@ -278,15 +278,13 @@ public class Main { // Similar to testSimplifyInCatch, but now the throw is in an outer try and we shouldn't simplify // it. Like in testDoNotSimplifyInTry, we need the help of the inliner to have an invoke followed // by a Goto. - private static int $noinline$testDoNotSimplifyInCatchInOuterTry(int num, int other_num) { + private static int $noinline$testDoNotSimplifyInCatchInOuterTry(int num) { try { try { throw new Error(); } catch (Error e) { if (num == 0) { - // We use `other_num` here because otherwise we propagate the knowledge that `num` equals - // zero. - $inline$testDoNotSimplifyInner(other_num); + $inline$testDoNotSimplifyInner(num); } return 0; } @@ -298,7 +296,7 @@ public class Main { // Check that when we perform SimplifyAlwaysThrows, that the phi for `phi_value` exists, and that // we correctly update it after running DCE. - /// CHECK-START: int Main.$noinline$UpdatePhisCorrectly(int, int) dead_code_elimination$after_inlining (before) + /// CHECK-START: int Main.$noinline$UpdatePhisCorrectly(int) dead_code_elimination$after_inlining (before) /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 /// CHECK-DAG: <<Const5:i\d+>> IntConstant 5 /// CHECK-DAG: <<ReturnValue:i\d+>> Phi [<<Const0>>,<<Const5>>] @@ -308,24 +306,23 @@ public class Main { /// CHECK-DAG: Goto block:<<InvokeBlock>> target:<<TargetBlock:B\d+>> /// CHECK-EVAL: "<<ExitBlock>>" != "<<TargetBlock>>" - /// CHECK-START: int Main.$noinline$UpdatePhisCorrectly(int, int) dead_code_elimination$after_inlining (after) + /// CHECK-START: int Main.$noinline$UpdatePhisCorrectly(int) dead_code_elimination$after_inlining (after) /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 /// CHECK-DAG: Return [<<Const0>>] /// CHECK-DAG: InvokeStaticOrDirect block:<<InvokeBlock:B\d+>> method_name:Main.alwaysThrows always_throws:true /// CHECK-DAG: Exit block:<<ExitBlock:B\d+>> /// CHECK-DAG: Goto block:<<InvokeBlock>> target:<<ExitBlock>> - /// CHECK-START: int Main.$noinline$UpdatePhisCorrectly(int, int) dead_code_elimination$after_inlining (after) + /// CHECK-START: int Main.$noinline$UpdatePhisCorrectly(int) dead_code_elimination$after_inlining (after) /// CHECK-NOT: Phi - private static int $noinline$UpdatePhisCorrectly(int num, int other_num) { + private static int $noinline$UpdatePhisCorrectly(int num) { int phi_value = 0; if (num == 0) { alwaysThrows(); // This while loop is here so that the `if (num == 0)` will be several blocks instead of - // just one. We use `other_num` here because otherwise we propagate the knowledge that `num` - // equals zero. - while (other_num == 0) { + // just one. + while (num == 0) { // Assign to phi_value so that the loop is not empty. phi_value = 2; } diff --git a/test/442-checker-constant-folding/src/Main.java b/test/442-checker-constant-folding/src/Main.java index 68f9b1f52b..1bdf7b5cc8 100644 --- a/test/442-checker-constant-folding/src/Main.java +++ b/test/442-checker-constant-folding/src/Main.java @@ -1577,338 +1577,6 @@ public class Main { return (double) imm; } - /// CHECK-START: int Main.$inline$SpecialCaseForZeroInt(int) constant_folding (before) - /// CHECK-DAG: Add - /// CHECK-DAG: Mul - - /// CHECK-START: int Main.$inline$SpecialCaseForZeroInt(int) constant_folding (before) - /// CHECK-NOT: IntConstant 6 - - /// CHECK-START: int Main.$inline$SpecialCaseForZeroInt(int) constant_folding (after) - /// CHECK-NOT: Add - - /// CHECK-START: int Main.$inline$SpecialCaseForZeroInt(int) constant_folding (after) - /// CHECK-NOT: Mul - - /// CHECK-START: int Main.$inline$SpecialCaseForZeroInt(int) constant_folding (after) - /// CHECK-DAG: <<Const:i\d+>> IntConstant 6 - /// CHECK-DAG: Return [<<Const>>] - private static int $inline$SpecialCaseForZeroInt(int value) { - if (value == 0) { - return (value + 2) * 3; - } - return value; - } - - /// CHECK-START: long Main.$inline$SpecialCaseForZeroLong(long) constant_folding (before) - /// CHECK-DAG: Add - /// CHECK-DAG: Mul - - /// CHECK-START: long Main.$inline$SpecialCaseForZeroLong(long) constant_folding (before) - /// CHECK-NOT: LongConstant 6 - - /// CHECK-START: long Main.$inline$SpecialCaseForZeroLong(long) constant_folding (after) - /// CHECK-NOT: Add - - /// CHECK-START: long Main.$inline$SpecialCaseForZeroLong(long) constant_folding (after) - /// CHECK-NOT: Mul - - /// CHECK-START: long Main.$inline$SpecialCaseForZeroLong(long) constant_folding (after) - /// CHECK-DAG: <<Const:j\d+>> LongConstant 6 - /// CHECK-DAG: Return [<<Const>>] - private static long $inline$SpecialCaseForZeroLong(long value) { - if (value == 0L) { - return (value + 2) * 3; - } - return value; - } - - /// CHECK-START: float Main.$inline$SpecialCaseForZeroFloat(float) constant_folding (before) - /// CHECK-DAG: Add - /// CHECK-DAG: Mul - - /// CHECK-START: float Main.$inline$SpecialCaseForZeroFloat(float) constant_folding (before) - /// CHECK-NOT: FloatConstant 6 - - /// CHECK-START: float Main.$inline$SpecialCaseForZeroFloat(float) constant_folding (after) - /// CHECK-NOT: Add - - /// CHECK-START: float Main.$inline$SpecialCaseForZeroFloat(float) constant_folding (after) - /// CHECK-NOT: Mul - - /// CHECK-START: float Main.$inline$SpecialCaseForZeroFloat(float) constant_folding (after) - /// CHECK-DAG: <<Const:f\d+>> FloatConstant 6 - /// CHECK-DAG: Return [<<Const>>] - private static float $inline$SpecialCaseForZeroFloat(float value) { - if (value == 0F) { - return (value + 2F) * 3F; - } - return value; - } - - /// CHECK-START: double Main.$inline$SpecialCaseForZeroDouble(double) constant_folding (before) - /// CHECK-DAG: Add - /// CHECK-DAG: Mul - - /// CHECK-START: double Main.$inline$SpecialCaseForZeroDouble(double) constant_folding (before) - /// CHECK-NOT: DoubleConstant 6 - - /// CHECK-START: double Main.$inline$SpecialCaseForZeroDouble(double) constant_folding (after) - /// CHECK-NOT: Add - - /// CHECK-START: double Main.$inline$SpecialCaseForZeroDouble(double) constant_folding (after) - /// CHECK-NOT: Mul - - /// CHECK-START: double Main.$inline$SpecialCaseForZeroDouble(double) constant_folding (after) - /// CHECK-DAG: <<Const:d\d+>> DoubleConstant 6 - /// CHECK-DAG: Return [<<Const>>] - private static double $inline$SpecialCaseForZeroDouble(double value) { - if (value == 0D) { - return (value + 2D) * 3D; - } - return value; - } - - // Note that we have Add instead of sub since internally we do `Add(value, -1)`. - /// CHECK-START: int Main.$noinline$NotEqualsPropagationInt(int) constant_folding (before) - /// CHECK-DAG: Add - /// CHECK-DAG: Div - - /// CHECK-START: int Main.$noinline$NotEqualsPropagationInt(int) constant_folding (after) - /// CHECK-NOT: Add - - /// CHECK-START: int Main.$noinline$NotEqualsPropagationInt(int) constant_folding (after) - /// CHECK-NOT: Div - - /// CHECK-START: int Main.$noinline$NotEqualsPropagationInt(int) constant_folding (after) - /// CHECK-DAG: <<Const:i\d+>> IntConstant 1 - /// CHECK-DAG: Return [<<Const>>] - private static int $noinline$NotEqualsPropagationInt(int value) { - if (value != 3) { - return value; - } else { - return (value - 1) / 2; - } - } - - /// CHECK-START: long Main.$noinline$NotEqualsPropagationLong(long) constant_folding (before) - /// CHECK-DAG: Sub - /// CHECK-DAG: Div - - /// CHECK-START: long Main.$noinline$NotEqualsPropagationLong(long) constant_folding (after) - /// CHECK-NOT: Sub - - /// CHECK-START: long Main.$noinline$NotEqualsPropagationLong(long) constant_folding (after) - /// CHECK-NOT: Div - - /// CHECK-START: long Main.$noinline$NotEqualsPropagationLong(long) constant_folding (after) - /// CHECK-DAG: <<Const:j\d+>> LongConstant 1 - /// CHECK-DAG: Return [<<Const>>] - private static long $noinline$NotEqualsPropagationLong(long value) { - if (value != 3L) { - return value; - } else { - return (value - 1L) / 2L; - } - } - - /// CHECK-START: float Main.$noinline$NotEqualsPropagationFloat(float) constant_folding (before) - /// CHECK-DAG: Sub - /// CHECK-DAG: Div - - /// CHECK-START: float Main.$noinline$NotEqualsPropagationFloat(float) constant_folding (after) - /// CHECK-NOT: Sub - - /// CHECK-START: float Main.$noinline$NotEqualsPropagationFloat(float) constant_folding (after) - /// CHECK-NOT: Div - - /// CHECK-START: float Main.$noinline$NotEqualsPropagationFloat(float) constant_folding (after) - /// CHECK-DAG: <<Const:f\d+>> FloatConstant 1 - /// CHECK-DAG: Return [<<Const>>] - private static float $noinline$NotEqualsPropagationFloat(float value) { - if (value != 3F) { - return value; - } else { - return (value - 1F) / 2F; - } - } - - /// CHECK-START: double Main.$noinline$NotEqualsPropagationDouble(double) constant_folding (before) - /// CHECK-DAG: Sub - /// CHECK-DAG: Div - - /// CHECK-START: double Main.$noinline$NotEqualsPropagationDouble(double) constant_folding (after) - /// CHECK-NOT: Sub - - /// CHECK-START: double Main.$noinline$NotEqualsPropagationDouble(double) constant_folding (after) - /// CHECK-NOT: Div - - /// CHECK-START: double Main.$noinline$NotEqualsPropagationDouble(double) constant_folding (after) - /// CHECK-DAG: <<Const:d\d+>> DoubleConstant 1 - /// CHECK-DAG: Return [<<Const>>] - private static double $noinline$NotEqualsPropagationDouble(double value) { - if (value != 3D) { - return value; - } else { - return (value - 1D) / 2D; - } - } - - /// CHECK-START: int Main.$noinline$InlineCaleeWithSpecialCaseForZeroInt(int) inliner (after) - /// CHECK-NOT: Add - - /// CHECK-START: int Main.$noinline$InlineCaleeWithSpecialCaseForZeroInt(int) inliner (after) - /// CHECK-NOT: Mul - - /// CHECK-START: int Main.$noinline$InlineCaleeWithSpecialCaseForZeroInt(int) inliner (after) - /// CHECK-DAG: <<Const:i\d+>> IntConstant 6 - /// CHECK-DAG: Return [<<Const>>] - private static int $noinline$InlineCaleeWithSpecialCaseForZeroInt(int value) { - if (value == 0) { - return $inline$SpecialCaseForZeroInt(value); - } - return value; - } - - /// CHECK-START: long Main.$noinline$InlineCaleeWithSpecialCaseForZeroLong(long) inliner (after) - /// CHECK-NOT: Add - - /// CHECK-START: long Main.$noinline$InlineCaleeWithSpecialCaseForZeroLong(long) inliner (after) - /// CHECK-NOT: Mul - - /// CHECK-START: long Main.$noinline$InlineCaleeWithSpecialCaseForZeroLong(long) inliner (after) - /// CHECK-DAG: <<Const:j\d+>> LongConstant 6 - /// CHECK-DAG: Return [<<Const>>] - private static long $noinline$InlineCaleeWithSpecialCaseForZeroLong(long value) { - if (value == 0L) { - return $inline$SpecialCaseForZeroLong(value); - } - return value; - } - - /// CHECK-START: float Main.$noinline$InlineCaleeWithSpecialCaseForZeroFloat(float) inliner (after) - /// CHECK-NOT: Add - - /// CHECK-START: float Main.$noinline$InlineCaleeWithSpecialCaseForZeroFloat(float) inliner (after) - /// CHECK-NOT: Mul - - /// CHECK-START: float Main.$noinline$InlineCaleeWithSpecialCaseForZeroFloat(float) inliner (after) - /// CHECK-DAG: <<Const:f\d+>> FloatConstant 6 - /// CHECK-DAG: Return [<<Const>>] - private static float $noinline$InlineCaleeWithSpecialCaseForZeroFloat(float value) { - if (value == 0F) { - return $inline$SpecialCaseForZeroFloat(value); - } - return value; - } - - /// CHECK-START: double Main.$noinline$InlineCaleeWithSpecialCaseForZeroDouble(double) inliner (after) - /// CHECK-NOT: Add - - /// CHECK-START: double Main.$noinline$InlineCaleeWithSpecialCaseForZeroDouble(double) inliner (after) - /// CHECK-NOT: Mul - - /// CHECK-START: double Main.$noinline$InlineCaleeWithSpecialCaseForZeroDouble(double) inliner (after) - /// CHECK-DAG: <<Const:d\d+>> DoubleConstant 6 - /// CHECK-DAG: Return [<<Const>>] - private static double $noinline$InlineCaleeWithSpecialCaseForZeroDouble(double value) { - if (value == 0D) { - return $inline$SpecialCaseForZeroDouble(value); - } - return value; - } - - // Check that don't propagate the value == 3 on `if not true` branch, as the `if true` branch also - // flows into the same block. - /// CHECK-START: int Main.$noinline$NotEqualsImplicitElseInt(int) constant_folding (before) - /// CHECK-DAG: Add - /// CHECK-DAG: Div - - /// CHECK-START: int Main.$noinline$NotEqualsImplicitElseInt(int) constant_folding (after) - /// CHECK-DAG: Add - /// CHECK-DAG: Div - private static int $noinline$NotEqualsImplicitElseInt(int value) { - if (value != 3) { - value++; - } - return (value - 1) / 2; - } - - /// CHECK-START: long Main.$noinline$NotEqualsImplicitElseLong(long) constant_folding (before) - /// CHECK-DAG: Sub - /// CHECK-DAG: Div - - /// CHECK-START: long Main.$noinline$NotEqualsImplicitElseLong(long) constant_folding (after) - /// CHECK-DAG: Sub - /// CHECK-DAG: Div - private static long $noinline$NotEqualsImplicitElseLong(long value) { - if (value != 3L) { - value += 1L; - } - return (value - 1L) / 2L; - } - - /// CHECK-START: float Main.$noinline$NotEqualsImplicitElseFloat(float) constant_folding (before) - /// CHECK-DAG: Sub - /// CHECK-DAG: Div - - /// CHECK-START: float Main.$noinline$NotEqualsImplicitElseFloat(float) constant_folding (after) - /// CHECK-DAG: Sub - /// CHECK-DAG: Div - private static float $noinline$NotEqualsImplicitElseFloat(float value) { - if (value != 3F) { - value += 1F; - } - return (value - 1F) / 2F; - } - - /// CHECK-START: double Main.$noinline$NotEqualsImplicitElseDouble(double) constant_folding (before) - /// CHECK-DAG: Sub - /// CHECK-DAG: Div - - /// CHECK-START: double Main.$noinline$NotEqualsImplicitElseDouble(double) constant_folding (after) - /// CHECK-DAG: Sub - /// CHECK-DAG: Div - private static double $noinline$NotEqualsImplicitElseDouble(double value) { - if (value != 3D) { - value += 1D; - } - return (value - 1D) / 2D; - } - - // By propagating the boolean we can elimniate some equality comparisons as we already know their - // result. In turn, we also enable DeadCodeElimination to eliminate more code. - /// CHECK-START: int Main.$noinline$PropagatingParameterValue(boolean) constant_folding (before) - /// CHECK-DAG: Equal - /// CHECK-DAG: Equal - /// CHECK-DAG: Equal - - /// CHECK-START: int Main.$noinline$PropagatingParameterValue(boolean) constant_folding (after) - /// CHECK: Equal - /// CHECK-NOT: Equal - - /// CHECK-START: int Main.$noinline$PropagatingParameterValue(boolean) dead_code_elimination$initial (before) - /// CHECK-DAG: IntConstant 1 - /// CHECK-DAG: IntConstant 2 - /// CHECK-DAG: IntConstant 3 - /// CHECK-DAG: IntConstant 4 - - /// CHECK-START: int Main.$noinline$PropagatingParameterValue(boolean) dead_code_elimination$initial (after) - /// CHECK-DAG: IntConstant 1 - /// CHECK-DAG: IntConstant 4 - - /// CHECK-START: int Main.$noinline$PropagatingParameterValue(boolean) dead_code_elimination$initial (after) - /// CHECK-NOT: IntConstant 2 - - /// CHECK-START: int Main.$noinline$PropagatingParameterValue(boolean) dead_code_elimination$initial (after) - /// CHECK-NOT: IntConstant 3 - private static int $noinline$PropagatingParameterValue(boolean value) { - if (value) { - return value ? 1 : 2; - } else { - return value ? 3 : 4; - } - } public static void main(String[] args) throws Exception { assertIntEquals(-42, IntNegation()); @@ -2040,52 +1708,6 @@ public class Main { assertDoubleEquals(33, ReturnDouble33()); assertDoubleEquals(34, ReturnDouble34()); assertDoubleEquals(99.25, ReturnDouble99P25()); - - // Tests for propagating known values due to if clauses. - - // Propagating within the same method. - assertIntEquals(6, $inline$SpecialCaseForZeroInt(0)); - assertIntEquals(3, $inline$SpecialCaseForZeroInt(3)); - assertLongEquals(6L, $inline$SpecialCaseForZeroLong(0L)); - assertLongEquals(3L, $inline$SpecialCaseForZeroLong(3L)); - assertFloatEquals(6F, $inline$SpecialCaseForZeroFloat(0F)); - assertFloatEquals(3F, $inline$SpecialCaseForZeroFloat(3F)); - assertDoubleEquals(6D, $inline$SpecialCaseForZeroDouble(0D)); - assertDoubleEquals(3D, $inline$SpecialCaseForZeroDouble(3D)); - - // Propagating within the same method, with not equals - assertIntEquals(0, $noinline$NotEqualsPropagationInt(0)); - assertIntEquals(1, $noinline$NotEqualsPropagationInt(3)); - assertLongEquals(0L, $noinline$NotEqualsPropagationLong(0L)); - assertLongEquals(1L, $noinline$NotEqualsPropagationLong(3L)); - assertFloatEquals(0F, $noinline$NotEqualsPropagationFloat(0F)); - assertFloatEquals(1F, $noinline$NotEqualsPropagationFloat(3F)); - assertDoubleEquals(0D, $noinline$NotEqualsPropagationDouble(0D)); - assertDoubleEquals(1D, $noinline$NotEqualsPropagationDouble(3D)); - - // Propagating so that the inliner can use it. - assertIntEquals(6, $noinline$InlineCaleeWithSpecialCaseForZeroInt(0)); - assertIntEquals(3, $noinline$InlineCaleeWithSpecialCaseForZeroInt(3)); - assertLongEquals(6L, $noinline$InlineCaleeWithSpecialCaseForZeroLong(0L)); - assertLongEquals(3L, $noinline$InlineCaleeWithSpecialCaseForZeroLong(3L)); - assertFloatEquals(6F, $noinline$InlineCaleeWithSpecialCaseForZeroFloat(0F)); - assertFloatEquals(3F, $noinline$InlineCaleeWithSpecialCaseForZeroFloat(3F)); - assertDoubleEquals(6D, $noinline$InlineCaleeWithSpecialCaseForZeroDouble(0D)); - assertDoubleEquals(3D, $noinline$InlineCaleeWithSpecialCaseForZeroDouble(3D)); - - // Propagating within the same method, with not equals - assertIntEquals(0, $noinline$NotEqualsImplicitElseInt(0)); - assertIntEquals(1, $noinline$NotEqualsImplicitElseInt(3)); - assertLongEquals(0L, $noinline$NotEqualsImplicitElseLong(0L)); - assertLongEquals(1L, $noinline$NotEqualsImplicitElseLong(3L)); - assertFloatEquals(0F, $noinline$NotEqualsImplicitElseFloat(0F)); - assertFloatEquals(1F, $noinline$NotEqualsImplicitElseFloat(3F)); - assertDoubleEquals(0D, $noinline$NotEqualsImplicitElseDouble(0D)); - assertDoubleEquals(1D, $noinline$NotEqualsImplicitElseDouble(3D)); - - // Propagating parameters. - assertIntEquals(1, $noinline$PropagatingParameterValue(true)); - assertIntEquals(4, $noinline$PropagatingParameterValue(false)); } Main() throws ClassNotFoundException { diff --git a/test/449-checker-bce/src/Main.java b/test/449-checker-bce/src/Main.java index fbe3586800..1144366dfb 100644 --- a/test/449-checker-bce/src/Main.java +++ b/test/449-checker-bce/src/Main.java @@ -1125,7 +1125,7 @@ public class Main { /// CHECK-DAG: <<Len:i\d+>> ArrayLength [<<Nul>>] loop:none /// CHECK-DAG: Equal [<<Len>>,<<Val>>] loop:none /// CHECK-DAG: <<Idx:i\d+>> Phi loop:<<Loop:B\d+>> - /// CHECK-DAG: BoundsCheck [<<Idx>>,<<Val>>] loop:<<Loop>> + /// CHECK-DAG: BoundsCheck [<<Idx>>,<<Len>>] loop:<<Loop>> // /// CHECK-START: void Main.lengthAlias4(int[]) BCE (after) /// CHECK-NOT: BoundsCheck diff --git a/test/485-checker-dce-loop-update/smali/TestCase.smali b/test/485-checker-dce-loop-update/smali/TestCase.smali index 3e7bca93c9..5290bad3ed 100644 --- a/test/485-checker-dce-loop-update/smali/TestCase.smali +++ b/test/485-checker-dce-loop-update/smali/TestCase.smali @@ -224,7 +224,7 @@ ## CHECK-DAG: If [<<ArgY>>] loop:<<HeaderY>> # # ### Inner loop ### -## CHECK-DAG: <<PhiZ2:i\d+>> Phi [<<PhiZ1>>,<<Cst0>>] loop:<<HeaderZ:B\d+>> +## CHECK-DAG: <<PhiZ2:i\d+>> Phi [<<PhiZ1>>,<<XorZ>>] loop:<<HeaderZ:B\d+>> ## CHECK-DAG: <<XorZ>> Xor [<<PhiZ2>>,<<Cst1>>] loop:<<HeaderZ>> ## CHECK-DAG: <<CondZ:z\d+>> Equal [<<XorZ>>,<<Cst0>>] loop:<<HeaderZ>> ## CHECK-DAG: If [<<CondZ>>] loop:<<HeaderZ>> @@ -246,8 +246,8 @@ ## CHECK-DAG: <<Add7>> Add [<<PhiX>>,<<Cst7>>] loop:<<HeaderY>> # # ### Inner loop ### -## CHECK-DAG: <<PhiZ:i\d+>> Phi [<<ArgZ>>,<<Cst0>>] loop:<<HeaderZ:B\d+>> -## CHECK-DAG: <<XorZ:i\d+>> Xor [<<PhiZ>>,<<Cst1>>] loop:<<HeaderZ>> +## CHECK-DAG: <<PhiZ:i\d+>> Phi [<<ArgZ>>,<<XorZ:i\d+>>] loop:<<HeaderZ:B\d+>> +## CHECK-DAG: <<XorZ>> Xor [<<PhiZ>>,<<Cst1>>] loop:<<HeaderZ>> ## CHECK-DAG: <<CondZ:z\d+>> Equal [<<XorZ>>,<<Cst0>>] loop:<<HeaderZ>> ## CHECK-DAG: If [<<CondZ>>] loop:<<HeaderZ>> # diff --git a/test/543-checker-dce-trycatch/smali/TestCase.smali b/test/543-checker-dce-trycatch/smali/TestCase.smali index 15eaabbc04..7ad9ba8e64 100644 --- a/test/543-checker-dce-trycatch/smali/TestCase.smali +++ b/test/543-checker-dce-trycatch/smali/TestCase.smali @@ -206,7 +206,6 @@ ## CHECK-START: int TestCase.testCatchPhiInputs_DefinedInTryBlock(int, int, int, int) dead_code_elimination$after_inlining (before) ## CHECK-DAG: <<Arg0:i\d+>> ParameterValue ## CHECK-DAG: <<Arg1:i\d+>> ParameterValue -## CHECK-DAG: <<Const0x0:i\d+>> IntConstant 0 ## CHECK-DAG: <<Const0xa:i\d+>> IntConstant 10 ## CHECK-DAG: <<Const0xb:i\d+>> IntConstant 11 ## CHECK-DAG: <<Const0xc:i\d+>> IntConstant 12 @@ -216,7 +215,7 @@ ## CHECK-DAG: <<Const0x10:i\d+>> IntConstant 16 ## CHECK-DAG: <<Const0x11:i\d+>> IntConstant 17 ## CHECK-DAG: <<Add:i\d+>> Add [<<Arg0>>,<<Arg1>>] -## CHECK-DAG: <<Phi:i\d+>> Phi [<<Const0x0>>,<<Const0xf>>] reg:3 is_catch_phi:false +## CHECK-DAG: <<Phi:i\d+>> Phi [<<Add>>,<<Const0xf>>] reg:3 is_catch_phi:false ## CHECK-DAG: Phi [<<Const0xa>>,<<Const0xb>>,<<Const0xd>>] reg:1 is_catch_phi:true ## CHECK-DAG: Phi [<<Add>>,<<Const0xc>>,<<Const0xe>>] reg:2 is_catch_phi:true ## CHECK-DAG: Phi [<<Phi>>,<<Const0x10>>,<<Const0x11>>] reg:3 is_catch_phi:true @@ -249,8 +248,7 @@ if-eqz v3, :define_phi const v3, 0xf :define_phi - # v3 = Phi [Add, 0xf] # dead catch phi input, defined in the dead block (HPhi). - # Note that the Add has to be equal to 0 since we do `if-eqz v3` + # v3 = Phi [Add, 0xf] # dead catch phi input, defined in the dead block (HPhi) div-int/2addr p0, v2 :else diff --git a/test/559-checker-irreducible-loop/smali/IrreducibleLoop.smali b/test/559-checker-irreducible-loop/smali/IrreducibleLoop.smali index 493567cac5..a30a11afb7 100644 --- a/test/559-checker-irreducible-loop/smali/IrreducibleLoop.smali +++ b/test/559-checker-irreducible-loop/smali/IrreducibleLoop.smali @@ -140,23 +140,24 @@ # other_loop_entry # i1 = phi(p0, i0) # -## CHECK-START: int IrreducibleLoop.liveness(int, int) liveness (after) +## CHECK-START: int IrreducibleLoop.liveness(int) liveness (after) ## CHECK-DAG: <<Arg:i\d+>> ParameterValue liveness:<<ArgLiv:\d+>> ranges:{[<<ArgLiv>>,<<ArgLoopPhiUse:\d+>>)} ## CHECK-DAG: <<LoopPhi:i\d+>> Phi [<<Arg>>,<<PhiInLoop:i\d+>>] liveness:<<ArgLoopPhiUse>> ranges:{[<<ArgLoopPhiUse>>,<<PhiInLoopUse:\d+>>)} ## CHECK-DAG: <<PhiInLoop>> Phi [<<Arg>>,<<LoopPhi>>] liveness:<<PhiInLoopUse>> ranges:{[<<PhiInLoopUse>>,<<BackEdgeLifetimeEnd:\d+>>)} ## CHECK: Return liveness:<<ReturnLiveness:\d+>> ## CHECK-EVAL: <<ReturnLiveness>> == <<BackEdgeLifetimeEnd>> + 2 -.method public static liveness(II)I +.method public static liveness(I)I .registers 2 - if-eq p0, p1, :other_loop_entry + const/16 v0, 42 + if-eq p0, v0, :other_loop_entry :loop_entry - add-int p1, p1, p0 - if-ne v0, p1, :exit + add-int v0, v0, p0 + if-ne v1, v0, :exit :other_loop_entry - add-int p1, p1, p1 + add-int v0, v0, v0 goto :loop_entry :exit - return p1 + return v0 .end method # Check that we don't GVN across irreducible loops: diff --git a/test/559-checker-irreducible-loop/src/Main.java b/test/559-checker-irreducible-loop/src/Main.java index b22e9b828e..97165eca6e 100644 --- a/test/559-checker-irreducible-loop/src/Main.java +++ b/test/559-checker-irreducible-loop/src/Main.java @@ -38,8 +38,8 @@ public class Main { } { - Method m = c.getMethod("liveness", int.class, int.class); - Object[] arguments = { 42, 42 }; + Method m = c.getMethod("liveness", int.class); + Object[] arguments = { 42 }; System.out.println(m.invoke(null, arguments)); } diff --git a/test/563-checker-fakestring/smali/TestCase.smali b/test/563-checker-fakestring/smali/TestCase.smali index c6561d5386..4721ecaa09 100644 --- a/test/563-checker-fakestring/smali/TestCase.smali +++ b/test/563-checker-fakestring/smali/TestCase.smali @@ -310,7 +310,7 @@ ## CHECK-NOT: NewInstance ## CHECK-DAG: <<Invoke1:l\d+>> InvokeStaticOrDirect method_name:java.lang.String.<init> ## CHECK-DAG: <<Invoke2:l\d+>> InvokeStaticOrDirect method_name:java.lang.String.<init> -## CHECK-DAG: <<Phi:l\d+>> Phi [<<Invoke1>>,<<Invoke2>>] +## CHECK-DAG: <<Phi:l\d+>> Phi [<<Invoke2>>,<<Invoke1>>] ## CHECK-DAG: Return [<<Phi>>] .method public static loopAndStringInitAndPhi([BZ)Ljava/lang/String; .registers 4 diff --git a/test/564-checker-inline-loop/src/Main.java b/test/564-checker-inline-loop/src/Main.java index 41eca3531d..6929913864 100644 --- a/test/564-checker-inline-loop/src/Main.java +++ b/test/564-checker-inline-loop/src/Main.java @@ -21,6 +21,9 @@ public class Main { /// CHECK-DAG: Return [<<Invoke>>] /// CHECK-START: int Main.inlineLoop() inliner (after) + /// CHECK-NOT: InvokeStaticOrDirect + + /// CHECK-START: int Main.inlineLoop() inliner (after) /// CHECK-DAG: <<Constant:i\d+>> IntConstant 42 /// CHECK-DAG: Return [<<Constant>>] @@ -28,31 +31,31 @@ public class Main { /// CHECK: Goto loop:{{B\d+}} public static int inlineLoop() { - return $inline$loopMethod(); + return loopMethod(); } /// CHECK-START: void Main.inlineWithinLoop() inliner (before) /// CHECK: InvokeStaticOrDirect + /// CHECK-START: void Main.inlineWithinLoop() inliner (after) + /// CHECK-NOT: InvokeStaticOrDirect + /// CHECK-START: void Main.inlineWithinLoop() licm (after) /// CHECK-DAG: Goto loop:<<OuterLoop:B\d+>> outer_loop:none /// CHECK-DAG: Goto outer_loop:<<OuterLoop>> public static void inlineWithinLoop() { while (doLoop) { - $inline$loopMethod(); + loopMethod(); } } - public static int $inline$loopMethod() { - // We use `otherDoLoop` here so we don't propagate the knowledge that `doLoop` is true when - // inlining from `inlineWithinLoop`. - while (otherDoLoop) {} + public static int loopMethod() { + while (doLoop) {} return 42; } public static boolean doLoop = false; - public static boolean otherDoLoop = false; public static void main(String[] args) { inlineLoop(); diff --git a/test/596-checker-dead-phi/smali/IrreducibleLoop.smali b/test/596-checker-dead-phi/smali/IrreducibleLoop.smali index 9f822bf19b..bab2ba99cc 100644 --- a/test/596-checker-dead-phi/smali/IrreducibleLoop.smali +++ b/test/596-checker-dead-phi/smali/IrreducibleLoop.smali @@ -20,19 +20,18 @@ # not adjacent. This revealed a bug in our SSA builder, where a dead loop phi would # be replaced by its incoming input during SsaRedundantPhiElimination. -# Check that the outer loop suspend check environment only has the two parameter vregs. -## CHECK-START: int IrreducibleLoop.liveness(int, int) builder (after) -## CHECK-DAG: <<Phi1:i\d+>> Phi reg:3 loop:{{B\d+}} irreducible:false -## CHECK-DAG: <<Phi2:i\d+>> Phi reg:4 loop:{{B\d+}} irreducible:false -## CHECK-DAG: SuspendCheck env:[[_,_,_,<<Phi1>>,<<Phi2>>]] loop:{{B\d+}} irreducible:false +# Check that the outer loop suspend check environment only has the parameter vreg. +## CHECK-START: int IrreducibleLoop.liveness(int) builder (after) +## CHECK-DAG: <<Phi:i\d+>> Phi reg:4 loop:{{B\d+}} irreducible:false +## CHECK-DAG: SuspendCheck env:[[_,_,_,_,<<Phi>>]] loop:{{B\d+}} irreducible:false # Check that the linear order has non-adjacent loop blocks. -## CHECK-START: int IrreducibleLoop.liveness(int, int) liveness (after) +## CHECK-START: int IrreducibleLoop.liveness(int) liveness (after) ## CHECK-DAG: Mul liveness:<<LPreEntry2:\d+>> ## CHECK-DAG: Add liveness:<<LBackEdge1:\d+>> ## CHECK-EVAL: <<LBackEdge1>> < <<LPreEntry2>> -.method public static liveness(II)I +.method public static liveness(I)I .registers 5 const-string v1, "MyString" @@ -51,9 +50,8 @@ if-ne v2, v3, :pre_header2 :pre_entry2 - # Add a marker on the irreducible loop entry. Here we use p1 because p0 is a - # known constant and we eliminate the Mul otherwise. - mul-int/2addr p1, p1 + # Add a marker on the irreducible loop entry. + mul-int/2addr p0, p0 goto :back_edge2 :back_edge2 @@ -63,9 +61,8 @@ if-eqz p0, :back_edge2 :back_edge1 - # Add a marker on the outer loop back edge. Here we use p1 because p0 is a - # known constant and we eliminate the Add otherwise. - add-int/2addr p1, p1 + # Add a marker on the outer loop back edge. + add-int/2addr p0, p0 # Set a wide register, to have v1 undefined at the back edge. const-wide/16 v0, 0x1 goto :header1 diff --git a/test/596-checker-dead-phi/src/Main.java b/test/596-checker-dead-phi/src/Main.java index c3384adb95..f3a55df46a 100644 --- a/test/596-checker-dead-phi/src/Main.java +++ b/test/596-checker-dead-phi/src/Main.java @@ -22,8 +22,8 @@ public class Main { // Note that we don't actually enter the loops in the 'liveness' // method, so this is just a verification that that part of the code we // generated for that method is correct. - Method m = c.getMethod("liveness", int.class, int.class); - Object[] arguments = {42, 12}; + Method m = c.getMethod("liveness", int.class); + Object[] arguments = { 42 }; System.out.println(m.invoke(null, arguments)); } } |