From e88b89ad1d1a583daf205c7a387ba13f549f95f1 Mon Sep 17 00:00:00 2001 From: Yixin Shou Date: Wed, 5 Mar 2014 06:07:48 -0500 Subject: [PATCH] Add x86 inlined abs method for float/double Add the optimized implementation of inlined abs method for float/double for X86 side. Change-Id: I4e095644a90524354040174954c1e127c7bb4ee2 Signed-off-by: Yixin Shou --- compiler/dex/quick/dex_file_method_inliner.cc | 8 ++- compiler/dex/quick/dex_file_method_inliner.h | 2 +- compiler/dex/quick/mir_to_lir.h | 4 +- compiler/dex/quick/x86/codegen_x86.h | 10 +++ compiler/dex/quick/x86/fp_x86.cc | 92 +++++++++++++++++++++++++++ compiler/dex/quick/x86/utility_x86.cc | 23 +++++++ 6 files changed, 134 insertions(+), 5 deletions(-) diff --git a/compiler/dex/quick/dex_file_method_inliner.cc b/compiler/dex/quick/dex_file_method_inliner.cc index 639720879..3f9379c8b 100644 --- a/compiler/dex/quick/dex_file_method_inliner.cc +++ b/compiler/dex/quick/dex_file_method_inliner.cc @@ -292,10 +292,14 @@ bool DexFileMethodInliner::AnalyseMethodCode(verifier::MethodVerifier* verifier) return success && AddInlineMethod(verifier->GetMethodReference().dex_method_index, method); } -bool DexFileMethodInliner::IsIntrinsic(uint32_t method_index) { +bool DexFileMethodInliner::IsIntrinsic(uint32_t method_index, InlineMethod* intrinsic) { ReaderMutexLock mu(Thread::Current(), lock_); auto it = inline_methods_.find(method_index); - return it != inline_methods_.end() && (it->second.flags & kInlineIntrinsic) != 0; + bool res = (it != inline_methods_.end() && (it->second.flags & kInlineIntrinsic) != 0); + if (res && intrinsic != nullptr) { + *intrinsic = it->second; + } + return res; } bool DexFileMethodInliner::GenIntrinsic(Mir2Lir* backend, CallInfo* info) { diff --git a/compiler/dex/quick/dex_file_method_inliner.h b/compiler/dex/quick/dex_file_method_inliner.h index c03f89c8f..70693c201 100644 --- a/compiler/dex/quick/dex_file_method_inliner.h +++ b/compiler/dex/quick/dex_file_method_inliner.h @@ -67,7 +67,7 @@ class DexFileMethodInliner { /** * Check whether a particular method index corresponds to an intrinsic function. */ - bool IsIntrinsic(uint32_t method_index) LOCKS_EXCLUDED(lock_); + bool IsIntrinsic(uint32_t method_index, InlineMethod* intrinsic) LOCKS_EXCLUDED(lock_); /** * Generate code for an intrinsic function invocation. diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h index 9155677c2..ca65432c5 100644 --- a/compiler/dex/quick/mir_to_lir.h +++ b/compiler/dex/quick/mir_to_lir.h @@ -953,8 +953,8 @@ class Mir2Lir : public Backend { bool GenInlinedReverseBytes(CallInfo* info, OpSize size); bool GenInlinedAbsInt(CallInfo* info); virtual bool GenInlinedAbsLong(CallInfo* info); - bool GenInlinedAbsFloat(CallInfo* info); - bool GenInlinedAbsDouble(CallInfo* info); + virtual bool GenInlinedAbsFloat(CallInfo* info); + virtual bool GenInlinedAbsDouble(CallInfo* info); bool GenInlinedFloatCvt(CallInfo* info); bool GenInlinedDoubleCvt(CallInfo* info); virtual bool GenInlinedIndexOf(CallInfo* info, bool zero_based); diff --git a/compiler/dex/quick/x86/codegen_x86.h b/compiler/dex/quick/x86/codegen_x86.h index 354084370..05d8c2adc 100644 --- a/compiler/dex/quick/x86/codegen_x86.h +++ b/compiler/dex/quick/x86/codegen_x86.h @@ -154,6 +154,8 @@ class X86Mir2Lir : public Mir2Lir { bool GenInlinedCas(CallInfo* info, bool is_long, bool is_object); bool GenInlinedMinMaxInt(CallInfo* info, bool is_min); bool GenInlinedSqrt(CallInfo* info); + bool GenInlinedAbsFloat(CallInfo* info) OVERRIDE; + bool GenInlinedAbsDouble(CallInfo* info) OVERRIDE; bool GenInlinedPeek(CallInfo* info, OpSize size); bool GenInlinedPoke(CallInfo* info, OpSize size); void GenNotLong(RegLocation rl_dest, RegLocation rl_src); @@ -795,6 +797,14 @@ class X86Mir2Lir : public Mir2Lir { */ void AnalyzeDoubleUse(RegLocation rl_use); + /* + * @brief Analyze one invoke-static MIR instruction + * @param opcode MIR instruction opcode. + * @param bb Basic block containing instruction. + * @param mir Instruction to analyze. + */ + void AnalyzeInvokeStatic(int opcode, BasicBlock * bb, MIR *mir); + bool Gen64Bit() const { return gen64bit_; } // Information derived from analysis of MIR diff --git a/compiler/dex/quick/x86/fp_x86.cc b/compiler/dex/quick/x86/fp_x86.cc index f6f06170b..26f6a69ef 100644 --- a/compiler/dex/quick/x86/fp_x86.cc +++ b/compiler/dex/quick/x86/fp_x86.cc @@ -501,6 +501,98 @@ bool X86Mir2Lir::GenInlinedSqrt(CallInfo* info) { return true; } +bool X86Mir2Lir::GenInlinedAbsFloat(CallInfo* info) { + // Get the argument + RegLocation rl_src = info->args[0]; + + // Get the inlined intrinsic target virtual register + RegLocation rl_dest = InlineTarget(info); + + // Get the virtual register number + int v_src_reg = mir_graph_->SRegToVReg(rl_src.s_reg_low); + int v_dst_reg = mir_graph_->SRegToVReg(rl_dest.s_reg_low); + + // if argument is the same as inlined intrinsic target + if (v_src_reg == v_dst_reg) { + rl_src = UpdateLoc(rl_src); + + // if argument is in the physical register + if (rl_src.location == kLocPhysReg) { + rl_src = LoadValue(rl_src, kCoreReg); + OpRegImm(kOpAnd, rl_src.reg, 0x7fffffff); + StoreValue(rl_dest, rl_src); + return true; + } + // the argument is in memory + DCHECK((rl_src.location == kLocDalvikFrame) || + (rl_src.location == kLocCompilerTemp)); + + // Operate directly into memory. + int displacement = SRegOffset(rl_dest.s_reg_low); + ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); + LIR *lir = NewLIR3(kX86And32MI, TargetReg(kSp).GetReg(), displacement, 0x7fffffff); + AnnotateDalvikRegAccess(lir, displacement >> 2, false /*is_load */, false /* is_64bit */); + AnnotateDalvikRegAccess(lir, displacement >> 2, true /* is_load */, false /* is_64bit*/); + return true; + } else { + rl_src = LoadValue(rl_src, kCoreReg); + RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); + OpRegRegImm(kOpAnd, rl_result.reg, rl_src.reg, 0x7fffffff); + StoreValue(rl_dest, rl_result); + return true; + } +} + +bool X86Mir2Lir::GenInlinedAbsDouble(CallInfo* info) { + RegLocation rl_src = info->args[0]; + RegLocation rl_dest = InlineTargetWide(info); + int v_src_reg = mir_graph_->SRegToVReg(rl_src.s_reg_low); + int v_dst_reg = mir_graph_->SRegToVReg(rl_dest.s_reg_low); + rl_src = UpdateLocWide(rl_src); + + // if argument is in the physical XMM register + if (rl_src.location == kLocPhysReg && rl_src.reg.IsFloat()) { + RegLocation rl_result = EvalLoc(rl_dest, kFPReg, true); + if (rl_result.reg != rl_src.reg) { + LoadConstantWide(rl_result.reg, 0x7fffffffffffffff); + NewLIR2(kX86PandRR, rl_result.reg.GetReg(), rl_src.reg.GetReg()); + } else { + RegStorage sign_mask = AllocTempDouble(); + LoadConstantWide(sign_mask, 0x7fffffffffffffff); + NewLIR2(kX86PandRR, rl_result.reg.GetReg(), sign_mask.GetReg()); + FreeTemp(sign_mask); + } + StoreValueWide(rl_dest, rl_result); + return true; + } else if (v_src_reg == v_dst_reg) { + // if argument is the same as inlined intrinsic target + // if argument is in the physical register + if (rl_src.location == kLocPhysReg) { + rl_src = LoadValueWide(rl_src, kCoreReg); + OpRegImm(kOpAnd, rl_src.reg.GetHigh(), 0x7fffffff); + StoreValueWide(rl_dest, rl_src); + return true; + } + // the argument is in memory + DCHECK((rl_src.location == kLocDalvikFrame) || + (rl_src.location == kLocCompilerTemp)); + + // Operate directly into memory. + int displacement = SRegOffset(rl_dest.s_reg_low); + ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); + LIR *lir = NewLIR3(kX86And32MI, TargetReg(kSp).GetReg(), displacement + HIWORD_OFFSET, 0x7fffffff); + AnnotateDalvikRegAccess(lir, (displacement + HIWORD_OFFSET) >> 2, true /* is_load */, true /* is_64bit*/); + AnnotateDalvikRegAccess(lir, (displacement + HIWORD_OFFSET) >> 2, false /*is_load */, true /* is_64bit */); + return true; + } else { + rl_src = LoadValueWide(rl_src, kCoreReg); + RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); + OpRegCopyWide(rl_result.reg, rl_src.reg); + OpRegImm(kOpAnd, rl_result.reg.GetHigh(), 0x7fffffff); + StoreValueWide(rl_dest, rl_result); + return true; + } +} } // namespace art diff --git a/compiler/dex/quick/x86/utility_x86.cc b/compiler/dex/quick/x86/utility_x86.cc index b93e3e883..46e877f8f 100644 --- a/compiler/dex/quick/x86/utility_x86.cc +++ b/compiler/dex/quick/x86/utility_x86.cc @@ -18,6 +18,8 @@ #include "dex/quick/mir_to_lir-inl.h" #include "dex/dataflow_iterator-inl.h" #include "x86_lir.h" +#include "dex/quick/dex_file_method_inliner.h" +#include "dex/quick/dex_file_to_method_inliner_map.h" namespace art { @@ -953,6 +955,9 @@ void X86Mir2Lir::AnalyzeMIR(int opcode, BasicBlock * bb, MIR *mir) { case Instruction::PACKED_SWITCH: store_method_addr_ = true; break; + case Instruction::INVOKE_STATIC: + AnalyzeInvokeStatic(opcode, bb, mir); + break; default: // Other instructions are not interesting yet. break; @@ -1020,4 +1025,22 @@ RegLocation X86Mir2Lir::UpdateLocWideTyped(RegLocation loc, int reg_class) { DCHECK(CheckCorePoolSanity()); return loc; } + +void X86Mir2Lir::AnalyzeInvokeStatic(int opcode, BasicBlock * bb, MIR *mir) { + uint32_t index = mir->dalvikInsn.vB; + if (!(mir->optimization_flags & MIR_INLINED)) { + DCHECK(cu_->compiler_driver->GetMethodInlinerMap() != nullptr); + InlineMethod method; + if (cu_->compiler_driver->GetMethodInlinerMap()->GetMethodInliner(cu_->dex_file) + ->IsIntrinsic(index, &method)) { + switch (method.opcode) { + case kIntrinsicAbsDouble: + store_method_addr_ = true; + break; + default: + break; + } + } + } +} } // namespace art -- 2.11.0