diff options
author | 2021-10-25 04:58:23 +0000 | |
---|---|---|
committer | 2021-10-25 08:11:22 +0000 | |
commit | 050686452146e1f5d31aed560c682d992c376fed (patch) | |
tree | 951ffcdd0c82be6fe976ca06852dbcde84058754 | |
parent | 884c147e93aab632ca13d2f0ea28110e8f8752a7 (diff) |
Revert "ART: Redundant AND operation removal optimization"
This reverts commit c498a1de3de1b36baebfd7b69b0af7fb4947d58e.
DroidMonitor-triggered revert due to breakage https://android-build.googleplex.com/builds/tests/view?invocationId=I97700009991646450&testResultId=TR34427775909599300&tab=results, bug b/203783068.
Bug: 203783068
Change-Id: Ia7adec8217839b2b20c5409b9c87d3f920d798c2
-rw-r--r-- | compiler/optimizing/instruction_simplifier.cc | 59 | ||||
-rw-r--r-- | test/458-checker-instruct-simplification/src/Main.java | 255 |
2 files changed, 1 insertions, 313 deletions
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc index 6ff71f2d3e..a75639f3c5 100644 --- a/compiler/optimizing/instruction_simplifier.cc +++ b/compiler/optimizing/instruction_simplifier.cc @@ -24,7 +24,6 @@ #include "intrinsics.h" #include "intrinsics_utils.h" #include "mirror/class-inl.h" -#include "optimizing/data_type.h" #include "optimizing/nodes.h" #include "scoped_thread_state_change-inl.h" #include "sharpening.h" @@ -113,6 +112,7 @@ class InstructionSimplifierVisitor : public HGraphDelegateVisitor { void VisitDeoptimize(HDeoptimize* deoptimize) override; void VisitVecMul(HVecMul* instruction) override; void VisitPredicatedInstanceFieldGet(HPredicatedInstanceFieldGet* instruction) override; + void SimplifySystemArrayCopy(HInvoke* invoke); void SimplifyStringEquals(HInvoke* invoke); void SimplifyFP2Int(HInvoke* invoke); @@ -1185,33 +1185,6 @@ static bool IsTypeConversionLossless(DataType::Type input_type, DataType::Type r !(result_type == DataType::Type::kInt64 && input_type == DataType::Type::kFloat32); } -static bool CanRemoveRedundantAnd(HConstant* and_right, - HConstant* shr_right, - DataType::Type result_type) { - int64_t and_cst = Int64FromConstant(and_right); - int64_t shr_cst = Int64FromConstant(shr_right); - - // In the following sequence A is the input value, D is the result: - // B := A & x - // C := B >> r - // D := TypeConv(n-bit type) C - - // The value of D is entirely dependent on the bits [n-1:0] of C, which in turn are dependent - // on bits [r+n-1:r] of B. - // Therefore, if the AND does not change bits [r+n-1:r] of A then it will not affect D. - // This can be checked by ensuring that bits [r+n-1:r] of the AND Constant are 1. - - // For example: return (byte) ((value & 0xff00) >> 8) - // return (byte) ((value & 0xff000000) >> 31) - - // The mask sets bits [r+n-1:r] to 1, and all others to 0. - int64_t mask = DataType::MaxValueOfIntegralType(DataType::ToUnsigned(result_type)) << shr_cst; - - // If the result of a bitwise AND between the mask and the AND constant is the original mask, then - // the AND does not change bits [r+n-1:r], meaning that it is redundant and can be removed. - return ((and_cst & mask) == mask); -} - static inline bool TryReplaceFieldOrArrayGetType(HInstruction* maybe_get, DataType::Type new_type) { if (maybe_get->IsInstanceFieldGet()) { maybe_get->AsInstanceFieldGet()->SetType(new_type); @@ -1332,36 +1305,6 @@ void InstructionSimplifierVisitor::VisitTypeConversion(HTypeConversion* instruct return; } } - } else if (input->IsShr() && DataType::IsIntegralType(result_type) && - // Optimization only applies to lossy Type Conversions. - !IsTypeConversionLossless(input_type, result_type)) { - DCHECK(DataType::IsIntegralType(input_type)); - HShr* shr_op = input->AsShr(); - HConstant* shr_right = shr_op->GetConstantRight(); - HInstruction* shr_left = shr_op->GetLeastConstantLeft(); - if (shr_right != nullptr && shr_left->IsAnd()) { - // Optimization needs AND -> SHR -> TypeConversion pattern. - HAnd* and_op = shr_left->AsAnd(); - HConstant* and_right = and_op->GetConstantRight(); - HInstruction* and_left = and_op->GetLeastConstantLeft(); - DataType::Type and_left_type = and_left->GetType(); - if (!DataType::IsUnsignedType(and_left_type) && - !DataType::IsUnsignedType(result_type) && - !DataType::IsUnsignedType(and_right->GetType()) && - (DataType::Size(and_left_type) < 8) && - (DataType::Size(result_type) == 1)) { - // TODO: Support Unsigned Types. - // TODO: Support Long Types. - // TODO: Support result types other than byte. - if (and_right != nullptr && and_op->HasOnlyOneNonEnvironmentUse() && - CanRemoveRedundantAnd(and_right, shr_right, result_type)) { - and_op->ReplaceWith(and_left); - and_op->GetBlock()->RemoveInstruction(and_op); - RecordSimplification(); - return; - } - } - } } else if (input->IsAnd() && DataType::IsIntegralType(result_type)) { DCHECK(DataType::IsIntegralType(input_type)); HAnd* input_and = input->AsAnd(); diff --git a/test/458-checker-instruct-simplification/src/Main.java b/test/458-checker-instruct-simplification/src/Main.java index 557f126d01..5ffb75feb9 100644 --- a/test/458-checker-instruct-simplification/src/Main.java +++ b/test/458-checker-instruct-simplification/src/Main.java @@ -2529,219 +2529,6 @@ public class Main { return "x".indexOf(ch, fromIndex); // Not simplified. } - /// CHECK-START: byte Main.$noinline$redundantAndNotRedundant(int) instruction_simplifier (before) - /// CHECK-DAG: And - - /// CHECK-START: byte Main.$noinline$redundantAndNotRedundant(int) instruction_simplifier (after) - /// CHECK-DAG: And - public static byte $noinline$redundantAndNotRedundant(int value) { - // Here the AND is not redundant. This test checks that it is not removed. - // 0xf500 = 1111 0101 0000 0000 - bits [11:8] of value will be changed by - // the AND with 0101. These bits are kept following the SHR and TypeConversion. - return (byte) ((value & 0xf500) >> 8); - } - - /// CHECK-START: byte Main.$noinline$redundantAndOtherUse(int) instruction_simplifier (before) - /// CHECK-DAG: And - - /// CHECK-START: byte Main.$noinline$redundantAndOtherUse(int) instruction_simplifier (after) - /// CHECK-DAG: And - public static byte $noinline$redundantAndOtherUse(int value){ - int v1 = value & 0xff00; - // Above AND is redundant in the context of calculating v2. - byte v2 = (byte) (v1 >> 8); - byte v3 = (byte) (v1 - 0x6eef); - // Use of AND result (v1) in calculating v3 means AND must not be removed. - return (byte) (v2 - v3); - } - - /// CHECK-START: byte Main.$noinline$redundantAndShortToByteShift2(short) instruction_simplifier (before) - /// CHECK-DAG: And - - /// CHECK-START: byte Main.$noinline$redundantAndShortToByteShift2(short) instruction_simplifier (after) - /// CHECK-NOT: And - public static byte $noinline$redundantAndShortToByteShift2(short value) { - // & 0xfff only changes bits higher than bit number 12 inclusive. - // These bits are discarded during Type Conversion to byte. - // Therefore AND is redundant and should be removed. - return (byte) ((value & 0xfff) >> 2); - } - - /// CHECK-START: byte Main.$noinline$redundantAndShortToByteShift5(short) instruction_simplifier (before) - /// CHECK-DAG: And - - /// CHECK-START: byte Main.$noinline$redundantAndShortToByteShift5(short) instruction_simplifier (after) - /// CHECK-NOT: And - public static byte $noinline$redundantAndShortToByteShift5(short value) { - // & 0xffe0 changes bits [4:0] and bits higher than 16 inclusive. - // These bits are discarded by the right shift and type conversion. - // Therefore AND is redundant and should be removed. - return (byte) ((value & 0xffe0) >> 5); - } - - /// CHECK-START: byte Main.$noinline$redundantAndShortToByteShift8(short) instruction_simplifier (before) - /// CHECK-DAG: And - - /// CHECK-START: byte Main.$noinline$redundantAndShortToByteShift8(short) instruction_simplifier (after) - /// CHECK-NOT: And - public static byte $noinline$redundantAndShortToByteShift8(short value) { - return (byte) ((value & 0xff00) >> 8); - } - - /// CHECK-START: byte Main.$noinline$redundantAndShortToByteShift9NotRedundant(short) instruction_simplifier (before) - /// CHECK-DAG: And - - /// CHECK-START: byte Main.$noinline$redundantAndShortToByteShift9NotRedundant(short) instruction_simplifier (after) - /// CHECK-DAG: And - public static byte $noinline$redundantAndShortToByteShift9NotRedundant(short value) { - // Byte and Short operands for bitwise operations (e.g. &,>>) are promoted to Int32 prior to operation. - // Negative operands will be sign extended accordingly: (short: 0xff45) --> (int: 0xffffff45) - // & fe00 will clear bits [31:16]. For negative 'value', this will clear sign bits. - // Without the AND, the right shift will move the sign extended ones into the result instead of zeros. - // Therefore AND is not redundant and should not be removed. - return (byte) ((value & 0xfe00) >> 9); - } - - /// CHECK-START: byte Main.$noinline$redundantAndShortToByteShift10NotRedundant(short) instruction_simplifier (before) - /// CHECK-DAG: And - - /// CHECK-START: byte Main.$noinline$redundantAndShortToByteShift10NotRedundant(short) instruction_simplifier (after) - /// CHECK-DAG: And - public static byte $noinline$redundantAndShortToByteShift10NotRedundant(short value) { - return (byte) ((value & 0x1ffff) >> 10); - } - - /// CHECK-START: byte Main.$noinline$redundantAndShortToByteShift12(short) instruction_simplifier (before) - /// CHECK-DAG: And - - /// CHECK-START: byte Main.$noinline$redundantAndShortToByteShift12(short) instruction_simplifier (after) - /// CHECK-NOT: And - public static byte $noinline$redundantAndShortToByteShift12(short value) { - // & fff00 preserves bits [19:8] and clears all others. - // Here the AND preserves enough ones; such that zeros are moved into the result. - // Therefore AND is redundant and can be removed. - return (byte) ((value & 0xfff00) >> 12); - } - - /// CHECK-START: byte Main.$noinline$redundantAndShortToByteShift15(short) instruction_simplifier (before) - /// CHECK-DAG: And - - /// CHECK-START: byte Main.$noinline$redundantAndShortToByteShift15(short) instruction_simplifier (after) - /// CHECK-NOT: And - public static byte $noinline$redundantAndShortToByteShift15(short value) { - return (byte) ((value & 0xffff00) >> 15); - } - - /// CHECK-START: byte Main.$noinline$redundantAndShortToByteShift16(short) instruction_simplifier (before) - /// CHECK-DAG: And - - /// CHECK-START: byte Main.$noinline$redundantAndShortToByteShift16(short) instruction_simplifier (after) - /// CHECK-NOT: And - public static byte $noinline$redundantAndShortToByteShift16(short value) { - return (byte) ((value & 0xf0ffff00) >> 16); - } - - /// CHECK-START: byte Main.$noinline$redundantAndIntToByteShift2(int) instruction_simplifier (before) - /// CHECK-DAG: And - - /// CHECK-START: byte Main.$noinline$redundantAndIntToByteShift2(int) instruction_simplifier (after) - /// CHECK-NOT: And - public static byte $noinline$redundantAndIntToByteShift2(int value) { - return (byte) ((value & 0xfff) >> 2); - } - - /// CHECK-START: byte Main.$noinline$redundantAndIntToByteShift5(int) instruction_simplifier (before) - /// CHECK-DAG: And - - /// CHECK-START: byte Main.$noinline$redundantAndIntToByteShift5(int) instruction_simplifier (after) - /// CHECK-NOT: And - public static byte $noinline$redundantAndIntToByteShift5(int value) { - return (byte) ((value & 0xffe0) >> 5); - } - - /// CHECK-START: byte Main.$noinline$redundantAndIntToByteShift8(int) instruction_simplifier (before) - /// CHECK-DAG: And - - /// CHECK-START: byte Main.$noinline$redundantAndIntToByteShift8(int) instruction_simplifier (after) - /// CHECK-NOT: And - public static byte $noinline$redundantAndIntToByteShift8(int value) { - return (byte) ((value & 0xffffff00) >> 8); - } - - /// CHECK-START: byte Main.$noinline$redundantAndIntToByteShift9(int) instruction_simplifier (before) - /// CHECK-DAG: And - - /// CHECK-START: byte Main.$noinline$redundantAndIntToByteShift9(int) instruction_simplifier (after) - /// CHECK-NOT: And - public static byte $noinline$redundantAndIntToByteShift9(int value) { - return (byte) ((value & 0xf001fe00) >> 9); - } - - /// CHECK-START: byte Main.$noinline$redundantAndIntToByteShift16(int) instruction_simplifier (before) - /// CHECK-DAG: And - - /// CHECK-START: byte Main.$noinline$redundantAndIntToByteShift16(int) instruction_simplifier (after) - /// CHECK-NOT: And - public static byte $noinline$redundantAndIntToByteShift16(int value) { - return (byte) ((value & 0xf0ff0000) >> 16); - } - - /// CHECK-START: byte Main.$noinline$redundantAndIntToByteShift20(int) instruction_simplifier (before) - /// CHECK-DAG: And - - /// CHECK-START: byte Main.$noinline$redundantAndIntToByteShift20(int) instruction_simplifier (after) - /// CHECK-NOT: And - public static byte $noinline$redundantAndIntToByteShift20(int value) { - return (byte) ((value & 0xfff00000) >> 20); - } - - /// CHECK-START: byte Main.$noinline$redundantAndIntToByteShift25(int) instruction_simplifier (before) - /// CHECK-DAG: And - - /// CHECK-START: byte Main.$noinline$redundantAndIntToByteShift25(int) instruction_simplifier (after) - /// CHECK-NOT: And - public static byte $noinline$redundantAndIntToByteShift25(int value) { - return (byte) ((value & 0xfe000000) >> 25); - } - - /// CHECK-START: byte Main.$noinline$redundantAndIntToByteShift24(int) instruction_simplifier (before) - /// CHECK-DAG: And - - /// CHECK-START: byte Main.$noinline$redundantAndIntToByteShift24(int) instruction_simplifier (after) - /// CHECK-NOT: And - public static byte $noinline$redundantAndIntToByteShift24(int value) { - return (byte) ((value & 0xff000000) >> 24); - } - - /// CHECK-START: byte Main.$noinline$redundantAndIntToByteShift31(int) instruction_simplifier (before) - /// CHECK-DAG: And - - /// CHECK-START: byte Main.$noinline$redundantAndIntToByteShift31(int) instruction_simplifier (after) - /// CHECK-NOT: And - public static byte $noinline$redundantAndIntToByteShift31(int value) { - return (byte) ((value & 0xff000000) >> 31); - } - - /// CHECK-START: byte Main.$noinline$redundantAndShortToByteShortAndConstant(short) instruction_simplifier (before) - /// CHECK-DAG: And - - /// CHECK-START: byte Main.$noinline$redundantAndShortToByteShortAndConstant(short) instruction_simplifier (after) - /// CHECK-NOT: And - public static byte $noinline$redundantAndShortToByteShortAndConstant(short value) { - short and_constant = (short) 0xff00; - return (byte) ((value & and_constant) >> 16); - } - - /// CHECK-START: byte Main.$noinline$redundantAndIntToByteShortAndConstant(int) instruction_simplifier (before) - /// CHECK-DAG: And - - /// CHECK-START: byte Main.$noinline$redundantAndIntToByteShortAndConstant(int) instruction_simplifier (after) - /// CHECK-NOT: And - public static byte $noinline$redundantAndIntToByteShortAndConstant(int value) { - short and_constant = (short) 0xff00; - return (byte) ((value & and_constant) >> 16); - } - public static void main(String[] args) throws Exception { Class smaliTests2 = Class.forName("SmaliTests2"); Method $noinline$XorAllOnes = smaliTests2.getMethod("$noinline$XorAllOnes", int.class); @@ -3006,48 +2793,6 @@ public class Main { assertIntEquals(0, $noinline$singleCharStringIndexOfAfter('x', -1)); assertIntEquals(-1, $noinline$singleCharStringIndexOfAfter('x', 1)); assertIntEquals(-1, $noinline$singleCharStringIndexOfAfter('Z', -1)); - - assertIntEquals(0x65,$noinline$redundantAndNotRedundant(0x7fff6f45)); - assertIntEquals(0x5e,$noinline$redundantAndOtherUse(0x7fff6f45)); - - assertIntEquals(0x79, $noinline$redundantAndShortToByteShift2((short) 0x6de7)); - assertIntEquals(0x79, $noinline$redundantAndShortToByteShift2((short) 0xfde7)); - assertIntEquals(0x7a, $noinline$redundantAndShortToByteShift5((short) 0x6f45)); - assertIntEquals(-6, $noinline$redundantAndShortToByteShift5((short) 0xff45)); - assertIntEquals(0x6f, $noinline$redundantAndShortToByteShift8((short) 0x6f45)); - assertIntEquals(-1, $noinline$redundantAndShortToByteShift8((short) 0xff45)); - assertIntEquals(0x37, $noinline$redundantAndShortToByteShift9NotRedundant((short) 0x6f45)); - assertIntEquals(127, $noinline$redundantAndShortToByteShift9NotRedundant((short) 0xff45)); - assertIntEquals(127, $noinline$redundantAndShortToByteShift10NotRedundant((short) 0xffff)); - assertIntEquals(6, $noinline$redundantAndShortToByteShift12((short) 0x6f45)); - assertIntEquals(-1, $noinline$redundantAndShortToByteShift12((short) 0xff45)); - assertIntEquals(0, $noinline$redundantAndShortToByteShift15((short) 0x6f45)); - assertIntEquals(-1, $noinline$redundantAndShortToByteShift15((short) 0xff45)); - assertIntEquals(0, $noinline$redundantAndShortToByteShift16((short) 0x6f45)); - assertIntEquals(-1, $noinline$redundantAndShortToByteShift16((short) 0xff45)); - assertIntEquals(0, $noinline$redundantAndShortToByteShortAndConstant((short) 0x6f45)); - assertIntEquals(-1, $noinline$redundantAndShortToByteShortAndConstant((short) 0xff45)); - - assertIntEquals(0x79, $noinline$redundantAndIntToByteShift2(0x7fff6de7)); - assertIntEquals(0x79, $noinline$redundantAndIntToByteShift2(0xfffffde7)); - assertIntEquals(0x7a, $noinline$redundantAndIntToByteShift5(0x7fff6f45)); - assertIntEquals(-6, $noinline$redundantAndIntToByteShift5(0xffffff45)); - assertIntEquals(0x6f, $noinline$redundantAndIntToByteShift8(0x7fff6f45)); - assertIntEquals(-1, $noinline$redundantAndIntToByteShift8(0xffffff45)); - assertIntEquals(-73, $noinline$redundantAndIntToByteShift9(0x7fff6f45)); - assertIntEquals(-1, $noinline$redundantAndIntToByteShift9(0xffffff45)); - assertIntEquals(0x6f, $noinline$redundantAndIntToByteShift16(0x7f6fffff)); - assertIntEquals(0x6f, $noinline$redundantAndIntToByteShift16(0xff6fff45)); - assertIntEquals(0x6f, $noinline$redundantAndIntToByteShift20(0x76ffffff)); - assertIntEquals(0x6f, $noinline$redundantAndIntToByteShift20(0xf6ffff45)); - assertIntEquals(0x7f, $noinline$redundantAndIntToByteShift24(0x7fffffff)); - assertIntEquals(-1, $noinline$redundantAndIntToByteShift24(0xffffff45)); - assertIntEquals(0x3f, $noinline$redundantAndIntToByteShift25(0x7fffffff)); - assertIntEquals(-1, $noinline$redundantAndIntToByteShift25(0xffffff45)); - assertIntEquals(0, $noinline$redundantAndIntToByteShift31(0x7fffffff)); - assertIntEquals(-1, $noinline$redundantAndIntToByteShift31(0xffffff45)); - assertIntEquals(-1, $noinline$redundantAndIntToByteShortAndConstant(0x7fffff45)); - assertIntEquals(-1, $noinline$redundantAndIntToByteShortAndConstant(0xffffff45)); } private static boolean $inline$true() { return true; } |