diff options
author | 2023-03-10 15:58:17 +0000 | |
---|---|---|
committer | 2023-10-10 12:51:37 +0000 | |
commit | d003e7530ed0b00df5504cf57f0dd6479629c67a (patch) | |
tree | 205938c02bfb914f007fc4e7e30f78b9b50b63e4 | |
parent | 472f6bced8e088fe8f97213587933e0c4420238f (diff) |
Add optimization to simplify Select+Binary/Unary ops
We can simplify a Select + Binary/Unary Op if:
* Both inputs to the Select instruction are constant, and
* The Select instruction is not used in another instruction
to avoid duplicating Selects.
* In the case of Binary ops, both inputs can't be Select.
Test: art/test/testrunner/testrunner.py --host --64 --optimizing -b
Change-Id: Ic716155e9a8515126c2867bb1d54593fa63011ae
-rw-r--r-- | compiler/optimizing/constant_folding.cc | 88 | ||||
-rw-r--r-- | compiler/optimizing/nodes.cc | 72 | ||||
-rw-r--r-- | compiler/optimizing/nodes.h | 15 | ||||
-rw-r--r-- | test/2265-checker-select-binary-unary/expected-stderr.txt | 0 | ||||
-rw-r--r-- | test/2265-checker-select-binary-unary/expected-stdout.txt | 0 | ||||
-rw-r--r-- | test/2265-checker-select-binary-unary/info.txt | 5 | ||||
-rw-r--r-- | test/2265-checker-select-binary-unary/src/Main.java | 145 | ||||
-rw-r--r-- | test/567-checker-builder-intrinsics/src/TestSignum.java | 8 | ||||
-rw-r--r-- | test/570-checker-select/src/Main.java | 1 | ||||
-rw-r--r-- | test/593-checker-boolean-2-integral-conv/smali/SmaliTests.smali | 6 | ||||
-rw-r--r-- | test/646-checker-long-const-to-int/src/Main.java | 10 |
11 files changed, 305 insertions, 45 deletions
diff --git a/compiler/optimizing/constant_folding.cc b/compiler/optimizing/constant_folding.cc index 2163c007e6..e20d9e83e6 100644 --- a/compiler/optimizing/constant_folding.cc +++ b/compiler/optimizing/constant_folding.cc @@ -37,6 +37,13 @@ class HConstantFoldingVisitor final : public HGraphDelegateVisitor { void VisitUnaryOperation(HUnaryOperation* inst) override; void VisitBinaryOperation(HBinaryOperation* inst) override; + // Tries to replace constants in binary operations like: + // * BinaryOp(Select(false_constant, true_constant, condition), other_constant), or + // * BinaryOp(other_constant, Select(false_constant, true_constant, condition)) + // with consolidated constants. For example, Add(Select(10, 20, condition), 5) can be replaced + // with Select(15, 25, condition). + bool TryRemoveBinaryOperationViaSelect(HBinaryOperation* inst); + void VisitArrayLength(HArrayLength* inst) override; void VisitDivZeroCheck(HDivZeroCheck* inst) override; void VisitIf(HIf* inst) override; @@ -113,9 +120,69 @@ void HConstantFoldingVisitor::VisitUnaryOperation(HUnaryOperation* inst) { if (constant != nullptr) { inst->ReplaceWith(constant); inst->GetBlock()->RemoveInstruction(inst); + } else if (inst->InputAt(0)->IsSelect() && inst->InputAt(0)->HasOnlyOneNonEnvironmentUse()) { + // Try to replace the select's inputs in Select+UnaryOperation cases. We can do this if both + // inputs to the select are constants, and this is the only use of the select. + HSelect* select = inst->InputAt(0)->AsSelect(); + HConstant* false_constant = inst->TryStaticEvaluation(select->GetFalseValue()); + if (false_constant == nullptr) { + return; + } + HConstant* true_constant = inst->TryStaticEvaluation(select->GetTrueValue()); + if (true_constant == nullptr) { + return; + } + DCHECK_EQ(select->InputAt(0), select->GetFalseValue()); + DCHECK_EQ(select->InputAt(1), select->GetTrueValue()); + select->ReplaceInput(false_constant, 0); + select->ReplaceInput(true_constant, 1); + select->UpdateType(); + inst->ReplaceWith(select); + inst->GetBlock()->RemoveInstruction(inst); } } +bool HConstantFoldingVisitor::TryRemoveBinaryOperationViaSelect(HBinaryOperation* inst) { + if (inst->GetLeft()->IsSelect() == inst->GetRight()->IsSelect()) { + // If both of them are constants, VisitBinaryOperation already tried the static evaluation. If + // both of them are selects, then we can't simplify. + // TODO(solanes): Technically, if both of them are selects we could simplify iff both select's + // conditions are equal e.g. Add(Select(1, 2, cond), Select(3, 4, cond)) could be replaced with + // Select(4, 6, cond). This seems very unlikely to happen so we don't implement it. + return false; + } + + const bool left_is_select = inst->GetLeft()->IsSelect(); + HSelect* select = left_is_select ? inst->GetLeft()->AsSelect() : inst->GetRight()->AsSelect(); + HInstruction* maybe_constant = left_is_select ? inst->GetRight() : inst->GetLeft(); + + if (select->HasOnlyOneNonEnvironmentUse()) { + // Try to replace the select's inputs in Select+BinaryOperation. We can do this if both + // inputs to the select are constants, and this is the only use of the select. + HConstant* false_constant = + inst->TryStaticEvaluation(left_is_select ? select->GetFalseValue() : maybe_constant, + left_is_select ? maybe_constant : select->GetFalseValue()); + if (false_constant == nullptr) { + return false; + } + HConstant* true_constant = + inst->TryStaticEvaluation(left_is_select ? select->GetTrueValue() : maybe_constant, + left_is_select ? maybe_constant : select->GetTrueValue()); + if (true_constant == nullptr) { + return false; + } + DCHECK_EQ(select->InputAt(0), select->GetFalseValue()); + DCHECK_EQ(select->InputAt(1), select->GetTrueValue()); + select->ReplaceInput(false_constant, 0); + select->ReplaceInput(true_constant, 1); + select->UpdateType(); + inst->ReplaceWith(select); + inst->GetBlock()->RemoveInstruction(inst); + return true; + } + return false; +} + void HConstantFoldingVisitor::VisitBinaryOperation(HBinaryOperation* inst) { // Constant folding: replace `op(a, b)' with a constant at // compile time if `a' and `b' are both constants. @@ -123,6 +190,8 @@ void HConstantFoldingVisitor::VisitBinaryOperation(HBinaryOperation* inst) { if (constant != nullptr) { inst->ReplaceWith(constant); inst->GetBlock()->RemoveInstruction(inst); + } else if (TryRemoveBinaryOperationViaSelect(inst)) { + // Already replaced inside TryRemoveBinaryOperationViaSelect. } else { InstructionWithAbsorbingInputSimplifier simplifier(GetGraph()); inst->Accept(&simplifier); @@ -299,6 +368,25 @@ void HConstantFoldingVisitor::VisitTypeConversion(HTypeConversion* inst) { if (constant != nullptr) { inst->ReplaceWith(constant); inst->GetBlock()->RemoveInstruction(inst); + } else if (inst->InputAt(0)->IsSelect() && inst->InputAt(0)->HasOnlyOneNonEnvironmentUse()) { + // Try to replace the select's inputs in Select+TypeConversion. We can do this if both + // inputs to the select are constants, and this is the only use of the select. + HSelect* select = inst->InputAt(0)->AsSelect(); + HConstant* false_constant = inst->TryStaticEvaluation(select->GetFalseValue()); + if (false_constant == nullptr) { + return; + } + HConstant* true_constant = inst->TryStaticEvaluation(select->GetTrueValue()); + if (true_constant == nullptr) { + return; + } + DCHECK_EQ(select->InputAt(0), select->GetFalseValue()); + DCHECK_EQ(select->InputAt(1), select->GetTrueValue()); + select->ReplaceInput(false_constant, 0); + select->ReplaceInput(true_constant, 1); + select->UpdateType(); + inst->ReplaceWith(select); + inst->GetBlock()->RemoveInstruction(inst); } } diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc index 2b7e384f34..5795ea7ca9 100644 --- a/compiler/optimizing/nodes.cc +++ b/compiler/optimizing/nodes.cc @@ -1816,10 +1816,12 @@ void HGraphVisitor::VisitBasicBlock(HBasicBlock* block) { } } -HConstant* HTypeConversion::TryStaticEvaluation() const { - HGraph* graph = GetBlock()->GetGraph(); - if (GetInput()->IsIntConstant()) { - int32_t value = GetInput()->AsIntConstant()->GetValue(); +HConstant* HTypeConversion::TryStaticEvaluation() const { return TryStaticEvaluation(GetInput()); } + +HConstant* HTypeConversion::TryStaticEvaluation(HInstruction* input) const { + HGraph* graph = input->GetBlock()->GetGraph(); + if (input->IsIntConstant()) { + int32_t value = input->AsIntConstant()->GetValue(); switch (GetResultType()) { case DataType::Type::kInt8: return graph->GetIntConstant(static_cast<int8_t>(value), GetDexPc()); @@ -1838,8 +1840,8 @@ HConstant* HTypeConversion::TryStaticEvaluation() const { default: return nullptr; } - } else if (GetInput()->IsLongConstant()) { - int64_t value = GetInput()->AsLongConstant()->GetValue(); + } else if (input->IsLongConstant()) { + int64_t value = input->AsLongConstant()->GetValue(); switch (GetResultType()) { case DataType::Type::kInt8: return graph->GetIntConstant(static_cast<int8_t>(value), GetDexPc()); @@ -1858,8 +1860,8 @@ HConstant* HTypeConversion::TryStaticEvaluation() const { default: return nullptr; } - } else if (GetInput()->IsFloatConstant()) { - float value = GetInput()->AsFloatConstant()->GetValue(); + } else if (input->IsFloatConstant()) { + float value = input->AsFloatConstant()->GetValue(); switch (GetResultType()) { case DataType::Type::kInt32: if (std::isnan(value)) @@ -1882,8 +1884,8 @@ HConstant* HTypeConversion::TryStaticEvaluation() const { default: return nullptr; } - } else if (GetInput()->IsDoubleConstant()) { - double value = GetInput()->AsDoubleConstant()->GetValue(); + } else if (input->IsDoubleConstant()) { + double value = input->AsDoubleConstant()->GetValue(); switch (GetResultType()) { case DataType::Type::kInt32: if (std::isnan(value)) @@ -1910,41 +1912,47 @@ HConstant* HTypeConversion::TryStaticEvaluation() const { return nullptr; } -HConstant* HUnaryOperation::TryStaticEvaluation() const { - if (GetInput()->IsIntConstant()) { - return Evaluate(GetInput()->AsIntConstant()); - } else if (GetInput()->IsLongConstant()) { - return Evaluate(GetInput()->AsLongConstant()); +HConstant* HUnaryOperation::TryStaticEvaluation() const { return TryStaticEvaluation(GetInput()); } + +HConstant* HUnaryOperation::TryStaticEvaluation(HInstruction* input) const { + if (input->IsIntConstant()) { + return Evaluate(input->AsIntConstant()); + } else if (input->IsLongConstant()) { + return Evaluate(input->AsLongConstant()); } else if (kEnableFloatingPointStaticEvaluation) { - if (GetInput()->IsFloatConstant()) { - return Evaluate(GetInput()->AsFloatConstant()); - } else if (GetInput()->IsDoubleConstant()) { - return Evaluate(GetInput()->AsDoubleConstant()); + if (input->IsFloatConstant()) { + return Evaluate(input->AsFloatConstant()); + } else if (input->IsDoubleConstant()) { + return Evaluate(input->AsDoubleConstant()); } } return nullptr; } HConstant* HBinaryOperation::TryStaticEvaluation() const { - if (GetLeft()->IsIntConstant() && GetRight()->IsIntConstant()) { - return Evaluate(GetLeft()->AsIntConstant(), GetRight()->AsIntConstant()); - } else if (GetLeft()->IsLongConstant()) { - if (GetRight()->IsIntConstant()) { + return TryStaticEvaluation(GetLeft(), GetRight()); +} + +HConstant* HBinaryOperation::TryStaticEvaluation(HInstruction* left, HInstruction* right) const { + if (left->IsIntConstant() && right->IsIntConstant()) { + return Evaluate(left->AsIntConstant(), right->AsIntConstant()); + } else if (left->IsLongConstant()) { + if (right->IsIntConstant()) { // The binop(long, int) case is only valid for shifts and rotations. DCHECK(IsShl() || IsShr() || IsUShr() || IsRor()) << DebugName(); - return Evaluate(GetLeft()->AsLongConstant(), GetRight()->AsIntConstant()); - } else if (GetRight()->IsLongConstant()) { - return Evaluate(GetLeft()->AsLongConstant(), GetRight()->AsLongConstant()); + return Evaluate(left->AsLongConstant(), right->AsIntConstant()); + } else if (right->IsLongConstant()) { + return Evaluate(left->AsLongConstant(), right->AsLongConstant()); } - } else if (GetLeft()->IsNullConstant() && GetRight()->IsNullConstant()) { + } else if (left->IsNullConstant() && right->IsNullConstant()) { // The binop(null, null) case is only valid for equal and not-equal conditions. DCHECK(IsEqual() || IsNotEqual()) << DebugName(); - return Evaluate(GetLeft()->AsNullConstant(), GetRight()->AsNullConstant()); + return Evaluate(left->AsNullConstant(), right->AsNullConstant()); } else if (kEnableFloatingPointStaticEvaluation) { - if (GetLeft()->IsFloatConstant() && GetRight()->IsFloatConstant()) { - return Evaluate(GetLeft()->AsFloatConstant(), GetRight()->AsFloatConstant()); - } else if (GetLeft()->IsDoubleConstant() && GetRight()->IsDoubleConstant()) { - return Evaluate(GetLeft()->AsDoubleConstant(), GetRight()->AsDoubleConstant()); + if (left->IsFloatConstant() && right->IsFloatConstant()) { + return Evaluate(left->AsFloatConstant(), right->AsFloatConstant()); + } else if (left->IsDoubleConstant() && right->IsDoubleConstant()) { + return Evaluate(left->AsDoubleConstant(), right->AsDoubleConstant()); } } return nullptr; diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index 3f60ec5241..9cf52183b8 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -3858,6 +3858,9 @@ class HUnaryOperation : public HExpression<1> { // be evaluated as a constant, return null. HConstant* TryStaticEvaluation() const; + // Same but for `input` instead of GetInput(). + HConstant* TryStaticEvaluation(HInstruction* input) const; + // Apply this operation to `x`. virtual HConstant* Evaluate(HIntConstant* x) const = 0; virtual HConstant* Evaluate(HLongConstant* x) const = 0; @@ -3934,6 +3937,9 @@ class HBinaryOperation : public HExpression<2> { // be evaluated as a constant, return null. HConstant* TryStaticEvaluation() const; + // Same but for `left` and `right` instead of GetLeft() and GetRight(). + HConstant* TryStaticEvaluation(HInstruction* left, HInstruction* right) const; + // Apply this operation to `x` and `y`. virtual HConstant* Evaluate([[maybe_unused]] HNullConstant* x, [[maybe_unused]] HNullConstant* y) const { @@ -6188,6 +6194,9 @@ class HTypeConversion final : public HExpression<1> { // containing the result. If the input cannot be converted, return nullptr. HConstant* TryStaticEvaluation() const; + // Same but for `input` instead of GetInput(). + HConstant* TryStaticEvaluation(HInstruction* input) const; + DECLARE_INSTRUCTION(TypeConversion); protected: @@ -8377,6 +8386,12 @@ class HSelect final : public HExpression<3> { return GetTrueValue()->CanBeNull() || GetFalseValue()->CanBeNull(); } + void UpdateType() { + DCHECK_EQ(HPhi::ToPhiType(GetTrueValue()->GetType()), + HPhi::ToPhiType(GetFalseValue()->GetType())); + SetPackedField<TypeField>(HPhi::ToPhiType(GetTrueValue()->GetType())); + } + DECLARE_INSTRUCTION(Select); protected: diff --git a/test/2265-checker-select-binary-unary/expected-stderr.txt b/test/2265-checker-select-binary-unary/expected-stderr.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/2265-checker-select-binary-unary/expected-stderr.txt diff --git a/test/2265-checker-select-binary-unary/expected-stdout.txt b/test/2265-checker-select-binary-unary/expected-stdout.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/2265-checker-select-binary-unary/expected-stdout.txt diff --git a/test/2265-checker-select-binary-unary/info.txt b/test/2265-checker-select-binary-unary/info.txt new file mode 100644 index 0000000000..b20b11a604 --- /dev/null +++ b/test/2265-checker-select-binary-unary/info.txt @@ -0,0 +1,5 @@ +Tests that we can simplify a Select + Binary/UnaryOps if: + * Both inputs to the Select instruction are constant, and + * The Select instruction is not used in another instruction + to avoid duplicating Selects. + * In the case of Binary ops, both inputs can't be Select. diff --git a/test/2265-checker-select-binary-unary/src/Main.java b/test/2265-checker-select-binary-unary/src/Main.java new file mode 100644 index 0000000000..33734fc4d6 --- /dev/null +++ b/test/2265-checker-select-binary-unary/src/Main.java @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import java.lang.reflect.Method; + +public class Main { + public static void main(String[] args) throws Throwable { + assertLongEquals(11L, $noinline$testIntToLong(0, 1)); + assertLongEquals(12L, $noinline$testIntToLong(1, 0)); + + assertFloatEquals(11f, $noinline$testIntToFloat(0, 1)); + assertFloatEquals(12f, $noinline$testIntToFloat(1, 0)); + + assertIntEquals(11, $noinline$testIntToByte(0, 1)); + assertIntEquals(12, $noinline$testIntToByte(1, 0)); + + assertIntEquals(11, $noinline$testLongToInt(0, 1)); + assertIntEquals(12, $noinline$testLongToInt(1, 0)); + } + + /// CHECK-START: long Main.$noinline$testIntToLong(int, int) select_generator (after) + /// CHECK: <<Const10:j\d+>> LongConstant 10 + /// CHECK: <<Const1:i\d+>> IntConstant 1 + /// CHECK: <<Const2:i\d+>> IntConstant 2 + /// CHECK: <<Sel:i\d+>> Select [<<Const1>>,<<Const2>>,<<Condition:z\d+>>] + /// CHECK: <<Type:j\d+>> TypeConversion [<<Sel>>] + /// CHECK: Add [<<Type>>,<<Const10>>] + + /// CHECK-START: long Main.$noinline$testIntToLong(int, int) constant_folding$after_gvn (after) + /// CHECK: <<Const11:j\d+>> LongConstant 11 + /// CHECK: <<Const12:j\d+>> LongConstant 12 + /// CHECK: Select [<<Const11>>,<<Const12>>,<<Condition:z\d+>>] + + /// CHECK-START: long Main.$noinline$testIntToLong(int, int) constant_folding$after_gvn (after) + /// CHECK-NOT: TypeConversion + /// CHECK-NOT: Add + private static long $noinline$testIntToLong(int a, int b) { + long result = 10; + int c = 1; + int d = 2; + return result + (a < b ? c : d); + } + + /// CHECK-START: float Main.$noinline$testIntToFloat(int, int) select_generator (after) + /// CHECK: <<Const10:f\d+>> FloatConstant 10 + /// CHECK: <<Const1:i\d+>> IntConstant 1 + /// CHECK: <<Const2:i\d+>> IntConstant 2 + /// CHECK: <<Sel:i\d+>> Select [<<Const1>>,<<Const2>>,<<Condition:z\d+>>] + /// CHECK: <<Type:f\d+>> TypeConversion [<<Sel>>] + /// CHECK: Add [<<Type>>,<<Const10>>] + + /// CHECK-START: float Main.$noinline$testIntToFloat(int, int) constant_folding$after_gvn (after) + /// CHECK: <<Const11:f\d+>> FloatConstant 11 + /// CHECK: <<Const12:f\d+>> FloatConstant 12 + /// CHECK: Select [<<Const11>>,<<Const12>>,<<Condition:z\d+>>] + + /// CHECK-START: float Main.$noinline$testIntToFloat(int, int) constant_folding$after_gvn (after) + /// CHECK-NOT: TypeConversion + /// CHECK-NOT: Add + private static float $noinline$testIntToFloat(int a, int b) { + float result = 10; + int c = 1; + int d = 2; + return result + (a < b ? c : d); + } + + /// CHECK-START: byte Main.$noinline$testIntToByte(int, int) select_generator (after) + /// CHECK: <<Const10:i\d+>> IntConstant 10 + /// CHECK: <<Const257:i\d+>> IntConstant 257 + /// CHECK: <<Const258:i\d+>> IntConstant 258 + /// CHECK: <<Sel:i\d+>> Select [<<Const257>>,<<Const258>>,<<Condition:z\d+>>] + /// CHECK: <<Type:b\d+>> TypeConversion [<<Sel>>] + /// CHECK: Add [<<Type>>,<<Const10>>] + + /// CHECK-START: byte Main.$noinline$testIntToByte(int, int) constant_folding$after_gvn (after) + /// CHECK: <<Const11:i\d+>> IntConstant 11 + /// CHECK: <<Const12:i\d+>> IntConstant 12 + /// CHECK: Select [<<Const11>>,<<Const12>>,<<Condition:z\d+>>] + + /// CHECK-START: byte Main.$noinline$testIntToByte(int, int) constant_folding$after_gvn (after) + /// CHECK-NOT: TypeConversion + /// CHECK-NOT: Add + private static byte $noinline$testIntToByte(int a, int b) { + byte result = 10; + int c = 257; // equal to 1 in byte + int d = 258; // equal to 2 in byte + // Due to `+` operating in ints, we need to do an extra cast. We can optimize away both type + // conversions. + return (byte) (result + (byte) (a < b ? c : d)); + } + + /// CHECK-START: int Main.$noinline$testLongToInt(int, int) select_generator (after) + /// CHECK: <<Const10:i\d+>> IntConstant 10 + /// CHECK: <<Const1:j\d+>> LongConstant 4294967297 + /// CHECK: <<Const2:j\d+>> LongConstant 4294967298 + /// CHECK: <<Sel:j\d+>> Select [<<Const1>>,<<Const2>>,<<Condition:z\d+>>] + /// CHECK: <<Type:i\d+>> TypeConversion [<<Sel>>] + /// CHECK: Add [<<Type>>,<<Const10>>] + + /// CHECK-START: int Main.$noinline$testLongToInt(int, int) constant_folding$after_gvn (after) + /// CHECK: <<Const11:i\d+>> IntConstant 11 + /// CHECK: <<Const12:i\d+>> IntConstant 12 + /// CHECK: Select [<<Const11>>,<<Const12>>,<<Condition:z\d+>>] + + /// CHECK-START: int Main.$noinline$testLongToInt(int, int) constant_folding$after_gvn (after) + /// CHECK-NOT: TypeConversion + /// CHECK-NOT: Add + private static int $noinline$testLongToInt(int a, int b) { + int result = 10; + long c = (1L << 32) + 1L; // Will be 1, when cast to int + long d = (1L << 32) + 2L; // Will be 2, when cast to int + return result + (int) (a < b ? c : d); + } + + private static void assertIntEquals(int expected, int actual) { + if (expected != actual) { + throw new AssertionError("Expected " + expected + " got " + actual); + } + } + + private static void assertLongEquals(long expected, long actual) { + if (expected != actual) { + throw new AssertionError("Expected " + expected + " got " + actual); + } + } + + private static void assertFloatEquals(float expected, float actual) { + if (expected != actual) { + throw new AssertionError("Expected " + expected + " got " + actual); + } + } +} diff --git a/test/567-checker-builder-intrinsics/src/TestSignum.java b/test/567-checker-builder-intrinsics/src/TestSignum.java index ed3c5fe3df..c807743b6f 100644 --- a/test/567-checker-builder-intrinsics/src/TestSignum.java +++ b/test/567-checker-builder-intrinsics/src/TestSignum.java @@ -92,13 +92,11 @@ public class TestSignum { /// CHECK-START: int TestSignum.signBoolean(boolean) select_generator (after) /// CHECK-NOT: Phi - /// CHECK-START: int TestSignum.signBoolean(boolean) instruction_simplifier$before_codegen (after) + /// CHECK-START: int TestSignum.signBoolean(boolean) instruction_simplifier$after_gvn (after) /// CHECK-DAG: <<Arg:z\d+>> ParameterValue - /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0 - /// CHECK-DAG: <<Result:i\d+>> Compare [<<Arg>>,<<Zero>>] - /// CHECK-DAG: Return [<<Result>>] + /// CHECK-DAG: Return [<<Arg>>] - /// CHECK-START: int TestSignum.signBoolean(boolean) instruction_simplifier$before_codegen (after) + /// CHECK-START: int TestSignum.signBoolean(boolean) instruction_simplifier$after_gvn (after) /// CHECK-NOT: Select private static int signBoolean(boolean x) { diff --git a/test/570-checker-select/src/Main.java b/test/570-checker-select/src/Main.java index 0e23b3dc00..57e4db5dbd 100644 --- a/test/570-checker-select/src/Main.java +++ b/test/570-checker-select/src/Main.java @@ -500,7 +500,6 @@ public class Main { /// CHECK-START: float Main.$noinline$FloatGtMatCond_FloatVarVar(float, float, float, float) register (after) /// CHECK: <<Cond:z\d+>> GreaterThanOrEqual /// CHECK-NEXT: <<Sel:f\d+>> Select [{{f\d+}},{{f\d+}},<<Cond>>] - /// CHECK-NEXT: TypeConversion [<<Cond>>] /// CHECK-START-ARM64: float Main.$noinline$FloatGtMatCond_FloatVarVar(float, float, float, float) disassembly (after) /// CHECK: GreaterThanOrEqual diff --git a/test/593-checker-boolean-2-integral-conv/smali/SmaliTests.smali b/test/593-checker-boolean-2-integral-conv/smali/SmaliTests.smali index f3f52a8f11..8e84d054a0 100644 --- a/test/593-checker-boolean-2-integral-conv/smali/SmaliTests.smali +++ b/test/593-checker-boolean-2-integral-conv/smali/SmaliTests.smali @@ -187,8 +187,10 @@ ## CHECK-START: long SmaliTests.booleanToLong(boolean) instruction_simplifier$before_codegen (after) ## CHECK-DAG: <<Arg:z\d+>> ParameterValue -## CHECK-DAG: <<ZToJ:j\d+>> TypeConversion [<<Arg>>] -## CHECK-DAG: Return [<<ZToJ>>] +## CHECK-DAG: <<Zero:j\d+>> LongConstant 0 +## CHECK-DAG: <<One:j\d+>> LongConstant 1 +## CHECK-DAG: <<Sel:j\d+>> Select [<<Zero>>,<<One>>,<<Arg>>] +## CHECK-DAG: Return [<<Sel>>] .method public static booleanToLong(Z)J .registers 3 .param p0, "b" # Z diff --git a/test/646-checker-long-const-to-int/src/Main.java b/test/646-checker-long-const-to-int/src/Main.java index 2133588d75..491565bc17 100644 --- a/test/646-checker-long-const-to-int/src/Main.java +++ b/test/646-checker-long-const-to-int/src/Main.java @@ -16,7 +16,7 @@ public class Main { public static void main(String[] args) { - System.out.println(test()); + System.out.println(test(0L)); } public static long testField = 0; @@ -29,18 +29,18 @@ public class Main { public static long longField6 = 0; public static long longField7 = 0; - /// CHECK-START-ARM: int Main.test() register (after) + /// CHECK-START-ARM: int Main.test(long) register (after) /// CHECK: TypeConversion locations:[#-8690466096623102344]->{{.*}} - public static int test() { + public static int test(long other) { // To avoid constant folding TypeConversion(const), hide the constant in a field. Then, hide - // it even more inside a Select that can only be reduced after LSE+InstructionSelector. We + // it even more inside a Select that can only be reduced after LSE+InstructionSimplifier. We // don't run constant folding after that. testField = 0x8765432112345678L; long value = testField; if (value + 1 == 0x8765432112345679L) { value = testField; } else { - value = 0; + value = other; } // Now, the `value` is in a register because of the store but we need // a constant location to trigger the bug, so load a bunch of other fields. |