diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/dex/quick/arm64/arm64_lir.h | 5 | ||||
| -rw-r--r-- | compiler/dex/quick/arm64/assemble_arm64.cc | 22 | ||||
| -rw-r--r-- | compiler/dex/quick/arm64/codegen_arm64.h | 630 | ||||
| -rw-r--r-- | compiler/dex/quick/arm64/fp_arm64.cc | 47 | ||||
| -rw-r--r-- | compiler/dex/quick/arm64/utility_arm64.cc | 4 | ||||
| -rw-r--r-- | compiler/dex/quick/dex_file_method_inliner.cc | 35 | ||||
| -rw-r--r-- | compiler/dex/quick/dex_file_method_inliner.h | 4 | ||||
| -rwxr-xr-x | compiler/dex/quick/gen_invoke.cc | 16 | ||||
| -rw-r--r-- | compiler/dex/quick/mir_to_lir.h | 4 |
9 files changed, 457 insertions, 310 deletions
diff --git a/compiler/dex/quick/arm64/arm64_lir.h b/compiler/dex/quick/arm64/arm64_lir.h index 90cb156749..a449cbd4f7 100644 --- a/compiler/dex/quick/arm64/arm64_lir.h +++ b/compiler/dex/quick/arm64/arm64_lir.h @@ -267,6 +267,8 @@ enum ArmOpcode { kA64Fcvtzs2xf, // fcvtzs [100111100s111000000000] rn[9-5] rd[4-0]. kA64Fcvt2Ss, // fcvt [0001111000100010110000] rn[9-5] rd[4-0]. kA64Fcvt2sS, // fcvt [0001111001100010010000] rn[9-5] rd[4-0]. + kA64Fcvtms2ws, // fcvtms [0001111000110000000000] rn[9-5] rd[4-0]. + kA64Fcvtms2xS, // fcvtms [1001111001110000000000] rn[9-5] rd[4-0]. kA64Fdiv3fff, // fdiv[000111100s1] rm[20-16] [000110] rn[9-5] rd[4-0]. kA64Fmax3fff, // fmax[000111100s1] rm[20-16] [010010] rn[9-5] rd[4-0]. kA64Fmin3fff, // fmin[000111100s1] rm[20-16] [010110] rn[9-5] rd[4-0]. @@ -278,6 +280,9 @@ enum ArmOpcode { kA64Fmov2xS, // fmov[1001111001101111000000] rn[9-5] rd[4-0]. kA64Fmul3fff, // fmul[000111100s1] rm[20-16] [000010] rn[9-5] rd[4-0]. kA64Fneg2ff, // fneg[000111100s100001010000] rn[9-5] rd[4-0]. + kA64Frintp2ff, // frintp [000111100s100100110000] rn[9-5] rd[4-0]. + kA64Frintm2ff, // frintm [000111100s100101010000] rn[9-5] rd[4-0]. + kA64Frintn2ff, // frintn [000111100s100100010000] rn[9-5] rd[4-0]. kA64Frintz2ff, // frintz [000111100s100101110000] rn[9-5] rd[4-0]. kA64Fsqrt2ff, // fsqrt[000111100s100001110000] rn[9-5] rd[4-0]. kA64Fsub3fff, // fsub[000111100s1] rm[20-16] [001110] rn[9-5] rd[4-0]. diff --git a/compiler/dex/quick/arm64/assemble_arm64.cc b/compiler/dex/quick/arm64/assemble_arm64.cc index c46be539e8..15c89f2f18 100644 --- a/compiler/dex/quick/arm64/assemble_arm64.cc +++ b/compiler/dex/quick/arm64/assemble_arm64.cc @@ -260,6 +260,14 @@ const ArmEncodingMap Arm64Mir2Lir::EncodingMap[kA64Last] = { kFmtRegS, 4, 0, kFmtRegD, 9, 5, kFmtUnused, -1, -1, kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, "fcvt", "!0s, !1S", kFixupNone), + ENCODING_MAP(kA64Fcvtms2ws, NO_VARIANTS(0x1e300000), + kFmtRegW, 4, 0, kFmtRegS, 9, 5, kFmtUnused, -1, -1, + kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, + "fcvtms", "!0w, !1s", kFixupNone), + ENCODING_MAP(kA64Fcvtms2xS, NO_VARIANTS(0x9e700000), + kFmtRegX, 4, 0, kFmtRegD, 9, 5, kFmtUnused, -1, -1, + kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, + "fcvtms", "!0x, !1S", kFixupNone), ENCODING_MAP(FWIDE(kA64Fdiv3fff), FLOAT_VARIANTS(0x1e201800), kFmtRegF, 4, 0, kFmtRegF, 9, 5, kFmtRegF, 20, 16, kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, @@ -304,6 +312,18 @@ const ArmEncodingMap Arm64Mir2Lir::EncodingMap[kA64Last] = { kFmtRegF, 4, 0, kFmtRegF, 9, 5, kFmtUnused, -1, -1, kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, "fneg", "!0f, !1f", kFixupNone), + ENCODING_MAP(FWIDE(kA64Frintp2ff), FLOAT_VARIANTS(0x1e24c000), + kFmtRegF, 4, 0, kFmtRegF, 9, 5, kFmtUnused, -1, -1, + kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, + "frintp", "!0f, !1f", kFixupNone), + ENCODING_MAP(FWIDE(kA64Frintm2ff), FLOAT_VARIANTS(0x1e254000), + kFmtRegF, 4, 0, kFmtRegF, 9, 5, kFmtUnused, -1, -1, + kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, + "frintm", "!0f, !1f", kFixupNone), + ENCODING_MAP(FWIDE(kA64Frintn2ff), FLOAT_VARIANTS(0x1e244000), + kFmtRegF, 4, 0, kFmtRegF, 9, 5, kFmtUnused, -1, -1, + kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, + "frintn", "!0f, !1f", kFixupNone), ENCODING_MAP(FWIDE(kA64Frintz2ff), FLOAT_VARIANTS(0x1e25c000), kFmtRegF, 4, 0, kFmtRegF, 9, 5, kFmtUnused, -1, -1, kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0_USE1, @@ -521,7 +541,7 @@ const ArmEncodingMap Arm64Mir2Lir::EncodingMap[kA64Last] = { ENCODING_MAP(WIDE(kA64StpPre4ffXD), CUSTOM_VARIANTS(0x2d800000, 0x6d800000), kFmtRegF, 4, 0, kFmtRegF, 14, 10, kFmtRegXOrSp, 9, 5, kFmtBitBlt, 21, 15, IS_QUAD_OP | REG_DEF2 | REG_USE012 | IS_STORE, - "stp", "!0r, !1f, [!2X, #!3D]!!", kFixupNone), + "stp", "!0f, !1f, [!2X, #!3D]!!", kFixupNone), ENCODING_MAP(WIDE(kA64StpPre4rrXD), CUSTOM_VARIANTS(0x29800000, 0xa9800000), kFmtRegR, 4, 0, kFmtRegR, 14, 10, kFmtRegXOrSp, 9, 5, kFmtBitBlt, 21, 15, IS_QUAD_OP | REG_DEF2 | REG_USE012 | IS_STORE, diff --git a/compiler/dex/quick/arm64/codegen_arm64.h b/compiler/dex/quick/arm64/codegen_arm64.h index 18f2a291c5..2c587b8bae 100644 --- a/compiler/dex/quick/arm64/codegen_arm64.h +++ b/compiler/dex/quick/arm64/codegen_arm64.h @@ -59,332 +59,348 @@ class Arm64Mir2Lir FINAL : public Mir2Lir { bool initialized_; }; - public: - Arm64Mir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena); - - // Required for target - codegen helpers. - bool SmallLiteralDivRem(Instruction::Code dalvik_opcode, bool is_div, RegLocation rl_src, - RegLocation rl_dest, int lit) OVERRIDE; - bool SmallLiteralDivRem64(Instruction::Code dalvik_opcode, bool is_div, RegLocation rl_src, - RegLocation rl_dest, int64_t lit); - bool HandleEasyDivRem(Instruction::Code dalvik_opcode, bool is_div, - RegLocation rl_src, RegLocation rl_dest, int lit) OVERRIDE; - bool HandleEasyDivRem64(Instruction::Code dalvik_opcode, bool is_div, - RegLocation rl_src, RegLocation rl_dest, int64_t lit); - bool EasyMultiply(RegLocation rl_src, RegLocation rl_dest, int lit) OVERRIDE; - LIR* CheckSuspendUsingLoad() OVERRIDE; - RegStorage LoadHelper(QuickEntrypointEnum trampoline) OVERRIDE; - LIR* LoadBaseDisp(RegStorage r_base, int displacement, RegStorage r_dest, - OpSize size, VolatileKind is_volatile) OVERRIDE; - LIR* LoadRefDisp(RegStorage r_base, int displacement, RegStorage r_dest, - VolatileKind is_volatile) - OVERRIDE; - LIR* LoadBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_dest, int scale, - OpSize size) OVERRIDE; - LIR* LoadRefIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_dest, int scale) - OVERRIDE; - LIR* LoadConstantNoClobber(RegStorage r_dest, int value); - LIR* LoadConstantWide(RegStorage r_dest, int64_t value); - LIR* StoreBaseDisp(RegStorage r_base, int displacement, RegStorage r_src, - OpSize size, VolatileKind is_volatile) OVERRIDE; - LIR* StoreRefDisp(RegStorage r_base, int displacement, RegStorage r_src, - VolatileKind is_volatile) OVERRIDE; - LIR* StoreBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_src, int scale, - OpSize size) OVERRIDE; - LIR* StoreRefIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_src, int scale) - OVERRIDE; - void MarkGCCard(RegStorage val_reg, RegStorage tgt_addr_reg) OVERRIDE; - LIR* OpCmpMemImmBranch(ConditionCode cond, RegStorage temp_reg, RegStorage base_reg, - int offset, int check_value, LIR* target, LIR** compare) OVERRIDE; - - // Required for target - register utilities. - RegStorage TargetReg(SpecialTargetRegister reg) OVERRIDE; - RegStorage TargetReg(SpecialTargetRegister symbolic_reg, WideKind wide_kind) OVERRIDE { - if (wide_kind == kWide || wide_kind == kRef) { - return As64BitReg(TargetReg(symbolic_reg)); - } else { - return Check32BitReg(TargetReg(symbolic_reg)); - } - } - RegStorage TargetPtrReg(SpecialTargetRegister symbolic_reg) OVERRIDE { + public: + Arm64Mir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena); + + // Required for target - codegen helpers. + bool SmallLiteralDivRem(Instruction::Code dalvik_opcode, bool is_div, RegLocation rl_src, + RegLocation rl_dest, int lit) OVERRIDE; + bool HandleEasyDivRem(Instruction::Code dalvik_opcode, bool is_div, + RegLocation rl_src, RegLocation rl_dest, int lit) OVERRIDE; + bool HandleEasyDivRem64(Instruction::Code dalvik_opcode, bool is_div, + RegLocation rl_src, RegLocation rl_dest, int64_t lit); + bool EasyMultiply(RegLocation rl_src, RegLocation rl_dest, int lit) OVERRIDE; + LIR* CheckSuspendUsingLoad() OVERRIDE; + RegStorage LoadHelper(QuickEntrypointEnum trampoline) OVERRIDE; + LIR* LoadBaseDisp(RegStorage r_base, int displacement, RegStorage r_dest, + OpSize size, VolatileKind is_volatile) OVERRIDE; + LIR* LoadRefDisp(RegStorage r_base, int displacement, RegStorage r_dest, + VolatileKind is_volatile) OVERRIDE; + LIR* LoadBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_dest, int scale, + OpSize size) OVERRIDE; + LIR* LoadRefIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_dest, int scale) + OVERRIDE; + LIR* LoadConstantNoClobber(RegStorage r_dest, int value) OVERRIDE; + LIR* LoadConstantWide(RegStorage r_dest, int64_t value) OVERRIDE; + LIR* StoreBaseDisp(RegStorage r_base, int displacement, RegStorage r_src, OpSize size, + VolatileKind is_volatile) OVERRIDE; + LIR* StoreRefDisp(RegStorage r_base, int displacement, RegStorage r_src, VolatileKind is_volatile) + OVERRIDE; + LIR* StoreBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_src, int scale, + OpSize size) OVERRIDE; + LIR* StoreRefIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_src, int scale) OVERRIDE; + void MarkGCCard(RegStorage val_reg, RegStorage tgt_addr_reg) OVERRIDE; + LIR* OpCmpMemImmBranch(ConditionCode cond, RegStorage temp_reg, RegStorage base_reg, + int offset, int check_value, LIR* target, LIR** compare) OVERRIDE; + + // Required for target - register utilities. + RegStorage TargetReg(SpecialTargetRegister reg) OVERRIDE; + RegStorage TargetReg(SpecialTargetRegister symbolic_reg, WideKind wide_kind) OVERRIDE { + if (wide_kind == kWide || wide_kind == kRef) { return As64BitReg(TargetReg(symbolic_reg)); + } else { + return Check32BitReg(TargetReg(symbolic_reg)); } - RegStorage GetArgMappingToPhysicalReg(int arg_num); - RegLocation GetReturnAlt(); - RegLocation GetReturnWideAlt(); - RegLocation LocCReturn(); - RegLocation LocCReturnRef(); - RegLocation LocCReturnDouble(); - RegLocation LocCReturnFloat(); - RegLocation LocCReturnWide(); - ResourceMask GetRegMaskCommon(const RegStorage& reg) const OVERRIDE; - void AdjustSpillMask(); - void ClobberCallerSave(); - void FreeCallTemps(); - void LockCallTemps(); - void CompilerInitializeRegAlloc(); - - // Required for target - miscellaneous. - void AssembleLIR(); - uint32_t LinkFixupInsns(LIR* head_lir, LIR* tail_lir, CodeOffset offset); - int AssignInsnOffsets(); - void AssignOffsets(); - uint8_t* EncodeLIRs(uint8_t* write_pos, LIR* lir); - void DumpResourceMask(LIR* lir, const ResourceMask& mask, const char* prefix) OVERRIDE; - void SetupTargetResourceMasks(LIR* lir, uint64_t flags, - ResourceMask* use_mask, ResourceMask* def_mask) OVERRIDE; - const char* GetTargetInstFmt(int opcode); - const char* GetTargetInstName(int opcode); - std::string BuildInsnString(const char* fmt, LIR* lir, unsigned char* base_addr); - ResourceMask GetPCUseDefEncoding() const OVERRIDE; - uint64_t GetTargetInstFlags(int opcode); - size_t GetInsnSize(LIR* lir) OVERRIDE; - bool IsUnconditionalBranch(LIR* lir); - - // Get the register class for load/store of a field. - RegisterClass RegClassForFieldLoadStore(OpSize size, bool is_volatile) OVERRIDE; - - // Required for target - Dalvik-level generators. - void GenShiftOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, - RegLocation lr_shift); - void GenArithImmOpLong(Instruction::Code opcode, RegLocation rl_dest, - RegLocation rl_src1, RegLocation rl_src2); - void GenArrayGet(int opt_flags, OpSize size, RegLocation rl_array, - RegLocation rl_index, RegLocation rl_dest, int scale); - void GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array, RegLocation rl_index, - RegLocation rl_src, int scale, bool card_mark); - void GenShiftImmOpLong(Instruction::Code opcode, RegLocation rl_dest, - RegLocation rl_src1, RegLocation rl_shift); - void GenLongOp(OpKind op, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); - void GenMulLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2); - void GenAddLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2); - void GenAndLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2); - void GenArithOpDouble(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2); - void GenArithOpFloat(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2); - void GenCmpFP(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2); - void GenConversion(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src); - bool GenInlinedReverseBits(CallInfo* info, OpSize size); - bool GenInlinedAbsFloat(CallInfo* info) OVERRIDE; - bool GenInlinedAbsDouble(CallInfo* info) OVERRIDE; - bool GenInlinedCas(CallInfo* info, bool is_long, bool is_object); - bool GenInlinedMinMax(CallInfo* info, bool is_min, bool is_long); - bool GenInlinedMinMaxFP(CallInfo* info, bool is_min, bool is_double); - bool GenInlinedSqrt(CallInfo* info); - bool GenInlinedPeek(CallInfo* info, OpSize size); - bool GenInlinedPoke(CallInfo* info, OpSize size); - bool GenInlinedAbsLong(CallInfo* info); - void GenIntToLong(RegLocation rl_dest, RegLocation rl_src); - void GenNotLong(RegLocation rl_dest, RegLocation rl_src); - void GenNegLong(RegLocation rl_dest, RegLocation rl_src); - void GenOrLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2); - void GenSubLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2); - void GenXorLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2); - void GenDivRemLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2, bool is_div); - RegLocation GenDivRem(RegLocation rl_dest, RegStorage reg_lo, RegStorage reg_hi, bool is_div); - RegLocation GenDivRemLit(RegLocation rl_dest, RegStorage reg_lo, int lit, bool is_div); - void GenCmpLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); - void GenDivZeroCheckWide(RegStorage reg); - void GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method); - void GenExitSequence(); - void GenSpecialExitSequence(); - void GenFillArrayData(DexOffset table_offset, RegLocation rl_src); - void GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias, bool is_double); - void GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir); - void GenSelect(BasicBlock* bb, MIR* mir) OVERRIDE; - void GenSelectConst32(RegStorage left_op, RegStorage right_op, ConditionCode code, - int32_t true_val, int32_t false_val, RegStorage rs_dest, - int dest_reg_class) OVERRIDE; - // Helper used in the above two. - void GenSelect(int32_t left, int32_t right, ConditionCode code, RegStorage rs_dest, - int result_reg_class); - - bool GenMemBarrier(MemBarrierKind barrier_kind); - void GenMonitorEnter(int opt_flags, RegLocation rl_src); - void GenMonitorExit(int opt_flags, RegLocation rl_src); - void GenMoveException(RegLocation rl_dest); - void GenMultiplyByTwoBitMultiplier(RegLocation rl_src, RegLocation rl_result, int lit, - int first_bit, int second_bit); - void GenNegDouble(RegLocation rl_dest, RegLocation rl_src); - void GenNegFloat(RegLocation rl_dest, RegLocation rl_src); - void GenPackedSwitch(MIR* mir, DexOffset table_offset, RegLocation rl_src); - void GenSparseSwitch(MIR* mir, DexOffset table_offset, RegLocation rl_src); - - // Spill core and FP registers. Returns the SP difference: either spill size, or whole - // frame size. - int SpillRegs(RegStorage base, uint32_t core_reg_mask, uint32_t fp_reg_mask, int frame_size); - - // Unspill core and FP registers. - void UnspillRegs(RegStorage base, uint32_t core_reg_mask, uint32_t fp_reg_mask, int frame_size); - - // Required for target - single operation generators. - LIR* OpUnconditionalBranch(LIR* target); - LIR* OpCmpBranch(ConditionCode cond, RegStorage src1, RegStorage src2, LIR* target); - LIR* OpCmpImmBranch(ConditionCode cond, RegStorage reg, int check_value, LIR* target); - LIR* OpCondBranch(ConditionCode cc, LIR* target); - LIR* OpDecAndBranch(ConditionCode c_code, RegStorage reg, LIR* target); - LIR* OpFpRegCopy(RegStorage r_dest, RegStorage r_src); - LIR* OpIT(ConditionCode cond, const char* guide); - void OpEndIT(LIR* it); - LIR* OpMem(OpKind op, RegStorage r_base, int disp); - LIR* OpPcRelLoad(RegStorage reg, LIR* target); - LIR* OpReg(OpKind op, RegStorage r_dest_src); - void OpRegCopy(RegStorage r_dest, RegStorage r_src); - LIR* OpRegCopyNoInsert(RegStorage r_dest, RegStorage r_src); - LIR* OpRegImm64(OpKind op, RegStorage r_dest_src1, int64_t value); - LIR* OpRegImm(OpKind op, RegStorage r_dest_src1, int value); - LIR* OpRegReg(OpKind op, RegStorage r_dest_src1, RegStorage r_src2); - LIR* OpMovRegMem(RegStorage r_dest, RegStorage r_base, int offset, MoveType move_type); - LIR* OpMovMemReg(RegStorage r_base, int offset, RegStorage r_src, MoveType move_type); - LIR* OpCondRegReg(OpKind op, ConditionCode cc, RegStorage r_dest, RegStorage r_src); - LIR* OpRegRegImm64(OpKind op, RegStorage r_dest, RegStorage r_src1, int64_t value); - LIR* OpRegRegImm(OpKind op, RegStorage r_dest, RegStorage r_src1, int value); - LIR* OpRegRegReg(OpKind op, RegStorage r_dest, RegStorage r_src1, RegStorage r_src2); - LIR* OpTestSuspend(LIR* target); - LIR* OpVldm(RegStorage r_base, int count); - LIR* OpVstm(RegStorage r_base, int count); - void OpRegCopyWide(RegStorage dest, RegStorage src); - - LIR* LoadBaseDispBody(RegStorage r_base, int displacement, RegStorage r_dest, OpSize size); - LIR* StoreBaseDispBody(RegStorage r_base, int displacement, RegStorage r_src, OpSize size); - LIR* OpRegRegRegShift(OpKind op, RegStorage r_dest, RegStorage r_src1, RegStorage r_src2, - int shift); - LIR* OpRegRegRegExtend(OpKind op, RegStorage r_dest, RegStorage r_src1, RegStorage r_src2, - A64RegExtEncodings ext, uint8_t amount); - LIR* OpRegRegShift(OpKind op, RegStorage r_dest_src1, RegStorage r_src2, int shift); - LIR* OpRegRegExtend(OpKind op, RegStorage r_dest_src1, RegStorage r_src2, - A64RegExtEncodings ext, uint8_t amount); - static const ArmEncodingMap EncodingMap[kA64Last]; - int EncodeShift(int code, int amount); - int EncodeExtend(int extend_type, int amount); - bool IsExtendEncoding(int encoded_value); - int EncodeLogicalImmediate(bool is_wide, uint64_t value); - uint64_t DecodeLogicalImmediate(bool is_wide, int 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); - - void FlushIns(RegLocation* ArgLocs, RegLocation rl_method); - - int GenDalvikArgsNoRange(CallInfo* info, int call_state, LIR** pcrLabel, - NextCallInsn next_call_insn, - const MethodReference& target_method, - uint32_t vtable_idx, - uintptr_t direct_code, uintptr_t direct_method, InvokeType type, - bool skip_this); - - int GenDalvikArgsRange(CallInfo* info, int call_state, LIR** pcrLabel, + } + RegStorage TargetPtrReg(SpecialTargetRegister symbolic_reg) OVERRIDE { + return As64BitReg(TargetReg(symbolic_reg)); + } + RegStorage GetArgMappingToPhysicalReg(int arg_num) OVERRIDE; + RegLocation GetReturnAlt() OVERRIDE; + RegLocation GetReturnWideAlt() OVERRIDE; + RegLocation LocCReturn() OVERRIDE; + RegLocation LocCReturnRef() OVERRIDE; + RegLocation LocCReturnDouble() OVERRIDE; + RegLocation LocCReturnFloat() OVERRIDE; + RegLocation LocCReturnWide() OVERRIDE; + ResourceMask GetRegMaskCommon(const RegStorage& reg) const OVERRIDE; + void AdjustSpillMask() OVERRIDE; + void ClobberCallerSave() OVERRIDE; + void FreeCallTemps() OVERRIDE; + void LockCallTemps() OVERRIDE; + void CompilerInitializeRegAlloc() OVERRIDE; + + // Required for target - miscellaneous. + void AssembleLIR() OVERRIDE; + void DumpResourceMask(LIR* lir, const ResourceMask& mask, const char* prefix) OVERRIDE; + void SetupTargetResourceMasks(LIR* lir, uint64_t flags, + ResourceMask* use_mask, ResourceMask* def_mask) OVERRIDE; + const char* GetTargetInstFmt(int opcode) OVERRIDE; + const char* GetTargetInstName(int opcode) OVERRIDE; + std::string BuildInsnString(const char* fmt, LIR* lir, unsigned char* base_addr) OVERRIDE; + ResourceMask GetPCUseDefEncoding() const OVERRIDE; + uint64_t GetTargetInstFlags(int opcode) OVERRIDE; + size_t GetInsnSize(LIR* lir) OVERRIDE; + bool IsUnconditionalBranch(LIR* lir) OVERRIDE; + + // Get the register class for load/store of a field. + RegisterClass RegClassForFieldLoadStore(OpSize size, bool is_volatile) OVERRIDE; + + // Required for target - Dalvik-level generators. + void GenShiftOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, + RegLocation lr_shift) OVERRIDE; + void GenArithImmOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, + RegLocation rl_src2) OVERRIDE; + void GenArrayGet(int opt_flags, OpSize size, RegLocation rl_array, RegLocation rl_index, + RegLocation rl_dest, int scale) OVERRIDE; + void GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array, RegLocation rl_index, + RegLocation rl_src, int scale, bool card_mark) OVERRIDE; + void GenShiftImmOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, + RegLocation rl_shift) OVERRIDE; + void GenMulLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, + RegLocation rl_src2) OVERRIDE; + void GenAddLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, + RegLocation rl_src2) OVERRIDE; + void GenAndLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, + RegLocation rl_src2) OVERRIDE; + void GenArithOpDouble(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, + RegLocation rl_src2) OVERRIDE; + void GenArithOpFloat(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, + RegLocation rl_src2) OVERRIDE; + void GenCmpFP(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, + RegLocation rl_src2) OVERRIDE; + void GenConversion(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src) OVERRIDE; + bool GenInlinedReverseBits(CallInfo* info, OpSize size) OVERRIDE; + bool GenInlinedAbsFloat(CallInfo* info) OVERRIDE; + bool GenInlinedAbsDouble(CallInfo* info) OVERRIDE; + bool GenInlinedCas(CallInfo* info, bool is_long, bool is_object) OVERRIDE; + bool GenInlinedMinMax(CallInfo* info, bool is_min, bool is_long) OVERRIDE; + bool GenInlinedMinMaxFP(CallInfo* info, bool is_min, bool is_double) OVERRIDE; + bool GenInlinedSqrt(CallInfo* info) OVERRIDE; + bool GenInlinedCeil(CallInfo* info) OVERRIDE; + bool GenInlinedFloor(CallInfo* info) OVERRIDE; + bool GenInlinedRint(CallInfo* info) OVERRIDE; + bool GenInlinedRound(CallInfo* info, bool is_double) OVERRIDE; + bool GenInlinedPeek(CallInfo* info, OpSize size) OVERRIDE; + bool GenInlinedPoke(CallInfo* info, OpSize size) OVERRIDE; + bool GenInlinedAbsLong(CallInfo* info) OVERRIDE; + void GenIntToLong(RegLocation rl_dest, RegLocation rl_src) OVERRIDE; + void GenNotLong(RegLocation rl_dest, RegLocation rl_src) OVERRIDE; + void GenNegLong(RegLocation rl_dest, RegLocation rl_src) OVERRIDE; + void GenOrLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, + RegLocation rl_src2) OVERRIDE; + void GenSubLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, + RegLocation rl_src2) OVERRIDE; + void GenXorLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, + RegLocation rl_src2) OVERRIDE; + void GenDivRemLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, + RegLocation rl_src2, bool is_div) OVERRIDE; + RegLocation GenDivRem(RegLocation rl_dest, RegStorage reg_lo, RegStorage reg_hi, bool is_div) + OVERRIDE; + RegLocation GenDivRemLit(RegLocation rl_dest, RegStorage reg_lo, int lit, bool is_div) + OVERRIDE; + void GenCmpLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) OVERRIDE; + void GenDivZeroCheckWide(RegStorage reg) OVERRIDE; + void GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method) OVERRIDE; + void GenExitSequence() OVERRIDE; + void GenSpecialExitSequence() OVERRIDE; + void GenFillArrayData(DexOffset table_offset, RegLocation rl_src) OVERRIDE; + void GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias, bool is_double) OVERRIDE; + void GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir) OVERRIDE; + void GenSelect(BasicBlock* bb, MIR* mir) OVERRIDE; + void GenSelectConst32(RegStorage left_op, RegStorage right_op, ConditionCode code, + int32_t true_val, int32_t false_val, RegStorage rs_dest, + int dest_reg_class) OVERRIDE; + + bool GenMemBarrier(MemBarrierKind barrier_kind) OVERRIDE; + void GenMonitorEnter(int opt_flags, RegLocation rl_src) OVERRIDE; + void GenMonitorExit(int opt_flags, RegLocation rl_src) OVERRIDE; + void GenMoveException(RegLocation rl_dest) OVERRIDE; + void GenMultiplyByTwoBitMultiplier(RegLocation rl_src, RegLocation rl_result, int lit, + int first_bit, int second_bit) OVERRIDE; + void GenNegDouble(RegLocation rl_dest, RegLocation rl_src) OVERRIDE; + void GenNegFloat(RegLocation rl_dest, RegLocation rl_src) OVERRIDE; + void GenPackedSwitch(MIR* mir, DexOffset table_offset, RegLocation rl_src) OVERRIDE; + void GenSparseSwitch(MIR* mir, DexOffset table_offset, RegLocation rl_src) OVERRIDE; + + // Required for target - single operation generators. + LIR* OpUnconditionalBranch(LIR* target) OVERRIDE; + LIR* OpCmpBranch(ConditionCode cond, RegStorage src1, RegStorage src2, LIR* target) OVERRIDE; + LIR* OpCmpImmBranch(ConditionCode cond, RegStorage reg, int check_value, LIR* target) OVERRIDE; + LIR* OpCondBranch(ConditionCode cc, LIR* target) OVERRIDE; + LIR* OpDecAndBranch(ConditionCode c_code, RegStorage reg, LIR* target) OVERRIDE; + LIR* OpFpRegCopy(RegStorage r_dest, RegStorage r_src) OVERRIDE; + LIR* OpIT(ConditionCode cond, const char* guide) OVERRIDE; + void OpEndIT(LIR* it) OVERRIDE; + LIR* OpMem(OpKind op, RegStorage r_base, int disp) OVERRIDE; + LIR* OpPcRelLoad(RegStorage reg, LIR* target) OVERRIDE; + LIR* OpReg(OpKind op, RegStorage r_dest_src) OVERRIDE; + void OpRegCopy(RegStorage r_dest, RegStorage r_src) OVERRIDE; + LIR* OpRegCopyNoInsert(RegStorage r_dest, RegStorage r_src) OVERRIDE; + LIR* OpRegImm(OpKind op, RegStorage r_dest_src1, int value) OVERRIDE; + LIR* OpRegReg(OpKind op, RegStorage r_dest_src1, RegStorage r_src2) OVERRIDE; + LIR* OpMovRegMem(RegStorage r_dest, RegStorage r_base, int offset, MoveType move_type) OVERRIDE; + LIR* OpMovMemReg(RegStorage r_base, int offset, RegStorage r_src, MoveType move_type) OVERRIDE; + LIR* OpCondRegReg(OpKind op, ConditionCode cc, RegStorage r_dest, RegStorage r_src) OVERRIDE; + LIR* OpRegRegImm(OpKind op, RegStorage r_dest, RegStorage r_src1, int value) OVERRIDE; + LIR* OpRegRegReg(OpKind op, RegStorage r_dest, RegStorage r_src1, RegStorage r_src2) OVERRIDE; + LIR* OpTestSuspend(LIR* target) OVERRIDE; + LIR* OpVldm(RegStorage r_base, int count) OVERRIDE; + LIR* OpVstm(RegStorage r_base, int count) OVERRIDE; + void OpRegCopyWide(RegStorage dest, RegStorage src) OVERRIDE; + + bool InexpensiveConstantInt(int32_t value) OVERRIDE; + bool InexpensiveConstantFloat(int32_t value) OVERRIDE; + bool InexpensiveConstantLong(int64_t value) OVERRIDE; + bool InexpensiveConstantDouble(int64_t value) OVERRIDE; + + void FlushIns(RegLocation* ArgLocs, RegLocation rl_method) OVERRIDE; + + int GenDalvikArgsNoRange(CallInfo* info, int call_state, LIR** pcrLabel, NextCallInsn next_call_insn, const MethodReference& target_method, uint32_t vtable_idx, uintptr_t direct_code, uintptr_t direct_method, InvokeType type, - bool skip_this); - InToRegStorageMapping in_to_reg_storage_mapping_; + bool skip_this) OVERRIDE; - bool WideGPRsAreAliases() OVERRIDE { - return true; // 64b architecture. - } - bool WideFPRsAreAliases() OVERRIDE { - return true; // 64b architecture. - } - size_t GetInstructionOffset(LIR* lir); - - LIR* InvokeTrampoline(OpKind op, RegStorage r_tgt, QuickEntrypointEnum trampoline) OVERRIDE; - - private: - /** - * @brief Given register xNN (dNN), returns register wNN (sNN). - * @param reg #RegStorage containing a Solo64 input register (e.g. @c x1 or @c d2). - * @return A Solo32 with the same register number as the @p reg (e.g. @c w1 or @c s2). - * @see As64BitReg - */ - RegStorage As32BitReg(RegStorage reg) { - DCHECK(!reg.IsPair()); - if ((kFailOnSizeError || kReportSizeError) && !reg.Is64Bit()) { - if (kFailOnSizeError) { - LOG(FATAL) << "Expected 64b register"; - } else { - LOG(WARNING) << "Expected 64b register"; - return reg; - } + int GenDalvikArgsRange(CallInfo* info, int call_state, LIR** pcrLabel, + NextCallInsn next_call_insn, + const MethodReference& target_method, + uint32_t vtable_idx, + uintptr_t direct_code, uintptr_t direct_method, InvokeType type, + bool skip_this) OVERRIDE; + + bool WideGPRsAreAliases() OVERRIDE { + return true; // 64b architecture. + } + bool WideFPRsAreAliases() OVERRIDE { + return true; // 64b architecture. + } + + size_t GetInstructionOffset(LIR* lir) OVERRIDE; + + LIR* InvokeTrampoline(OpKind op, RegStorage r_tgt, QuickEntrypointEnum trampoline) OVERRIDE; + + private: + /** + * @brief Given register xNN (dNN), returns register wNN (sNN). + * @param reg #RegStorage containing a Solo64 input register (e.g. @c x1 or @c d2). + * @return A Solo32 with the same register number as the @p reg (e.g. @c w1 or @c s2). + * @see As64BitReg + */ + RegStorage As32BitReg(RegStorage reg) { + DCHECK(!reg.IsPair()); + if ((kFailOnSizeError || kReportSizeError) && !reg.Is64Bit()) { + if (kFailOnSizeError) { + LOG(FATAL) << "Expected 64b register"; + } else { + LOG(WARNING) << "Expected 64b register"; + return reg; } - RegStorage ret_val = RegStorage(RegStorage::k32BitSolo, - reg.GetRawBits() & RegStorage::kRegTypeMask); - DCHECK_EQ(GetRegInfo(reg)->FindMatchingView(RegisterInfo::k32SoloStorageMask) - ->GetReg().GetReg(), - ret_val.GetReg()); - return ret_val; } + RegStorage ret_val = RegStorage(RegStorage::k32BitSolo, + reg.GetRawBits() & RegStorage::kRegTypeMask); + DCHECK_EQ(GetRegInfo(reg)->FindMatchingView(RegisterInfo::k32SoloStorageMask) + ->GetReg().GetReg(), + ret_val.GetReg()); + return ret_val; + } - RegStorage Check32BitReg(RegStorage reg) { - if ((kFailOnSizeError || kReportSizeError) && !reg.Is32Bit()) { - if (kFailOnSizeError) { - LOG(FATAL) << "Checked for 32b register"; - } else { - LOG(WARNING) << "Checked for 32b register"; - return As32BitReg(reg); - } + RegStorage Check32BitReg(RegStorage reg) { + if ((kFailOnSizeError || kReportSizeError) && !reg.Is32Bit()) { + if (kFailOnSizeError) { + LOG(FATAL) << "Checked for 32b register"; + } else { + LOG(WARNING) << "Checked for 32b register"; + return As32BitReg(reg); } - return reg; } + return reg; + } - /** - * @brief Given register wNN (sNN), returns register xNN (dNN). - * @param reg #RegStorage containing a Solo32 input register (e.g. @c w1 or @c s2). - * @return A Solo64 with the same register number as the @p reg (e.g. @c x1 or @c d2). - * @see As32BitReg - */ - RegStorage As64BitReg(RegStorage reg) { - DCHECK(!reg.IsPair()); - if ((kFailOnSizeError || kReportSizeError) && !reg.Is32Bit()) { - if (kFailOnSizeError) { - LOG(FATAL) << "Expected 32b register"; - } else { - LOG(WARNING) << "Expected 32b register"; - return reg; - } + /** + * @brief Given register wNN (sNN), returns register xNN (dNN). + * @param reg #RegStorage containing a Solo32 input register (e.g. @c w1 or @c s2). + * @return A Solo64 with the same register number as the @p reg (e.g. @c x1 or @c d2). + * @see As32BitReg + */ + RegStorage As64BitReg(RegStorage reg) { + DCHECK(!reg.IsPair()); + if ((kFailOnSizeError || kReportSizeError) && !reg.Is32Bit()) { + if (kFailOnSizeError) { + LOG(FATAL) << "Expected 32b register"; + } else { + LOG(WARNING) << "Expected 32b register"; + return reg; } - RegStorage ret_val = RegStorage(RegStorage::k64BitSolo, - reg.GetRawBits() & RegStorage::kRegTypeMask); - DCHECK_EQ(GetRegInfo(reg)->FindMatchingView(RegisterInfo::k64SoloStorageMask) - ->GetReg().GetReg(), - ret_val.GetReg()); - return ret_val; } + RegStorage ret_val = RegStorage(RegStorage::k64BitSolo, + reg.GetRawBits() & RegStorage::kRegTypeMask); + DCHECK_EQ(GetRegInfo(reg)->FindMatchingView(RegisterInfo::k64SoloStorageMask) + ->GetReg().GetReg(), + ret_val.GetReg()); + return ret_val; + } - RegStorage Check64BitReg(RegStorage reg) { - if ((kFailOnSizeError || kReportSizeError) && !reg.Is64Bit()) { - if (kFailOnSizeError) { - LOG(FATAL) << "Checked for 64b register"; - } else { - LOG(WARNING) << "Checked for 64b register"; - return As64BitReg(reg); - } + RegStorage Check64BitReg(RegStorage reg) { + if ((kFailOnSizeError || kReportSizeError) && !reg.Is64Bit()) { + if (kFailOnSizeError) { + LOG(FATAL) << "Checked for 64b register"; + } else { + LOG(WARNING) << "Checked for 64b register"; + return As64BitReg(reg); } - return reg; } + return reg; + } + + int32_t EncodeImmSingle(uint32_t bits); + int32_t EncodeImmDouble(uint64_t bits); + LIR* LoadFPConstantValue(RegStorage r_dest, int32_t value); + LIR* LoadFPConstantValueWide(RegStorage r_dest, int64_t value); + void ReplaceFixup(LIR* prev_lir, LIR* orig_lir, LIR* new_lir); + void InsertFixupBefore(LIR* prev_lir, LIR* orig_lir, LIR* new_lir); + void AssignDataOffsets(); + RegLocation GenDivRem(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2, + bool is_div, bool check_zero); + RegLocation GenDivRemLit(RegLocation rl_dest, RegLocation rl_src1, int lit, bool is_div); + size_t GetLoadStoreSize(LIR* lir); + + bool SmallLiteralDivRem64(Instruction::Code dalvik_opcode, bool is_div, RegLocation rl_src, + RegLocation rl_dest, int64_t lit); + + uint32_t LinkFixupInsns(LIR* head_lir, LIR* tail_lir, CodeOffset offset); + int AssignInsnOffsets(); + void AssignOffsets(); + uint8_t* EncodeLIRs(uint8_t* write_pos, LIR* lir); + + // Spill core and FP registers. Returns the SP difference: either spill size, or whole + // frame size. + int SpillRegs(RegStorage base, uint32_t core_reg_mask, uint32_t fp_reg_mask, int frame_size); + + // Unspill core and FP registers. + void UnspillRegs(RegStorage base, uint32_t core_reg_mask, uint32_t fp_reg_mask, int frame_size); + + void GenLongOp(OpKind op, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); + + LIR* OpRegImm64(OpKind op, RegStorage r_dest_src1, int64_t value); + LIR* OpRegRegImm64(OpKind op, RegStorage r_dest, RegStorage r_src1, int64_t value); + + LIR* OpRegRegShift(OpKind op, RegStorage r_dest_src1, RegStorage r_src2, int shift); + LIR* OpRegRegRegShift(OpKind op, RegStorage r_dest, RegStorage r_src1, RegStorage r_src2, + int shift); + int EncodeShift(int code, int amount); + + LIR* OpRegRegExtend(OpKind op, RegStorage r_dest_src1, RegStorage r_src2, + A64RegExtEncodings ext, uint8_t amount); + LIR* OpRegRegRegExtend(OpKind op, RegStorage r_dest, RegStorage r_src1, RegStorage r_src2, + A64RegExtEncodings ext, uint8_t amount); + int EncodeExtend(int extend_type, int amount); + bool IsExtendEncoding(int encoded_value); + + LIR* LoadBaseDispBody(RegStorage r_base, int displacement, RegStorage r_dest, OpSize size); + LIR* StoreBaseDispBody(RegStorage r_base, int displacement, RegStorage r_src, OpSize size); + + int EncodeLogicalImmediate(bool is_wide, uint64_t value); + uint64_t DecodeLogicalImmediate(bool is_wide, int value); + ArmConditionCode ArmConditionEncoding(ConditionCode code); + + // Helper used in the two GenSelect variants. + void GenSelect(int32_t left, int32_t right, ConditionCode code, RegStorage rs_dest, + int result_reg_class); - LIR* LoadFPConstantValue(RegStorage r_dest, int32_t value); - LIR* LoadFPConstantValueWide(RegStorage r_dest, int64_t value); - void ReplaceFixup(LIR* prev_lir, LIR* orig_lir, LIR* new_lir); - void InsertFixupBefore(LIR* prev_lir, LIR* orig_lir, LIR* new_lir); - void AssignDataOffsets(); - RegLocation GenDivRem(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2, - bool is_div, bool check_zero); - RegLocation GenDivRemLit(RegLocation rl_dest, RegLocation rl_src1, int lit, bool is_div); - size_t GetLoadStoreSize(LIR* lir); + InToRegStorageMapping in_to_reg_storage_mapping_; + static const ArmEncodingMap EncodingMap[kA64Last]; }; } // namespace art diff --git a/compiler/dex/quick/arm64/fp_arm64.cc b/compiler/dex/quick/arm64/fp_arm64.cc index ed13c04361..d0b2636453 100644 --- a/compiler/dex/quick/arm64/fp_arm64.cc +++ b/compiler/dex/quick/arm64/fp_arm64.cc @@ -17,6 +17,7 @@ #include "arm64_lir.h" #include "codegen_arm64.h" #include "dex/quick/mir_to_lir-inl.h" +#include "utils.h" namespace art { @@ -386,6 +387,52 @@ bool Arm64Mir2Lir::GenInlinedSqrt(CallInfo* info) { return true; } +bool Arm64Mir2Lir::GenInlinedCeil(CallInfo* info) { + RegLocation rl_src = info->args[0]; + RegLocation rl_dest = InlineTargetWide(info); + rl_src = LoadValueWide(rl_src, kFPReg); + RegLocation rl_result = EvalLoc(rl_dest, kFPReg, true); + NewLIR2(FWIDE(kA64Frintp2ff), rl_result.reg.GetReg(), rl_src.reg.GetReg()); + StoreValueWide(rl_dest, rl_result); + return true; +} + +bool Arm64Mir2Lir::GenInlinedFloor(CallInfo* info) { + RegLocation rl_src = info->args[0]; + RegLocation rl_dest = InlineTargetWide(info); + rl_src = LoadValueWide(rl_src, kFPReg); + RegLocation rl_result = EvalLoc(rl_dest, kFPReg, true); + NewLIR2(FWIDE(kA64Frintm2ff), rl_result.reg.GetReg(), rl_src.reg.GetReg()); + StoreValueWide(rl_dest, rl_result); + return true; +} + +bool Arm64Mir2Lir::GenInlinedRint(CallInfo* info) { + RegLocation rl_src = info->args[0]; + RegLocation rl_dest = InlineTargetWide(info); + rl_src = LoadValueWide(rl_src, kFPReg); + RegLocation rl_result = EvalLoc(rl_dest, kFPReg, true); + NewLIR2(FWIDE(kA64Frintn2ff), rl_result.reg.GetReg(), rl_src.reg.GetReg()); + StoreValueWide(rl_dest, rl_result); + return true; +} + +bool Arm64Mir2Lir::GenInlinedRound(CallInfo* info, bool is_double) { + int32_t encoded_imm = EncodeImmSingle(bit_cast<float, uint32_t>(0.5f)); + ArmOpcode wide = (is_double) ? FWIDE(0) : FUNWIDE(0); + RegLocation rl_src = info->args[0]; + RegLocation rl_dest = (is_double) ? InlineTargetWide(info) : InlineTarget(info); + rl_src = (is_double) ? LoadValueWide(rl_src, kFPReg) : LoadValue(rl_src, kFPReg); + RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); + RegStorage r_tmp = (is_double) ? AllocTempDouble() : AllocTempSingle(); + // 0.5f and 0.5d are encoded in the same way. + NewLIR2(kA64Fmov2fI | wide, r_tmp.GetReg(), encoded_imm); + NewLIR3(kA64Fadd3fff | wide, rl_src.reg.GetReg(), rl_src.reg.GetReg(), r_tmp.GetReg()); + NewLIR2((is_double) ? kA64Fcvtms2xS : kA64Fcvtms2ws, rl_result.reg.GetReg(), rl_src.reg.GetReg()); + (is_double) ? StoreValueWide(rl_dest, rl_result) : StoreValue(rl_dest, rl_result); + return true; +} + bool Arm64Mir2Lir::GenInlinedMinMaxFP(CallInfo* info, bool is_min, bool is_double) { DCHECK_EQ(cu_->instruction_set, kArm64); int op = (is_min) ? kA64Fmin3fff : kA64Fmax3fff; diff --git a/compiler/dex/quick/arm64/utility_arm64.cc b/compiler/dex/quick/arm64/utility_arm64.cc index 5131bd816d..cd1840ae0a 100644 --- a/compiler/dex/quick/arm64/utility_arm64.cc +++ b/compiler/dex/quick/arm64/utility_arm64.cc @@ -23,7 +23,7 @@ namespace art { /* This file contains codegen for the A64 ISA. */ -static int32_t EncodeImmSingle(uint32_t bits) { +int32_t Arm64Mir2Lir::EncodeImmSingle(uint32_t bits) { /* * Valid values will have the form: * @@ -55,7 +55,7 @@ static int32_t EncodeImmSingle(uint32_t bits) { return (bit7 | bit6 | bit5_to_0); } -static int32_t EncodeImmDouble(uint64_t bits) { +int32_t Arm64Mir2Lir::EncodeImmDouble(uint64_t bits) { /* * Valid values will have the form: * diff --git a/compiler/dex/quick/dex_file_method_inliner.cc b/compiler/dex/quick/dex_file_method_inliner.cc index 0e46c96501..7abf3e7ed5 100644 --- a/compiler/dex/quick/dex_file_method_inliner.cc +++ b/compiler/dex/quick/dex_file_method_inliner.cc @@ -48,6 +48,11 @@ static constexpr bool kIntrinsicIsStatic[] = { true, // kIntrinsicMinMaxFloat true, // kIntrinsicMinMaxDouble true, // kIntrinsicSqrt + true, // kIntrinsicCeil + true, // kIntrinsicFloor + true, // kIntrinsicRint + true, // kIntrinsicRoundFloat + true, // kIntrinsicRoundDouble false, // kIntrinsicGet false, // kIntrinsicCharAt false, // kIntrinsicCompareTo @@ -75,6 +80,11 @@ COMPILE_ASSERT(kIntrinsicIsStatic[kIntrinsicMinMaxLong], MinMaxLong_must_be_stat COMPILE_ASSERT(kIntrinsicIsStatic[kIntrinsicMinMaxFloat], MinMaxFloat_must_be_static); COMPILE_ASSERT(kIntrinsicIsStatic[kIntrinsicMinMaxDouble], MinMaxDouble_must_be_static); COMPILE_ASSERT(kIntrinsicIsStatic[kIntrinsicSqrt], Sqrt_must_be_static); +COMPILE_ASSERT(kIntrinsicIsStatic[kIntrinsicCeil], Ceil_must_be_static); +COMPILE_ASSERT(kIntrinsicIsStatic[kIntrinsicFloor], Floor_must_be_static); +COMPILE_ASSERT(kIntrinsicIsStatic[kIntrinsicRint], Rint_must_be_static); +COMPILE_ASSERT(kIntrinsicIsStatic[kIntrinsicRoundFloat], RoundFloat_must_be_static); +COMPILE_ASSERT(kIntrinsicIsStatic[kIntrinsicRoundDouble], RoundDouble_must_be_static); COMPILE_ASSERT(!kIntrinsicIsStatic[kIntrinsicGet], Get_must_not_be_static); COMPILE_ASSERT(!kIntrinsicIsStatic[kIntrinsicCharAt], CharAt_must_not_be_static); COMPILE_ASSERT(!kIntrinsicIsStatic[kIntrinsicCompareTo], CompareTo_must_not_be_static); @@ -155,6 +165,10 @@ const char* const DexFileMethodInliner::kNameCacheNames[] = { "max", // kNameCacheMax "min", // kNameCacheMin "sqrt", // kNameCacheSqrt + "ceil", // kNameCacheCeil + "floor", // kNameCacheFloor + "rint", // kNameCacheRint + "round", // kNameCacheRound "get", // kNameCacheGet "charAt", // kNameCacheCharAt "compareTo", // kNameCacheCompareTo @@ -314,6 +328,17 @@ const DexFileMethodInliner::IntrinsicDef DexFileMethodInliner::kIntrinsicMethods INTRINSIC(JavaLangMath, Sqrt, D_D, kIntrinsicSqrt, 0), INTRINSIC(JavaLangStrictMath, Sqrt, D_D, kIntrinsicSqrt, 0), + INTRINSIC(JavaLangMath, Ceil, D_D, kIntrinsicCeil, 0), + INTRINSIC(JavaLangStrictMath, Ceil, D_D, kIntrinsicCeil, 0), + INTRINSIC(JavaLangMath, Floor, D_D, kIntrinsicFloor, 0), + INTRINSIC(JavaLangStrictMath, Floor, D_D, kIntrinsicFloor, 0), + INTRINSIC(JavaLangMath, Rint, D_D, kIntrinsicRint, 0), + INTRINSIC(JavaLangStrictMath, Rint, D_D, kIntrinsicRint, 0), + INTRINSIC(JavaLangMath, Round, F_I, kIntrinsicRoundFloat, 0), + INTRINSIC(JavaLangStrictMath, Round, F_I, kIntrinsicRoundFloat, 0), + INTRINSIC(JavaLangMath, Round, D_J, kIntrinsicRoundDouble, 0), + INTRINSIC(JavaLangStrictMath, Round, D_J, kIntrinsicRoundDouble, 0), + INTRINSIC(JavaLangRefReference, Get, _Object, kIntrinsicGet, 0), INTRINSIC(JavaLangString, CharAt, I_C, kIntrinsicCharAt, 0), @@ -436,6 +461,16 @@ bool DexFileMethodInliner::GenIntrinsic(Mir2Lir* backend, CallInfo* info) { return backend->GenInlinedMinMaxFP(info, intrinsic.d.data & kIntrinsicFlagMin, true /* is_double */); case kIntrinsicSqrt: return backend->GenInlinedSqrt(info); + case kIntrinsicCeil: + return backend->GenInlinedCeil(info); + case kIntrinsicFloor: + return backend->GenInlinedFloor(info); + case kIntrinsicRint: + return backend->GenInlinedRint(info); + case kIntrinsicRoundFloat: + return backend->GenInlinedRound(info, false /* is_double */); + case kIntrinsicRoundDouble: + return backend->GenInlinedRound(info, true /* is_double */); case kIntrinsicGet: return backend->GenInlinedGet(info); case kIntrinsicCharAt: diff --git a/compiler/dex/quick/dex_file_method_inliner.h b/compiler/dex/quick/dex_file_method_inliner.h index cb8c165ce5..1bd3c48e34 100644 --- a/compiler/dex/quick/dex_file_method_inliner.h +++ b/compiler/dex/quick/dex_file_method_inliner.h @@ -141,6 +141,10 @@ class DexFileMethodInliner { kNameCacheMax, kNameCacheMin, kNameCacheSqrt, + kNameCacheCeil, + kNameCacheFloor, + kNameCacheRint, + kNameCacheRound, kNameCacheGet, kNameCacheCharAt, kNameCacheCompareTo, diff --git a/compiler/dex/quick/gen_invoke.cc b/compiler/dex/quick/gen_invoke.cc index 5fc699669d..8e7f6a6c58 100755 --- a/compiler/dex/quick/gen_invoke.cc +++ b/compiler/dex/quick/gen_invoke.cc @@ -1427,6 +1427,22 @@ bool Mir2Lir::GenInlinedMinMaxFP(CallInfo* info, bool is_min, bool is_double) { return false; } +bool Mir2Lir::GenInlinedCeil(CallInfo* info) { + return false; +} + +bool Mir2Lir::GenInlinedFloor(CallInfo* info) { + return false; +} + +bool Mir2Lir::GenInlinedRint(CallInfo* info) { + return false; +} + +bool Mir2Lir::GenInlinedRound(CallInfo* info, bool is_double) { + return false; +} + bool Mir2Lir::GenInlinedFloatCvt(CallInfo* info) { if (cu_->instruction_set == kMips) { // TODO - add Mips implementation diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h index b19942db8c..70c17da6ad 100644 --- a/compiler/dex/quick/mir_to_lir.h +++ b/compiler/dex/quick/mir_to_lir.h @@ -965,6 +965,10 @@ class Mir2Lir : public Backend { virtual bool GenInlinedAbsDouble(CallInfo* info) = 0; bool GenInlinedFloatCvt(CallInfo* info); bool GenInlinedDoubleCvt(CallInfo* info); + virtual bool GenInlinedCeil(CallInfo* info); + virtual bool GenInlinedFloor(CallInfo* info); + virtual bool GenInlinedRint(CallInfo* info); + virtual bool GenInlinedRound(CallInfo* info, bool is_double); virtual bool GenInlinedArrayCopyCharArray(CallInfo* info); virtual bool GenInlinedIndexOf(CallInfo* info, bool zero_based); bool GenInlinedStringCompareTo(CallInfo* info); |