summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Georgia Kouveli <georgia.kouveli@linaro.org> 2019-01-31 16:12:16 +0000
committer Treehugger Robot <treehugger-gerrit@google.com> 2019-08-13 00:43:36 +0000
commitbac080b0beec961671a7753c88780d8bf700fa40 (patch)
tree101965980dec12c1355077dd9699822211b265e4
parent44b977d9e2974cdbd8ef11f35919166dada92bda (diff)
Loop vectorizer should not remove instructions that can throw
Instructions that are not used outside of the inner loop were inadvertently being removed. Make sure this does not happen. Original author: Georgia Kouveli <georgia.kouveli@linaro.org> Committed by: David Horstmann <david.horstmann@linaro.org> Test: 1961-checker-loop-vectorizer Test: test-art-target Change-Id: I3af9e861e75669457e5925dd1d655db784a55287
-rw-r--r--compiler/optimizing/loop_optimization.cc7
-rw-r--r--test/1961-checker-loop-vectorizer/expected.txt3
-rw-r--r--test/1961-checker-loop-vectorizer/info.txt1
-rw-r--r--test/1961-checker-loop-vectorizer/src/Main.java83
4 files changed, 93 insertions, 1 deletions
diff --git a/compiler/optimizing/loop_optimization.cc b/compiler/optimizing/loop_optimization.cc
index 3e1c42c8d9..9c4e9d25f7 100644
--- a/compiler/optimizing/loop_optimization.cc
+++ b/compiler/optimizing/loop_optimization.cc
@@ -1283,6 +1283,10 @@ bool HLoopOptimization::VectorizeDef(LoopNode* node,
// (3) unit stride index,
// (4) vectorizable right-hand-side value.
uint64_t restrictions = kNone;
+ // Don't accept expressions that can throw.
+ if (instruction->CanThrow()) {
+ return false;
+ }
if (instruction->IsArraySet()) {
DataType::Type type = instruction->AsArraySet()->GetComponentType();
HInstruction* base = instruction->InputAt(0);
@@ -1334,7 +1338,8 @@ bool HLoopOptimization::VectorizeDef(LoopNode* node,
}
// Otherwise accept only expressions with no effects outside the immediate loop-body.
// Note that actual uses are inspected during right-hand-side tree traversal.
- return !IsUsedOutsideLoop(node->loop_info, instruction) && !instruction->DoesAnyWrite();
+ return !IsUsedOutsideLoop(node->loop_info, instruction)
+ && !instruction->DoesAnyWrite();
}
bool HLoopOptimization::VectorizeUse(LoopNode* node,
diff --git a/test/1961-checker-loop-vectorizer/expected.txt b/test/1961-checker-loop-vectorizer/expected.txt
new file mode 100644
index 0000000000..e25e266500
--- /dev/null
+++ b/test/1961-checker-loop-vectorizer/expected.txt
@@ -0,0 +1,3 @@
+DivZeroCheck
+CheckCast
+BoundsCheck
diff --git a/test/1961-checker-loop-vectorizer/info.txt b/test/1961-checker-loop-vectorizer/info.txt
new file mode 100644
index 0000000000..ab768d9b3e
--- /dev/null
+++ b/test/1961-checker-loop-vectorizer/info.txt
@@ -0,0 +1 @@
+Test loop vectorizer corner cases.
diff --git a/test/1961-checker-loop-vectorizer/src/Main.java b/test/1961-checker-loop-vectorizer/src/Main.java
new file mode 100644
index 0000000000..4d521a1a58
--- /dev/null
+++ b/test/1961-checker-loop-vectorizer/src/Main.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+/**
+ * Test corner cases for loop vectorizer.
+ */
+public class Main {
+ /// CHECK-START: void Main.$noinline$testDivZeroCheck() loop_optimization (before)
+ /// CHECK: DivZeroCheck
+ /// CHECK-NOT: DivZeroCheck
+ /// CHECK-START: void Main.$noinline$testDivZeroCheck() loop_optimization (after)
+ /// CHECK: DivZeroCheck
+ public static void $noinline$testDivZeroCheck() {
+ int[] a = new int[10];
+ for (int i = 0; i < a.length; ++i) {
+ int x = 42 / 0; // unused but throwing
+ a[i] = 42;
+ }
+ }
+
+ static class Base {}
+ static class Foo extends Base {}
+ static class Bar extends Base {}
+
+ /// CHECK-START: void Main.$noinline$testCheckCast() loop_optimization (before)
+ /// CHECK: CheckCast
+ /// CHECK-NOT: CheckCast
+ /// CHECK-START: void Main.$noinline$testCheckCast() loop_optimization (after)
+ /// CHECK: CheckCast
+ public static void $noinline$testCheckCast() {
+ Base base = new Foo();
+ int[] a = new int[10];
+ for (int i = 0; i < a.length; ++i) {
+ Bar bar = (Bar) base; // unused but throwing
+ a[i] = 42;
+ }
+ }
+
+ /// CHECK-START: void Main.$noinline$testBoundsCheck() loop_optimization (before)
+ /// CHECK: BoundsCheck
+ /// CHECK-NOT: BoundsCheck
+ /// CHECK-START: void Main.$noinline$testBoundsCheck() loop_optimization (after)
+ /// CHECK: BoundsCheck
+ public static void $noinline$testBoundsCheck() {
+ int[] a = new int[10];
+ for (int i = 0; i < a.length; ++i) {
+ int x = a[11]; // unused but throwing
+ a[i] = 42;
+ }
+ }
+
+ public static void main(String[] args) {
+ // We must not optimize any of the exceptions away.
+ try {
+ $noinline$testDivZeroCheck();
+ } catch (java.lang.ArithmeticException e) {
+ System.out.println("DivZeroCheck");
+ }
+ try {
+ $noinline$testCheckCast();
+ } catch (java.lang.ClassCastException e) {
+ System.out.println("CheckCast");
+ }
+ try {
+ $noinline$testBoundsCheck();
+ } catch (java.lang.ArrayIndexOutOfBoundsException e) {
+ System.out.println("BoundsCheck");
+ }
+ }
+}