diff options
author | Roland Levillain <rpl@google.com> | 2014-10-24 10:48:38 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2014-10-24 10:48:39 +0000 |
commit | 64727aeef8f4243f2058a19a43a937248a60dae1 (patch) | |
tree | 9bf09ff29bb49d4be382e49822300668913f18e5 | |
parent | 8bde036ebd74ce94477e65077bed6dea9c29616b (diff) | |
parent | 2e07b4f0a84a7968b4690c2b1be2e2f75cc6fa8e (diff) | |
download | android_art-64727aeef8f4243f2058a19a43a937248a60dae1.tar.gz android_art-64727aeef8f4243f2058a19a43a937248a60dae1.tar.bz2 android_art-64727aeef8f4243f2058a19a43a937248a60dae1.zip |
Merge "Revert "Revert "Implement long negate instruction in the optimizing compiler."""
-rw-r--r-- | compiler/optimizing/builder.cc | 5 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_arm.cc | 26 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86.cc | 13 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86_64.cc | 6 | ||||
-rw-r--r-- | compiler/utils/x86_64/assembler_x86_64.cc | 7 | ||||
-rw-r--r-- | compiler/utils/x86_64/assembler_x86_64.h | 1 | ||||
-rw-r--r-- | test/411-optimizing-arith/src/Main.java | 34 | ||||
-rw-r--r-- | test/415-optimizing-arith-neg/expected.txt | 0 | ||||
-rw-r--r-- | test/415-optimizing-arith-neg/info.txt | 1 | ||||
-rw-r--r-- | test/415-optimizing-arith-neg/src/Main.java | 98 | ||||
-rw-r--r-- | test/Android.run-test.mk | 1 |
11 files changed, 154 insertions, 38 deletions
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc index e5e996434a..e4dee46c39 100644 --- a/compiler/optimizing/builder.cc +++ b/compiler/optimizing/builder.cc @@ -748,6 +748,11 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, uint32 break; } + case Instruction::NEG_LONG: { + Unop_12x<HNeg>(instruction, Primitive::kPrimLong); + break; + } + case Instruction::NOT_INT: { Unop_12x<HNot>(instruction, Primitive::kPrimInt); break; diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc index 7b00d2f523..a3b31d89c9 100644 --- a/compiler/optimizing/code_generator_arm.cc +++ b/compiler/optimizing/code_generator_arm.cc @@ -1043,11 +1043,13 @@ void LocationsBuilderARM::VisitNeg(HNeg* neg) { new (GetGraph()->GetArena()) LocationSummary(neg, LocationSummary::kNoCall); switch (neg->GetResultType()) { case Primitive::kPrimInt: + case Primitive::kPrimLong: { + bool output_overlaps = (neg->GetResultType() == Primitive::kPrimLong); locations->SetInAt(0, Location::RequiresRegister()); - locations->SetOut(Location::RequiresRegister()); + locations->SetOut(Location::RequiresRegister(), output_overlaps); break; + } - case Primitive::kPrimLong: case Primitive::kPrimFloat: case Primitive::kPrimDouble: LOG(FATAL) << "Not yet implemented neg type " << neg->GetResultType(); @@ -1069,6 +1071,26 @@ void InstructionCodeGeneratorARM::VisitNeg(HNeg* neg) { break; case Primitive::kPrimLong: + DCHECK(in.IsRegisterPair()); + // out.lo = 0 - in.lo (and update the carry/borrow (C) flag) + __ rsbs(out.AsRegisterPairLow<Register>(), + in.AsRegisterPairLow<Register>(), + ShifterOperand(0)); + // We cannot emit an RSC (Reverse Subtract with Carry) + // instruction here, as it does not exist in the Thumb-2 + // instruction set. We use the following approach + // using SBC and SUB instead. + // + // out.hi = -C + __ sbc(out.AsRegisterPairHigh<Register>(), + out.AsRegisterPairHigh<Register>(), + ShifterOperand(out.AsRegisterPairHigh<Register>())); + // out.hi = out.hi - in.hi + __ sub(out.AsRegisterPairHigh<Register>(), + out.AsRegisterPairHigh<Register>(), + ShifterOperand(in.AsRegisterPairHigh<Register>())); + break; + case Primitive::kPrimFloat: case Primitive::kPrimDouble: LOG(FATAL) << "Not yet implemented neg type " << neg->GetResultType(); diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc index 61f0750c5c..aa0f06b67f 100644 --- a/compiler/optimizing/code_generator_x86.cc +++ b/compiler/optimizing/code_generator_x86.cc @@ -990,11 +990,11 @@ void LocationsBuilderX86::VisitNeg(HNeg* neg) { new (GetGraph()->GetArena()) LocationSummary(neg, LocationSummary::kNoCall); switch (neg->GetResultType()) { case Primitive::kPrimInt: + case Primitive::kPrimLong: locations->SetInAt(0, Location::RequiresRegister()); locations->SetOut(Location::SameAsFirstInput()); break; - case Primitive::kPrimLong: case Primitive::kPrimFloat: case Primitive::kPrimDouble: LOG(FATAL) << "Not yet implemented neg type " << neg->GetResultType(); @@ -1016,6 +1016,17 @@ void InstructionCodeGeneratorX86::VisitNeg(HNeg* neg) { break; case Primitive::kPrimLong: + DCHECK(in.IsRegisterPair()); + __ negl(out.AsRegisterPairLow<Register>()); + // Negation is similar to subtraction from zero. The least + // significant byte triggers a borrow when it is different from + // zero; to take it into account, add 1 to the most significant + // byte if the carry flag (CF) is set to 1 after the first NEGL + // operation. + __ adcl(out.AsRegisterPairHigh<Register>(), Immediate(0)); + __ negl(out.AsRegisterPairHigh<Register>()); + break; + case Primitive::kPrimFloat: case Primitive::kPrimDouble: LOG(FATAL) << "Not yet implemented neg type " << neg->GetResultType(); diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc index 4a05b89892..892ca9d9c7 100644 --- a/compiler/optimizing/code_generator_x86_64.cc +++ b/compiler/optimizing/code_generator_x86_64.cc @@ -976,11 +976,11 @@ void LocationsBuilderX86_64::VisitNeg(HNeg* neg) { new (GetGraph()->GetArena()) LocationSummary(neg, LocationSummary::kNoCall); switch (neg->GetResultType()) { case Primitive::kPrimInt: + case Primitive::kPrimLong: locations->SetInAt(0, Location::RequiresRegister()); locations->SetOut(Location::SameAsFirstInput()); break; - case Primitive::kPrimLong: case Primitive::kPrimFloat: case Primitive::kPrimDouble: LOG(FATAL) << "Not yet implemented neg type " << neg->GetResultType(); @@ -1002,6 +1002,10 @@ void InstructionCodeGeneratorX86_64::VisitNeg(HNeg* neg) { break; case Primitive::kPrimLong: + DCHECK(in.IsRegister()); + __ negq(out.As<CpuRegister>()); + break; + case Primitive::kPrimFloat: case Primitive::kPrimDouble: LOG(FATAL) << "Not yet implemented neg type " << neg->GetResultType(); diff --git a/compiler/utils/x86_64/assembler_x86_64.cc b/compiler/utils/x86_64/assembler_x86_64.cc index f4c9862f93..f164138168 100644 --- a/compiler/utils/x86_64/assembler_x86_64.cc +++ b/compiler/utils/x86_64/assembler_x86_64.cc @@ -1340,6 +1340,13 @@ void X86_64Assembler::negl(CpuRegister reg) { EmitOperand(3, Operand(reg)); } +void X86_64Assembler::negq(CpuRegister reg) { + AssemblerBuffer::EnsureCapacity ensured(&buffer_); + EmitRex64(reg); + EmitUint8(0xF7); + EmitOperand(3, Operand(reg)); +} + void X86_64Assembler::notl(CpuRegister reg) { AssemblerBuffer::EnsureCapacity ensured(&buffer_); diff --git a/compiler/utils/x86_64/assembler_x86_64.h b/compiler/utils/x86_64/assembler_x86_64.h index 92b81ec2e7..ec29271b5e 100644 --- a/compiler/utils/x86_64/assembler_x86_64.h +++ b/compiler/utils/x86_64/assembler_x86_64.h @@ -450,6 +450,7 @@ class X86_64Assembler FINAL : public Assembler { void shrq(CpuRegister reg, const Immediate& imm); void negl(CpuRegister reg); + void negq(CpuRegister reg); void notl(CpuRegister reg); void enter(const Immediate& imm); diff --git a/test/411-optimizing-arith/src/Main.java b/test/411-optimizing-arith/src/Main.java index 4de2271ebd..a22c516ff4 100644 --- a/test/411-optimizing-arith/src/Main.java +++ b/test/411-optimizing-arith/src/Main.java @@ -74,7 +74,6 @@ public class Main { public static void main(String[] args) { mul(); - neg(); } public static void mul() { @@ -164,34 +163,6 @@ public class Main { expectEquals(Double.POSITIVE_INFINITY, $opt$Mul(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY)); } - public static void neg() { - expectEquals(-1, $opt$Neg(1)); - expectEquals(1, $opt$Neg(-1)); - expectEquals(0, $opt$Neg(0)); - expectEquals(51, $opt$Neg(-51)); - expectEquals(-51, $opt$Neg(51)); - expectEquals(2147483647, $opt$Neg(-2147483647)); // (2^31 - 1) - expectEquals(-2147483647, $opt$Neg(2147483647)); // -(2^31 - 1) - // From the Java 7 SE Edition specification: - // http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.15.4 - // - // For integer values, negation is the same as subtraction from - // zero. The Java programming language uses two's-complement - // representation for integers, and the range of two's-complement - // values is not symmetric, so negation of the maximum negative - // int or long results in that same maximum negative number. - // Overflow occurs in this case, but no exception is thrown. - // For all integer values x, -x equals (~x)+1.'' - expectEquals(-2147483648, $opt$Neg(-2147483648)); // -(2^31) - - $opt$InplaceNegOne(1); - } - - public static void $opt$InplaceNegOne(int a) { - a = -a; - expectEquals(-1, a); - } - static int $opt$Mul(int a, int b) { return a * b; } @@ -207,9 +178,4 @@ public class Main { static double $opt$Mul(double a, double b) { return a * b; } - - static int $opt$Neg(int a){ - return -a; - } - } diff --git a/test/415-optimizing-arith-neg/expected.txt b/test/415-optimizing-arith-neg/expected.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/415-optimizing-arith-neg/expected.txt diff --git a/test/415-optimizing-arith-neg/info.txt b/test/415-optimizing-arith-neg/info.txt new file mode 100644 index 0000000000..8494aad938 --- /dev/null +++ b/test/415-optimizing-arith-neg/info.txt @@ -0,0 +1 @@ +Tests for arithmetic negation operations. diff --git a/test/415-optimizing-arith-neg/src/Main.java b/test/415-optimizing-arith-neg/src/Main.java new file mode 100644 index 0000000000..b21b998235 --- /dev/null +++ b/test/415-optimizing-arith-neg/src/Main.java @@ -0,0 +1,98 @@ +/* + * 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. + */ + +// Note that $opt$ is a marker for the optimizing compiler to ensure +// it does compile the method. +public class Main { + + public static void expectEquals(int expected, int result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } + + public static void expectEquals(long expected, long result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } + + public static void main(String[] args) { + negInt(); + $opt$InplaceNegOneInt(1); + + negLong(); + $opt$InplaceNegOneLong(1L); + } + + private static void negInt() { + expectEquals(-1, $opt$NegInt(1)); + expectEquals(1, $opt$NegInt(-1)); + expectEquals(0, $opt$NegInt(0)); + expectEquals(51, $opt$NegInt(-51)); + expectEquals(-51, $opt$NegInt(51)); + expectEquals(2147483647, $opt$NegInt(-2147483647)); // (2^31 - 1) + expectEquals(-2147483647, $opt$NegInt(2147483647)); // -(2^31 - 1) + // From the Java 7 SE Edition specification: + // http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.15.4 + // + // For integer values, negation is the same as subtraction from + // zero. The Java programming language uses two's-complement + // representation for integers, and the range of two's-complement + // values is not symmetric, so negation of the maximum negative + // int or long results in that same maximum negative number. + // Overflow occurs in this case, but no exception is thrown. + // For all integer values x, -x equals (~x)+1.'' + expectEquals(-2147483648, $opt$NegInt(-2147483648)); // -(2^31) + } + + private static void $opt$InplaceNegOneInt(int a) { + a = -a; + expectEquals(-1, a); + } + + private static void negLong() { + expectEquals(-1L, $opt$NegLong(1L)); + expectEquals(1L, $opt$NegLong(-1L)); + expectEquals(0L, $opt$NegLong(0L)); + expectEquals(51L, $opt$NegLong(-51L)); + expectEquals(-51L, $opt$NegLong(51L)); + + expectEquals(2147483647L, $opt$NegLong(-2147483647L)); // (2^31 - 1) + expectEquals(-2147483647L, $opt$NegLong(2147483647L)); // -(2^31 - 1) + expectEquals(2147483648L, $opt$NegLong(-2147483648L)); // 2^31 + expectEquals(-2147483648L, $opt$NegLong(2147483648L)); // -(2^31) + + expectEquals(9223372036854775807L, $opt$NegLong(-9223372036854775807L)); // (2^63 - 1) + expectEquals(-9223372036854775807L, $opt$NegLong(9223372036854775807L)); // -(2^63 - 1) + // See remark regarding the negation of the maximum negative + // (long) value in negInt(). + expectEquals(-9223372036854775808L, $opt$NegLong(-9223372036854775808L)); // -(2^63) + } + + private static void $opt$InplaceNegOneLong(long a) { + a = -a; + expectEquals(-1L, a); + } + + static int $opt$NegInt(int a){ + return -a; + } + + static long $opt$NegLong(long a){ + return -a; + } +} diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk index 682282532b..5b95beb96e 100644 --- a/test/Android.run-test.mk +++ b/test/Android.run-test.mk @@ -317,6 +317,7 @@ TEST_ART_BROKEN_OPTIMIZING_ARM64_RUN_TESTS := \ 412-new-array \ 413-regalloc-regression \ 414-optimizing-arith-sub \ + 415-optimizing-arith-neg \ 700-LoadArgRegs \ 800-smali |