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
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 22f5d96..afffbe2 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -3337,7 +3337,7 @@
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<CpuRegister>());
}
diff --git a/compiler/optimizing/locations.cc b/compiler/optimizing/locations.cc
index 42aba04..d14dfc1 100644
--- a/compiler/optimizing/locations.cc
+++ b/compiler/optimizing/locations.cc
@@ -51,16 +51,17 @@
}
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 0000000..e69de29
--- /dev/null
+++ b/test/521-regression-integer-field-set/expected.txt
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 0000000..62f7e3d
--- /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 0000000..9924e09
--- /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;
+}