From: Anton Kirilov Date: Tue, 28 Feb 2017 16:59:15 +0000 (+0000) Subject: ARM: Generate UBFX for HAnd X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=effd5bfa62fa3065a8386b192bf60d41c320f6e4;p=android-x86%2Fart.git ARM: Generate UBFX for HAnd Test: m test-art-target-run-test-538-checker-embed-constants Change-Id: I8e6af76b99543331e8ffec01bd8df3f09890708e --- diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc index bab626f5a..5d62dcb4f 100644 --- a/compiler/optimizing/code_generator_arm.cc +++ b/compiler/optimizing/code_generator_arm.cc @@ -5304,18 +5304,29 @@ bool LocationsBuilderARM::CanEncodeConstantAsImmediate(uint32_t value, return true; } Opcode neg_opcode = kNoOperand; + uint32_t neg_value = 0; switch (opcode) { - case AND: neg_opcode = BIC; value = ~value; break; - case ORR: neg_opcode = ORN; value = ~value; break; - case ADD: neg_opcode = SUB; value = -value; break; - case ADC: neg_opcode = SBC; value = ~value; break; - case SUB: neg_opcode = ADD; value = -value; break; - case SBC: neg_opcode = ADC; value = ~value; break; - case MOV: neg_opcode = MVN; value = ~value; break; + case AND: neg_opcode = BIC; neg_value = ~value; break; + case ORR: neg_opcode = ORN; neg_value = ~value; break; + case ADD: neg_opcode = SUB; neg_value = -value; break; + case ADC: neg_opcode = SBC; neg_value = ~value; break; + case SUB: neg_opcode = ADD; neg_value = -value; break; + case SBC: neg_opcode = ADC; neg_value = ~value; break; + case MOV: neg_opcode = MVN; neg_value = ~value; break; default: return false; } - return assembler->ShifterOperandCanHold(kNoRegister, kNoRegister, neg_opcode, value, set_cc, &so); + + if (assembler->ShifterOperandCanHold(kNoRegister, + kNoRegister, + neg_opcode, + neg_value, + set_cc, + &so)) { + return true; + } + + return opcode == AND && IsPowerOfTwo(value + 1); } void InstructionCodeGeneratorARM::HandleFieldGet(HInstruction* instruction, @@ -7571,9 +7582,11 @@ void InstructionCodeGeneratorARM::GenerateAndConst(Register out, Register first, ShifterOperand so; if (__ ShifterOperandCanHold(kNoRegister, kNoRegister, AND, value, &so)) { __ and_(out, first, so); - } else { - DCHECK(__ ShifterOperandCanHold(kNoRegister, kNoRegister, BIC, ~value, &so)); + } else if (__ ShifterOperandCanHold(kNoRegister, kNoRegister, BIC, ~value, &so)) { __ bic(out, first, ShifterOperand(~value)); + } else { + DCHECK(IsPowerOfTwo(value + 1)); + __ ubfx(out, first, 0, WhichPowerOf2(value + 1)); } } diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc index a1f30cd2b..3bf1a4e91 100644 --- a/compiler/optimizing/code_generator_arm_vixl.cc +++ b/compiler/optimizing/code_generator_arm_vixl.cc @@ -5315,18 +5315,24 @@ bool LocationsBuilderARMVIXL::CanEncodeConstantAsImmediate(uint32_t value, return true; } Opcode neg_opcode = kNoOperand; + uint32_t neg_value = 0; switch (opcode) { - case AND: neg_opcode = BIC; value = ~value; break; - case ORR: neg_opcode = ORN; value = ~value; break; - case ADD: neg_opcode = SUB; value = -value; break; - case ADC: neg_opcode = SBC; value = ~value; break; - case SUB: neg_opcode = ADD; value = -value; break; - case SBC: neg_opcode = ADC; value = ~value; break; - case MOV: neg_opcode = MVN; value = ~value; break; + case AND: neg_opcode = BIC; neg_value = ~value; break; + case ORR: neg_opcode = ORN; neg_value = ~value; break; + case ADD: neg_opcode = SUB; neg_value = -value; break; + case ADC: neg_opcode = SBC; neg_value = ~value; break; + case SUB: neg_opcode = ADD; neg_value = -value; break; + case SBC: neg_opcode = ADC; neg_value = ~value; break; + case MOV: neg_opcode = MVN; neg_value = ~value; break; default: return false; } - return assembler->ShifterOperandCanHold(neg_opcode, value, set_cc); + + if (assembler->ShifterOperandCanHold(neg_opcode, neg_value, set_cc)) { + return true; + } + + return opcode == AND && IsPowerOfTwo(value + 1); } void InstructionCodeGeneratorARMVIXL::HandleFieldGet(HInstruction* instruction, @@ -7631,10 +7637,12 @@ void InstructionCodeGeneratorARMVIXL::GenerateAndConst(vixl32::Register out, return; } if (GetAssembler()->ShifterOperandCanHold(AND, value)) { - __ And(out, first, value); + __ And(out, first, value); + } else if (GetAssembler()->ShifterOperandCanHold(BIC, ~value)) { + __ Bic(out, first, ~value); } else { - DCHECK(GetAssembler()->ShifterOperandCanHold(BIC, ~value)); - __ Bic(out, first, ~value); + DCHECK(IsPowerOfTwo(value + 1)); + __ Ubfx(out, first, 0, WhichPowerOf2(value + 1)); } } diff --git a/test/538-checker-embed-constants/src/Main.java b/test/538-checker-embed-constants/src/Main.java index 4f34ec90e..94aad9d32 100644 --- a/test/538-checker-embed-constants/src/Main.java +++ b/test/538-checker-embed-constants/src/Main.java @@ -37,13 +37,20 @@ public class Main { } /// CHECK-START-ARM: int Main.and511(int) disassembly (after) - /// CHECK: mov {{r\d+}}, #511 - /// CHECK: and{{(\.w)?}} {{r\d+}}, {{r\d+}}, {{r\d+}} + /// CHECK: ubfx {{r\d+}}, {{r\d+}}, #0, #9 public static int and511(int arg) { return arg & 511; } + /// CHECK-START-ARM: int Main.andF00D(int) disassembly (after) + /// CHECK: mov {{r\d+}}, #61453 + /// CHECK: and{{(\.w)?}} {{r\d+}}, {{r\d+}}, {{r\d+}} + + public static int andF00D(int arg) { + return arg & 0xF00D; + } + /// CHECK-START-ARM: int Main.andNot15(int) disassembly (after) /// CHECK-NOT: mvn {{r\d+}}, #15 /// CHECK: bic {{r\d+}}, {{r\d+}}, #0xf @@ -114,17 +121,29 @@ public class Main { } /// CHECK-START-ARM: long Main.and511(long) disassembly (after) - /// CHECK: mov {{r\d+}}, #511 + /// CHECK: ubfx {{r\d+}}, {{r\d+}}, #0, #9 /// CHECK-NEXT: mov{{s?}} {{r\d+}}, #0 /// CHECK-NOT: and{{(\.w)?}} /// CHECK-NOT: bic{{(\.w)?}} + + public static long and511(long arg) { + return arg & 511L; + } + + /// CHECK-START-ARM: long Main.andF00D(long) disassembly (after) + /// CHECK: mov {{r\d+}}, #61453 + /// CHECK-NEXT: mov{{s?}} {{r\d+}}, #0 + /// CHECK-NOT: and{{(\.w)?}} + /// CHECK-NOT: bic{{(\.w)?}} + /// CHECK-NOT: ubfx /// CHECK: and{{(\.w)?}} {{r\d+}}, {{r\d+}}, {{r\d+}} /// CHECK-NEXT: and{{(\.w)?}} {{r\d+}}, {{r\d+}}, {{r\d+}} /// CHECK-NOT: and{{(\.w)?}} /// CHECK-NOT: bic{{(\.w)?}} + /// CHECK-NOT: ubfx - public static long and511(long arg) { - return arg & 511L; + public static long andF00D(long arg) { + return arg & 0xF00DL; } /// CHECK-START-ARM: long Main.andNot15(long) disassembly (after) @@ -631,6 +650,7 @@ public class Main { int arg = 0x87654321; assertIntEquals(and255(arg), 0x21); assertIntEquals(and511(arg), 0x121); + assertIntEquals(andF00D(arg), 0x4001); assertIntEquals(andNot15(arg), 0x87654320); assertIntEquals(or255(arg), 0x876543ff); assertIntEquals(or511(arg), 0x876543ff); @@ -642,6 +662,7 @@ public class Main { long longArg = 0x1234567887654321L; assertLongEquals(and255(longArg), 0x21L); assertLongEquals(and511(longArg), 0x121L); + assertLongEquals(andF00D(longArg), 0x4001L); assertLongEquals(andNot15(longArg), 0x1234567887654320L); assertLongEquals(and0xfffffff00000000f(longArg), 0x1234567000000001L); assertLongEquals(or255(longArg), 0x12345678876543ffL);