diff options
author | 2019-01-31 16:12:16 +0000 | |
---|---|---|
committer | 2019-08-13 00:43:36 +0000 | |
commit | bac080b0beec961671a7753c88780d8bf700fa40 (patch) | |
tree | 101965980dec12c1355077dd9699822211b265e4 | |
parent | 44b977d9e2974cdbd8ef11f35919166dada92bda (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.cc | 7 | ||||
-rw-r--r-- | test/1961-checker-loop-vectorizer/expected.txt | 3 | ||||
-rw-r--r-- | test/1961-checker-loop-vectorizer/info.txt | 1 | ||||
-rw-r--r-- | test/1961-checker-loop-vectorizer/src/Main.java | 83 |
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"); + } + } +} |