summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/optimizing/graph_checker_test.cc1
-rw-r--r--compiler/optimizing/instruction_simplifier.cc18
-rw-r--r--test/137-cfi/cfi.cc1
-rw-r--r--test/137-cfi/src/Main.java12
-rw-r--r--test/458-checker-instruction-simplification/src/Main.java70
-rw-r--r--test/572-checker-array-get-regression/src/Main.java2
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