From 06b66d05a6251d91b5e2516f579bfff5fa49191c Mon Sep 17 00:00:00 2001 From: Roland Levillain Date: Wed, 1 Jul 2015 12:47:25 +0100 Subject: [PATCH] Fix a MOV instruction in Optimizing's x86-64 code generator. Use `movl' instead of `movw' to store a 32-bit immediate (integer or reference) into a field. Also fix art::Location::RegisterOrInt32LongConstant to properly handle non-long constants. Change-Id: I34c6ec8eaa1632822a31969f87c9c2d6c5b96326 --- compiler/optimizing/code_generator_x86_64.cc | 2 +- compiler/optimizing/locations.cc | 17 ++++--- test/521-regression-integer-field-set/expected.txt | 0 test/521-regression-integer-field-set/info.txt | 3 ++ .../521-regression-integer-field-set/src/Main.java | 58 ++++++++++++++++++++++ 5 files changed, 71 insertions(+), 9 deletions(-) create mode 100644 test/521-regression-integer-field-set/expected.txt create mode 100644 test/521-regression-integer-field-set/info.txt create mode 100644 test/521-regression-integer-field-set/src/Main.java diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc index 22f5d9663..afffbe204 100644 --- a/compiler/optimizing/code_generator_x86_64.cc +++ b/compiler/optimizing/code_generator_x86_64.cc @@ -3337,7 +3337,7 @@ void InstructionCodeGeneratorX86_64::HandleFieldSet(HInstruction* instruction, case Primitive::kPrimNot: { if (value.IsConstant()) { int32_t v = CodeGenerator::GetInt32ValueOf(value.GetConstant()); - __ movw(Address(base, offset), Immediate(v)); + __ movl(Address(base, offset), Immediate(v)); } else { __ movl(Address(base, offset), value.AsRegister()); } diff --git a/compiler/optimizing/locations.cc b/compiler/optimizing/locations.cc index 42aba0482..d14dfc190 100644 --- a/compiler/optimizing/locations.cc +++ b/compiler/optimizing/locations.cc @@ -51,16 +51,17 @@ Location Location::RegisterOrConstant(HInstruction* instruction) { } Location Location::RegisterOrInt32LongConstant(HInstruction* instruction) { - if (!instruction->IsConstant() || !instruction->AsConstant()->IsLongConstant()) { + if (instruction->IsIntConstant() || instruction->IsNullConstant()) { + return Location::ConstantLocation(instruction->AsConstant()); + } else if (instruction->IsLongConstant()) { + // Does the long constant fit in a 32 bit int? + int64_t value = instruction->AsLongConstant()->GetValue(); + return IsInt<32>(value) + ? Location::ConstantLocation(instruction->AsConstant()) + : Location::RequiresRegister(); + } else { return Location::RequiresRegister(); } - - // Does the long constant fit in a 32 bit int? - int64_t value = instruction->AsConstant()->AsLongConstant()->GetValue(); - - return IsInt<32>(value) - ? Location::ConstantLocation(instruction->AsConstant()) - : Location::RequiresRegister(); } Location Location::ByteRegisterOrConstant(int reg, HInstruction* instruction) { diff --git a/test/521-regression-integer-field-set/expected.txt b/test/521-regression-integer-field-set/expected.txt new file mode 100644 index 000000000..e69de29bb diff --git a/test/521-regression-integer-field-set/info.txt b/test/521-regression-integer-field-set/info.txt new file mode 100644 index 000000000..62f7e3dc2 --- /dev/null +++ b/test/521-regression-integer-field-set/info.txt @@ -0,0 +1,3 @@ +Regression test for Optimizing's x86-64 code generator, where moving a +32-bit immediate (integer or reference) into a field used to generate +a `movw` instruction instead of a `movl` instruction. diff --git a/test/521-regression-integer-field-set/src/Main.java b/test/521-regression-integer-field-set/src/Main.java new file mode 100644 index 000000000..9924e09f0 --- /dev/null +++ b/test/521-regression-integer-field-set/src/Main.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2015 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. + */ + +class Main { + public static void assertIntEquals(int expected, int result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } + + public static void main(String[] args) { + Main m = new Main(); + + m.$noinline$SetInstanceField(); + assertIntEquals(123456, m.i); + + $noinline$SetStaticField(); + assertIntEquals(456789, s); + } + + private static boolean doThrow = false; + + private void $noinline$SetInstanceField() { + if (doThrow) { + // Try defeating inlining. + throw new Error(); + } + + // Set a value than does not fit in a 16-bit (signed) integer. + i = 123456; + } + + private static void $noinline$SetStaticField() { + if (doThrow) { + // Try defeating inlining. + throw new Error(); + } + + // Set a value than does not fit in a 16-bit (signed) integer. + s = 456789; + } + + private int i = 0; + private static int s = 0; +} -- 2.11.0