diff options
| -rw-r--r-- | compiler/optimizing/graph_checker_test.cc | 1 | ||||
| -rw-r--r-- | compiler/optimizing/instruction_simplifier.cc | 18 | ||||
| -rw-r--r-- | test/137-cfi/cfi.cc | 1 | ||||
| -rw-r--r-- | test/137-cfi/src/Main.java | 12 | ||||
| -rw-r--r-- | test/458-checker-instruction-simplification/src/Main.java | 70 | ||||
| -rw-r--r-- | test/572-checker-array-get-regression/src/Main.java | 2 |
6 files changed, 97 insertions, 7 deletions
diff --git a/compiler/optimizing/graph_checker_test.cc b/compiler/optimizing/graph_checker_test.cc index 659141fbf4..2b8231942b 100644 --- a/compiler/optimizing/graph_checker_test.cc +++ b/compiler/optimizing/graph_checker_test.cc @@ -38,6 +38,7 @@ HGraph* CreateSimpleCFG(ArenaAllocator* allocator) { graph->AddBlock(exit_block); graph->SetExitBlock(exit_block); entry_block->AddSuccessor(exit_block); + graph->BuildDominatorTree(); return graph; } diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc index 98f8009846..a48d06f3d0 100644 --- a/compiler/optimizing/instruction_simplifier.cc +++ b/compiler/optimizing/instruction_simplifier.cc @@ -830,6 +830,24 @@ void InstructionSimplifierVisitor::VisitTypeConversion(HTypeConversion* instruct return; } } + } else if (input->IsAnd() && + Primitive::IsIntegralType(result_type) && + input->HasOnlyOneNonEnvironmentUse()) { + DCHECK(Primitive::IsIntegralType(input_type)); + HAnd* input_and = input->AsAnd(); + HConstant* constant = input_and->GetConstantRight(); + if (constant != nullptr) { + int64_t value = Int64FromConstant(constant); + DCHECK_NE(value, -1); // "& -1" would have been optimized away in VisitAnd(). + size_t trailing_ones = CTZ(~static_cast<uint64_t>(value)); + if (trailing_ones >= kBitsPerByte * Primitive::ComponentSize(result_type)) { + // The `HAnd` is useless, for example in `(byte) (x & 0xff)`, get rid of it. + input_and->ReplaceWith(input_and->GetLeastConstantLeft()); + input_and->GetBlock()->RemoveInstruction(input_and); + RecordSimplification(); + return; + } + } } } diff --git a/test/137-cfi/cfi.cc b/test/137-cfi/cfi.cc index 87656bcf0e..45251b8f7d 100644 --- a/test/137-cfi/cfi.cc +++ b/test/137-cfi/cfi.cc @@ -53,6 +53,7 @@ static void CauseSegfault() { extern "C" JNIEXPORT jboolean JNICALL Java_Main_sleep(JNIEnv*, jobject, jint, jboolean, jdouble) { // Keep pausing. + printf("Going to sleep\n"); for (;;) { pause(); } diff --git a/test/137-cfi/src/Main.java b/test/137-cfi/src/Main.java index 77553380c8..d60a4ebba8 100644 --- a/test/137-cfi/src/Main.java +++ b/test/137-cfi/src/Main.java @@ -16,10 +16,7 @@ import java.io.BufferedReader; import java.io.FileReader; -import java.io.InputStream; -import java.io.OutputStream; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; +import java.io.InputStreamReader; import java.util.Arrays; import java.util.Comparator; @@ -98,9 +95,12 @@ public class Main implements Comparator<Main> { throw new RuntimeException("Couldn't parse process"); } - // Wait a bit, so the forked process has time to run until its sleep phase. + // Wait until the forked process had time to run until its sleep phase. try { - Thread.sleep(5000); + InputStreamReader stdout = new InputStreamReader(p.getInputStream(), "UTF-8"); + BufferedReader lineReader = new BufferedReader(stdout); + while (!lineReader.readLine().contains("Going to sleep")) { + } } catch (Exception e) { throw new RuntimeException(e); } diff --git a/test/458-checker-instruction-simplification/src/Main.java b/test/458-checker-instruction-simplification/src/Main.java index 1b710d8142..8d6bb653f4 100644 --- a/test/458-checker-instruction-simplification/src/Main.java +++ b/test/458-checker-instruction-simplification/src/Main.java @@ -1711,6 +1711,65 @@ public class Main { return "c=" + ((int) c) + ", b=" + ((int) b); // implicit conversions. } + /// CHECK-START: byte Main.longAnd0xffToByte(long) instruction_simplifier (before) + /// CHECK-DAG: <<Arg:j\d+>> ParameterValue + /// CHECK-DAG: <<Mask:j\d+>> LongConstant 255 + /// CHECK-DAG: <<And:j\d+>> And [<<Mask>>,<<Arg>>] + /// CHECK-DAG: <<Int:i\d+>> TypeConversion [<<And>>] + /// CHECK-DAG: <<Byte:b\d+>> TypeConversion [<<Int>>] + /// CHECK-DAG: Return [<<Byte>>] + + /// CHECK-START: byte Main.longAnd0xffToByte(long) instruction_simplifier (after) + /// CHECK-DAG: <<Arg:j\d+>> ParameterValue + /// CHECK-DAG: <<Byte:b\d+>> TypeConversion [<<Arg>>] + /// CHECK-DAG: Return [<<Byte>>] + + /// CHECK-START: byte Main.longAnd0xffToByte(long) instruction_simplifier (after) + /// CHECK-NOT: And + + public static byte longAnd0xffToByte(long value) { + return (byte) (value & 0xff); + } + + /// CHECK-START: char Main.intAnd0x1ffffToChar(int) instruction_simplifier (before) + /// CHECK-DAG: <<Arg:i\d+>> ParameterValue + /// CHECK-DAG: <<Mask:i\d+>> IntConstant 131071 + /// CHECK-DAG: <<And:i\d+>> And [<<Mask>>,<<Arg>>] + /// CHECK-DAG: <<Char:c\d+>> TypeConversion [<<And>>] + /// CHECK-DAG: Return [<<Char>>] + + /// CHECK-START: char Main.intAnd0x1ffffToChar(int) instruction_simplifier (after) + /// CHECK-DAG: <<Arg:i\d+>> ParameterValue + /// CHECK-DAG: <<Char:c\d+>> TypeConversion [<<Arg>>] + /// CHECK-DAG: Return [<<Char>>] + + /// CHECK-START: char Main.intAnd0x1ffffToChar(int) instruction_simplifier (after) + /// CHECK-NOT: And + + public static char intAnd0x1ffffToChar(int value) { + // Keeping all significant bits and one more. + return (char) (value & 0x1ffff); + } + + /// CHECK-START: short Main.intAnd0x17fffToShort(int) instruction_simplifier (before) + /// CHECK-DAG: <<Arg:i\d+>> ParameterValue + /// CHECK-DAG: <<Mask:i\d+>> IntConstant 98303 + /// CHECK-DAG: <<And:i\d+>> And [<<Mask>>,<<Arg>>] + /// CHECK-DAG: <<Short:s\d+>> TypeConversion [<<And>>] + /// CHECK-DAG: Return [<<Short>>] + + /// CHECK-START: short Main.intAnd0x17fffToShort(int) instruction_simplifier (after) + /// CHECK-DAG: <<Arg:i\d+>> ParameterValue + /// CHECK-DAG: <<Mask:i\d+>> IntConstant 98303 + /// CHECK-DAG: <<And:i\d+>> And [<<Mask>>,<<Arg>>] + /// CHECK-DAG: <<Short:s\d+>> TypeConversion [<<And>>] + /// CHECK-DAG: Return [<<Short>>] + + public static short intAnd0x17fffToShort(int value) { + // No simplification: clearing a significant bit. + return (short) (value & 0x17fff); + } + public static void main(String[] args) { int arg = 123456; @@ -1836,6 +1895,17 @@ public class Main { assertStringEquals(shortToCharToBytePrint((short) 1025), "c=1025, b=1"); assertStringEquals(shortToCharToBytePrint((short) 1023), "c=1023, b=-1"); assertStringEquals(shortToCharToBytePrint((short) -1), "c=65535, b=-1"); + + assertIntEquals(longAnd0xffToByte(0x1234432112344321L), 0x21); + assertIntEquals(longAnd0xffToByte(Long.MIN_VALUE), 0); + assertIntEquals(longAnd0xffToByte(Long.MAX_VALUE), -1); + assertIntEquals(intAnd0x1ffffToChar(0x43211234), 0x1234); + assertIntEquals(intAnd0x1ffffToChar(Integer.MIN_VALUE), 0); + assertIntEquals(intAnd0x1ffffToChar(Integer.MAX_VALUE), Character.MAX_VALUE); + assertIntEquals(intAnd0x17fffToShort(0x87654321), 0x4321); + assertIntEquals(intAnd0x17fffToShort(0x88888888), 0x0888); + assertIntEquals(intAnd0x17fffToShort(Integer.MIN_VALUE), 0); + assertIntEquals(intAnd0x17fffToShort(Integer.MAX_VALUE), Short.MAX_VALUE); } public static boolean booleanField; diff --git a/test/572-checker-array-get-regression/src/Main.java b/test/572-checker-array-get-regression/src/Main.java index a9bf326427..b55be706f4 100644 --- a/test/572-checker-array-get-regression/src/Main.java +++ b/test/572-checker-array-get-regression/src/Main.java @@ -20,7 +20,7 @@ public class Main { System.out.println(test().intValue()); } - /// CHECK-START: java.lang.Integer Main.test() ssa_builder (after) + /// CHECK-START: java.lang.Integer Main.test() builder (after) /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod /// CHECK-DAG: <<Const2P19:i\d+>> IntConstant 524288 /// CHECK-DAG: <<ConstM1:i\d+>> IntConstant -1 |