diff options
author | Anton Kirilov <anton.kirilov@linaro.org> | 2017-02-28 16:59:15 +0000 |
---|---|---|
committer | Anton Kirilov <anton.kirilov@linaro.org> | 2017-03-10 15:15:15 +0000 |
commit | effd5bfa62fa3065a8386b192bf60d41c320f6e4 (patch) | |
tree | 7bd021367a3e6b0cfd9cd3bf08fb5bd5c177c666 /compiler/optimizing/code_generator_arm.cc | |
parent | f92e179efdd070c4d54633ac305199b10f957bd7 (diff) |
ARM: Generate UBFX for HAnd
Test: m test-art-target-run-test-538-checker-embed-constants
Change-Id: I8e6af76b99543331e8ffec01bd8df3f09890708e
Diffstat (limited to 'compiler/optimizing/code_generator_arm.cc')
-rw-r--r-- | compiler/optimizing/code_generator_arm.cc | 33 |
1 files changed, 23 insertions, 10 deletions
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc index bab626f5ae..5d62dcb4ff 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)); } } |