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
diff --git a/compiler/optimizing/loop_optimization.cc b/compiler/optimizing/loop_optimization.cc
index 3e1c42c..9c4e9d2 100644
--- a/compiler/optimizing/loop_optimization.cc
+++ b/compiler/optimizing/loop_optimization.cc
@@ -1283,6 +1283,10 @@
// (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 @@
}
// 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 0000000..e25e266
--- /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 0000000..ab768d9
--- /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 0000000..4d521a1
--- /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");
+ }
+ }
+}