diff options
| -rw-r--r-- | compiler/dex/quick/arm/arm_lir.h | 1 | ||||
| -rw-r--r-- | compiler/dex/quick/arm/assemble_arm.cc | 4 | ||||
| -rw-r--r-- | compiler/dex/quick/arm/codegen_arm.h | 9 | ||||
| -rw-r--r-- | compiler/dex/quick/arm/int_arm.cc | 1 | ||||
| -rw-r--r-- | compiler/dex/quick/arm/utility_arm.cc | 90 |
5 files changed, 77 insertions, 28 deletions
diff --git a/compiler/dex/quick/arm/arm_lir.h b/compiler/dex/quick/arm/arm_lir.h index 4c7f87433d..b9d9a1111d 100644 --- a/compiler/dex/quick/arm/arm_lir.h +++ b/compiler/dex/quick/arm/arm_lir.h @@ -488,6 +488,7 @@ enum ArmOpcode { kThumb2BicRRI8M, // bic rd, rn, #<const> [11110] i [000010] rn[19..16] [0] imm3[14..12] rd[11..8] imm8[7..0]. kThumb2AndRRI8M, // and rd, rn, #<const> [11110] i [000000] rn[19..16] [0] imm3[14..12] rd[11..8] imm8[7..0]. kThumb2OrrRRI8M, // orr rd, rn, #<const> [11110] i [000100] rn[19..16] [0] imm3[14..12] rd[11..8] imm8[7..0]. + kThumb2OrnRRI8M, // orn rd, rn, #<const> [11110] i [000110] rn[19..16] [0] imm3[14..12] rd[11..8] imm8[7..0]. kThumb2EorRRI8M, // eor rd, rn, #<const> [11110] i [001000] rn[19..16] [0] imm3[14..12] rd[11..8] imm8[7..0]. kThumb2AddRRI8M, // add rd, rn, #<const> [11110] i [010001] rn[19..16] [0] imm3[14..12] rd[11..8] imm8[7..0]. kThumb2AdcRRI8M, // adc rd, rn, #<const> [11110] i [010101] rn[19..16] [0] imm3[14..12] rd[11..8] imm8[7..0]. diff --git a/compiler/dex/quick/arm/assemble_arm.cc b/compiler/dex/quick/arm/assemble_arm.cc index 76ec9dfbc5..de93e2602b 100644 --- a/compiler/dex/quick/arm/assemble_arm.cc +++ b/compiler/dex/quick/arm/assemble_arm.cc @@ -788,6 +788,10 @@ const ArmEncodingMap ArmMir2Lir::EncodingMap[kArmLast] = { kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtModImm, -1, -1, kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1, "orr", "!0C, !1C, #!2m", 4, kFixupNone), + ENCODING_MAP(kThumb2OrnRRI8M, 0xf0600000, + kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtModImm, -1, -1, + kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1, + "orn", "!0C, !1C, #!2m", 4, kFixupNone), ENCODING_MAP(kThumb2EorRRI8M, 0xf0800000, kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtModImm, -1, -1, kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1, diff --git a/compiler/dex/quick/arm/codegen_arm.h b/compiler/dex/quick/arm/codegen_arm.h index e8d0c32ffd..0bc4c3b7bf 100644 --- a/compiler/dex/quick/arm/codegen_arm.h +++ b/compiler/dex/quick/arm/codegen_arm.h @@ -250,10 +250,11 @@ class ArmMir2Lir FINAL : public Mir2Lir { int EncodeShift(int code, int amount); int ModifiedImmediate(uint32_t value); ArmConditionCode ArmConditionEncoding(ConditionCode code); - bool InexpensiveConstantInt(int32_t value); - bool InexpensiveConstantFloat(int32_t value); - bool InexpensiveConstantLong(int64_t value); - bool InexpensiveConstantDouble(int64_t value); + bool InexpensiveConstantInt(int32_t value) OVERRIDE; + bool InexpensiveConstantInt(int32_t value, Instruction::Code opcode) OVERRIDE; + bool InexpensiveConstantFloat(int32_t value) OVERRIDE; + bool InexpensiveConstantLong(int64_t value) OVERRIDE; + bool InexpensiveConstantDouble(int64_t value) OVERRIDE; RegStorage AllocPreservedDouble(int s_reg); RegStorage AllocPreservedSingle(int s_reg); diff --git a/compiler/dex/quick/arm/int_arm.cc b/compiler/dex/quick/arm/int_arm.cc index 4aedbafcfb..1a7b4395d8 100644 --- a/compiler/dex/quick/arm/int_arm.cc +++ b/compiler/dex/quick/arm/int_arm.cc @@ -592,7 +592,6 @@ bool ArmMir2Lir::GetEasyMultiplyOp(int lit, ArmMir2Lir::EasyMultiplyOp* op) { // Try to convert *lit to 1~2 RegRegRegShift/RegRegShift forms. bool ArmMir2Lir::GetEasyMultiplyTwoOps(int lit, EasyMultiplyOp* ops) { - GetEasyMultiplyOp(lit, &ops[0]); if (GetEasyMultiplyOp(lit, &ops[0])) { ops[1].op = kOpInvalid; ops[1].shift = 0; diff --git a/compiler/dex/quick/arm/utility_arm.cc b/compiler/dex/quick/arm/utility_arm.cc index 7168b9f30b..117d8f016d 100644 --- a/compiler/dex/quick/arm/utility_arm.cc +++ b/compiler/dex/quick/arm/utility_arm.cc @@ -97,31 +97,11 @@ LIR* ArmMir2Lir::LoadFPConstantValue(int r_dest, int value) { return load_pc_rel; } -static int LeadingZeros(uint32_t val) { - uint32_t alt; - int32_t n; - int32_t count; - - count = 16; - n = 32; - do { - alt = val >> count; - if (alt != 0) { - n = n - count; - val = alt; - } - count >>= 1; - } while (count); - return n - val; -} - /* * Determine whether value can be encoded as a Thumb2 modified * immediate. If not, return -1. If so, return i:imm3:a:bcdefgh form. */ int ArmMir2Lir::ModifiedImmediate(uint32_t value) { - int32_t z_leading; - int32_t z_trailing; uint32_t b0 = value & 0xff; /* Note: case of value==0 must use 0:000:0:0000000 encoding */ @@ -135,8 +115,8 @@ int ArmMir2Lir::ModifiedImmediate(uint32_t value) { if (value == ((b0 << 24) | (b0 << 8))) return (0x2 << 8) | b0; /* 0:010:a:bcdefgh */ /* Can we do it with rotation? */ - z_leading = LeadingZeros(value); - z_trailing = 32 - LeadingZeros(~value & (value - 1)); + int z_leading = CLZ(value); + int z_trailing = CTZ(value); /* A run of eight or fewer active bits? */ if ((z_leading + z_trailing) < 24) return -1; /* No - bail */ @@ -152,6 +132,64 @@ bool ArmMir2Lir::InexpensiveConstantInt(int32_t value) { return (ModifiedImmediate(value) >= 0) || (ModifiedImmediate(~value) >= 0); } +bool ArmMir2Lir::InexpensiveConstantInt(int32_t value, Instruction::Code opcode) { + switch (opcode) { + case Instruction::ADD_INT: + case Instruction::ADD_INT_2ADDR: + case Instruction::SUB_INT: + case Instruction::SUB_INT_2ADDR: + if ((value >> 12) == (value >> 31)) { // Signed 12-bit, RRI12 versions of ADD/SUB. + return true; + } + FALLTHROUGH_INTENDED; + case Instruction::IF_EQ: + case Instruction::IF_NE: + case Instruction::IF_LT: + case Instruction::IF_GE: + case Instruction::IF_GT: + case Instruction::IF_LE: + return (ModifiedImmediate(value) >= 0) || (ModifiedImmediate(-value) >= 0); + case Instruction::SHL_INT: + case Instruction::SHL_INT_2ADDR: + case Instruction::SHR_INT: + case Instruction::SHR_INT_2ADDR: + case Instruction::USHR_INT: + case Instruction::USHR_INT_2ADDR: + return true; + case Instruction::AND_INT: + case Instruction::AND_INT_2ADDR: + case Instruction::AND_INT_LIT16: + case Instruction::AND_INT_LIT8: + case Instruction::OR_INT: + case Instruction::OR_INT_2ADDR: + case Instruction::OR_INT_LIT16: + case Instruction::OR_INT_LIT8: + return (ModifiedImmediate(value) >= 0) || (ModifiedImmediate(~value) >= 0); + case Instruction::XOR_INT: + case Instruction::XOR_INT_2ADDR: + case Instruction::XOR_INT_LIT16: + case Instruction::XOR_INT_LIT8: + return (ModifiedImmediate(value) >= 0); + case Instruction::MUL_INT: + case Instruction::MUL_INT_2ADDR: + case Instruction::MUL_INT_LIT8: + case Instruction::MUL_INT_LIT16: + case Instruction::DIV_INT: + case Instruction::DIV_INT_2ADDR: + case Instruction::DIV_INT_LIT8: + case Instruction::DIV_INT_LIT16: + case Instruction::REM_INT: + case Instruction::REM_INT_2ADDR: + case Instruction::REM_INT_LIT8: + case Instruction::REM_INT_LIT16: { + EasyMultiplyOp ops[2]; + return GetEasyMultiplyTwoOps(value, ops); + } + default: + return false; + } +} + bool ArmMir2Lir::InexpensiveConstantFloat(int32_t value) { return EncodeImmSingle(value) >= 0; } @@ -510,7 +548,7 @@ LIR* ArmMir2Lir::OpRegRegImm(OpKind op, RegStorage r_dest, RegStorage r_src1, in op = (op == kOpAdd) ? kOpSub : kOpAdd; } } - if (mod_imm < 0 && (abs_value & 0x3ff) == abs_value) { + if (mod_imm < 0 && (abs_value >> 12) == 0) { // This is deliberately used only if modified immediate encoding is inadequate since // we sometimes actually use the flags for small values but not necessarily low regs. if (op == kOpAdd) @@ -542,6 +580,12 @@ LIR* ArmMir2Lir::OpRegRegImm(OpKind op, RegStorage r_dest, RegStorage r_src1, in case kOpOr: opcode = kThumb2OrrRRI8M; alt_opcode = kThumb2OrrRRR; + if (mod_imm < 0) { + mod_imm = ModifiedImmediate(~value); + if (mod_imm >= 0) { + opcode = kThumb2OrnRRI8M; + } + } break; case kOpAnd: if (mod_imm < 0) { |