diff options
author | 2014-09-22 11:51:51 +0100 | |
---|---|---|
committer | 2014-09-22 11:54:48 +0100 | |
commit | 145f0ca7c7c5f5fd9f5226f2a65e1fd9ba3a4f47 (patch) | |
tree | 775f344295e864e60694c2d43aa7f90a6249422f | |
parent | cff942b1f7ebb82e3d5e0a1334467544eced1575 (diff) |
Fix a bug in the handling of moves in register allocator.
Change-Id: Iaf1f34b0bece4f252290a97c3b73cc06e365985a
-rw-r--r-- | compiler/optimizing/register_allocator.cc | 4 | ||||
-rw-r--r-- | test/408-move-bug/expected.txt | 0 | ||||
-rw-r--r-- | test/408-move-bug/info.txt | 2 | ||||
-rw-r--r-- | test/408-move-bug/src/Main.java | 69 |
4 files changed, 75 insertions, 0 deletions
diff --git a/compiler/optimizing/register_allocator.cc b/compiler/optimizing/register_allocator.cc index 786261121b..9ba75b8da4 100644 --- a/compiler/optimizing/register_allocator.cc +++ b/compiler/optimizing/register_allocator.cc @@ -796,6 +796,10 @@ void RegisterAllocator::InsertParallelMoveAt(size_t position, // This is a parallel move for connecting siblings in a same block. We need to // differentiate it with moves for connecting blocks, and input moves. if (previous->GetLifetimePosition() != position) { + // If the previous instruction of the previous instruction is not a parallel + // move, we have to insert the new parallel move before the input or connecting + // block moves. + at = previous; previous = previous->GetPrevious(); } } diff --git a/test/408-move-bug/expected.txt b/test/408-move-bug/expected.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/408-move-bug/expected.txt diff --git a/test/408-move-bug/info.txt b/test/408-move-bug/info.txt new file mode 100644 index 0000000000..27a3dbc1f5 --- /dev/null +++ b/test/408-move-bug/info.txt @@ -0,0 +1,2 @@ +Regression test for the register allocator in the optimizing +compiler. Input moves where being overridden by sibling moves. diff --git a/test/408-move-bug/src/Main.java b/test/408-move-bug/src/Main.java new file mode 100644 index 0000000000..420298b8c6 --- /dev/null +++ b/test/408-move-bug/src/Main.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2014 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. + */ + +public class Main { + + public static void main(String[] args) { + crash(); + npe(); + } + + static void crash() { + boolean b = baz(); + // Create many objects to starve registers. + Main foo1 = create(); + Main foo2 = create(); + Main foo3 = create(); + Main foo4 = create(); + foo1.otherField = null; + // On X86, we would force b to be in a byte register, which + // would generate moves. This code exposed a bug in the + // register allocator, where an input move was not just before + // the instruction itself, and its destination was overridden + // by another value. + foo1.field = b; + foo2.field = b; + foo3.field = b; + foo4.field = b; + foo1.lastField = b; + } + + // Similar to `crash` but generated an NPE. + static void npe() { + boolean b = baz(); + Main foo1 = create(); + Main foo2 = create(); + Main foo3 = create(); + Main foo4 = create(); + foo1.field = b; + foo2.field = b; + foo3.field = b; + foo4.field = b; + foo1.lastField = b; + } + + static Main create() { + return new Main(); + } + + static boolean baz() { + return false; + } + + boolean field; + Object otherField; + boolean lastField; +} |