GenSpecialCase support for x86
Moved GenSpecialCase from being ARM specific to common code to allow
it to be used by x86 quick as well.
Change-Id: I728733e8f4c4da99af6091ef77e5c76ae0fee850
Signed-off-by: Razvan A Lupusoru <razvan.a.lupusoru@intel.com>
diff --git a/compiler/dex/quick/arm/call_arm.cc b/compiler/dex/quick/arm/call_arm.cc
index a30e80a..b36dde9 100644
--- a/compiler/dex/quick/arm/call_arm.cc
+++ b/compiler/dex/quick/arm/call_arm.cc
@@ -18,225 +18,11 @@
#include "arm_lir.h"
#include "codegen_arm.h"
-#include "dex/quick/dex_file_method_inliner.h"
#include "dex/quick/mir_to_lir-inl.h"
#include "entrypoints/quick/quick_entrypoints.h"
namespace art {
-// TODO: generalize & move to RegUtil.cc
-// The number of dalvik registers passed in core registers.
-constexpr int kInArgsInCoreRegs = 3;
-// The core register corresponding to the first (index 0) input argument.
-constexpr int kInArg0CoreReg = r1; // r0 is Method*.
-// Offset, in words, for getting args from stack (even core reg args have space on stack).
-constexpr int kInArgToStackOffset = 1;
-
-/* Lock argument if it's in register. */
-void ArmMir2Lir::LockArg(int in_position, bool wide) {
- if (in_position < kInArgsInCoreRegs) {
- LockTemp(kInArg0CoreReg + in_position);
- }
- if (wide && in_position + 1 < kInArgsInCoreRegs) {
- LockTemp(kInArg0CoreReg + in_position + 1);
- }
-}
-
-/* Load argument into register. LockArg(in_position, wide) must have been previously called. */
-int ArmMir2Lir::LoadArg(int in_position, bool wide) {
- if (in_position < kInArgsInCoreRegs) {
- int low_reg = kInArg0CoreReg + in_position;
- if (!wide) {
- return low_reg;
- }
- int high_reg = (in_position != kInArgsInCoreRegs - 1) ? low_reg + 1 : LoadArg(in_position + 1);
- return (low_reg & 0xff) | ((high_reg & 0xff) << 8);
- }
- int low_reg = AllocTemp();
- int offset = (in_position + kInArgToStackOffset) * sizeof(uint32_t);
- if (!wide) {
- LoadWordDisp(rARM_SP, offset, low_reg);
- return low_reg;
- }
- int high_reg = AllocTemp();
- LoadBaseDispWide(rARM_SP, offset, low_reg, high_reg, INVALID_SREG);
- return (low_reg & 0xff) | ((high_reg & 0xff) << 8);
-}
-
-void ArmMir2Lir::LoadArgDirect(int in_position, RegLocation rl_dest) {
- int reg = kInArg0CoreReg + in_position;
- int offset = (in_position + kInArgToStackOffset) * sizeof(uint32_t);
- if (!rl_dest.wide) {
- if (in_position < kInArgsInCoreRegs) {
- OpRegCopy(rl_dest.low_reg, reg);
- } else {
- LoadWordDisp(rARM_SP, offset, rl_dest.low_reg);
- }
- } else {
- if (in_position < kInArgsInCoreRegs - 1) {
- OpRegCopyWide(rl_dest.low_reg, rl_dest.high_reg, reg, reg + 1);
- } else if (in_position == kInArgsInCoreRegs - 1) {
- OpRegCopy(rl_dest.low_reg, reg);
- LoadWordDisp(rARM_SP, offset + sizeof(uint32_t), rl_dest.high_reg);
- } else {
- LoadBaseDispWide(rARM_SP, offset, rl_dest.low_reg, rl_dest.high_reg, INVALID_SREG);
- }
- }
-}
-
-/* Find the next MIR, which may be in a following basic block */
-// TODO: make this a utility in mir_graph.
-MIR* ArmMir2Lir::GetNextMir(BasicBlock** p_bb, MIR* mir) {
- BasicBlock* bb = *p_bb;
- MIR* orig_mir = mir;
- while (bb != NULL) {
- if (mir != NULL) {
- mir = mir->next;
- }
- if (mir != NULL) {
- return mir;
- } else {
- bb = mir_graph_->GetBasicBlock(bb->fall_through);
- *p_bb = bb;
- if (bb) {
- mir = bb->first_mir_insn;
- if (mir != NULL) {
- return mir;
- }
- }
- }
- }
- return orig_mir;
-}
-
-/* Used for the "verbose" listing */
-// TODO: move to common code
-void ArmMir2Lir::GenPrintLabel(MIR* mir) {
- /* Mark the beginning of a Dalvik instruction for line tracking */
- if (cu_->verbose) {
- char* inst_str = mir_graph_->GetDalvikDisassembly(mir);
- MarkBoundary(mir->offset, inst_str);
- }
-}
-
-MIR* ArmMir2Lir::SpecialIGet(BasicBlock** bb, MIR* mir, const InlineMethod& special) {
- // FastInstance() already checked by DexFileMethodInliner.
- const InlineIGetIPutData& data = special.d.ifield_data;
- if (data.method_is_static || data.object_arg != 0) {
- return NULL; // The object is not "this" and has to be null-checked.
- }
-
- DCHECK_NE(data.op_size, kDouble); // The inliner doesn't distinguish kDouble, uses kLong.
- bool wide = (data.op_size == kLong);
-
- // Point of no return - no aborts after this
- ArmMir2Lir::GenPrintLabel(mir);
- LockArg(data.object_arg);
- RegLocation rl_dest = wide ? GetReturnWide(false) : GetReturn(false);
- int reg_obj = LoadArg(data.object_arg);
- if (wide) {
- LoadBaseDispWide(reg_obj, data.field_offset, rl_dest.low_reg, rl_dest.high_reg, INVALID_SREG);
- } else {
- LoadBaseDisp(reg_obj, data.field_offset, rl_dest.low_reg, kWord, INVALID_SREG);
- }
- if (data.is_volatile) {
- GenMemBarrier(kLoadLoad);
- }
- return GetNextMir(bb, mir);
-}
-
-MIR* ArmMir2Lir::SpecialIPut(BasicBlock** bb, MIR* mir, const InlineMethod& special) {
- // FastInstance() already checked by DexFileMethodInliner.
- const InlineIGetIPutData& data = special.d.ifield_data;
- if (data.method_is_static || data.object_arg != 0) {
- return NULL; // The object is not "this" and has to be null-checked.
- }
-
- DCHECK_NE(data.op_size, kDouble); // The inliner doesn't distinguish kDouble, uses kLong.
- bool wide = (data.op_size == kLong);
-
- // Point of no return - no aborts after this
- ArmMir2Lir::GenPrintLabel(mir);
- LockArg(data.object_arg);
- LockArg(data.src_arg, wide);
- int reg_obj = LoadArg(data.object_arg);
- int reg_src = LoadArg(data.src_arg, wide);
- if (data.is_volatile) {
- GenMemBarrier(kStoreStore);
- }
- if (wide) {
- StoreBaseDispWide(reg_obj, data.field_offset, reg_src & 0xff, reg_src >> 8);
- } else {
- StoreBaseDisp(reg_obj, data.field_offset, reg_src, kWord);
- }
- if (data.is_volatile) {
- GenMemBarrier(kLoadLoad);
- }
- if (data.is_object) {
- MarkGCCard(reg_src, reg_obj);
- }
- return GetNextMir(bb, mir);
-}
-
-MIR* ArmMir2Lir::SpecialIdentity(MIR* mir, const InlineMethod& special) {
- const InlineReturnArgData& data = special.d.return_data;
- DCHECK_NE(data.op_size, kDouble); // The inliner doesn't distinguish kDouble, uses kLong.
- bool wide = (data.op_size == kLong);
-
- // Point of no return - no aborts after this
- ArmMir2Lir::GenPrintLabel(mir);
- LockArg(data.arg, wide);
- RegLocation rl_dest = wide ? GetReturnWide(false) : GetReturn(false);
- LoadArgDirect(data.arg, rl_dest);
- return mir;
-}
-
-/*
- * Special-case code genration for simple non-throwing leaf methods.
- */
-void ArmMir2Lir::GenSpecialCase(BasicBlock* bb, MIR* mir,
- const InlineMethod& special) {
- DCHECK(special.flags & kInlineSpecial);
- current_dalvik_offset_ = mir->offset;
- MIR* next_mir = NULL;
- switch (special.opcode) {
- case kInlineOpNop:
- DCHECK(mir->dalvikInsn.opcode == Instruction::RETURN_VOID);
- next_mir = mir;
- break;
- case kInlineOpConst:
- ArmMir2Lir::GenPrintLabel(mir);
- LoadConstant(rARM_RET0, static_cast<int>(special.d.data));
- next_mir = GetNextMir(&bb, mir);
- break;
- case kInlineOpIGet:
- next_mir = SpecialIGet(&bb, mir, special);
- break;
- case kInlineOpIPut:
- next_mir = SpecialIPut(&bb, mir, special);
- break;
- case kInlineOpReturnArg:
- next_mir = SpecialIdentity(mir, special);
- break;
- default:
- return;
- }
- if (next_mir != NULL) {
- current_dalvik_offset_ = next_mir->offset;
- if (special.opcode != kInlineOpReturnArg) {
- ArmMir2Lir::GenPrintLabel(next_mir);
- }
- NewLIR1(kThumbBx, rARM_LR);
- core_spill_mask_ = 0;
- num_core_spills_ = 0;
- fp_spill_mask_ = 0;
- num_fp_spills_ = 0;
- frame_size_ = 0;
- core_vmap_table_.clear();
- fp_vmap_table_.clear();
- }
-}
-
/*
* The sparse table in the literal pool is an array of <key,displacement>
* pairs. For each set, we'll load them as a pair using ldmia.
@@ -610,4 +396,8 @@
}
}
+void ArmMir2Lir::GenSpecialExitSequence() {
+ NewLIR1(kThumbBx, rARM_LR);
+}
+
} // namespace art
diff --git a/compiler/dex/quick/arm/codegen_arm.h b/compiler/dex/quick/arm/codegen_arm.h
index 7ee241c..65dee80 100644
--- a/compiler/dex/quick/arm/codegen_arm.h
+++ b/compiler/dex/quick/arm/codegen_arm.h
@@ -52,6 +52,7 @@
int AllocTypedTempPair(bool fp_hint, int reg_class);
int S2d(int low_reg, int high_reg);
int TargetReg(SpecialTargetRegister reg);
+ int GetArgMappingToPhysicalReg(int arg_num);
RegLocation GetReturnAlt();
RegLocation GetReturnWideAlt();
RegLocation LocCReturn();
@@ -122,6 +123,7 @@
void GenDivZeroCheck(int reg_lo, int reg_hi);
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);
@@ -136,7 +138,6 @@
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);
- void GenSpecialCase(BasicBlock* bb, MIR* mir, const InlineMethod& special);
// Required for target - single operation generators.
LIR* OpUnconditionalBranch(LIR* target);
@@ -170,7 +171,6 @@
LIR* LoadBaseDispBody(int rBase, int displacement, int r_dest, int r_dest_hi, OpSize size,
int s_reg);
LIR* StoreBaseDispBody(int rBase, int displacement, int r_src, int r_src_hi, OpSize size);
- void GenPrintLabel(MIR* mir);
LIR* OpRegRegRegShift(OpKind op, int r_dest, int r_src1, int r_src2, int shift);
LIR* OpRegRegShift(OpKind op, int r_dest_src1, int r_src2, int shift);
static const ArmEncodingMap EncodingMap[kArmLast];
@@ -185,13 +185,6 @@
private:
void GenFusedLongCmpImmBranch(BasicBlock* bb, RegLocation rl_src1, int64_t val,
ConditionCode ccode);
- void LockArg(int in_position, bool wide = false);
- int LoadArg(int in_position, bool wide = false);
- void LoadArgDirect(int in_position, RegLocation rl_dest);
- MIR* GetNextMir(BasicBlock** p_bb, MIR* mir);
- MIR* SpecialIGet(BasicBlock** bb, MIR* mir, const InlineMethod& special);
- MIR* SpecialIPut(BasicBlock** bb, MIR* mir, const InlineMethod& special);
- MIR* SpecialIdentity(MIR* mir, const InlineMethod& special);
LIR* LoadFPConstantValue(int r_dest, int value);
void ReplaceFixup(LIR* prev_lir, LIR* orig_lir, LIR* new_lir);
void InsertFixupBefore(LIR* prev_lir, LIR* orig_lir, LIR* new_lir);
diff --git a/compiler/dex/quick/arm/target_arm.cc b/compiler/dex/quick/arm/target_arm.cc
index ceec7d5..83431ad 100644
--- a/compiler/dex/quick/arm/target_arm.cc
+++ b/compiler/dex/quick/arm/target_arm.cc
@@ -83,6 +83,19 @@
return res;
}
+int ArmMir2Lir::GetArgMappingToPhysicalReg(int arg_num) {
+ // For the 32-bit internal ABI, the first 3 arguments are passed in registers.
+ switch (arg_num) {
+ case 0:
+ return rARM_ARG1;
+ case 1:
+ return rARM_ARG2;
+ case 2:
+ return rARM_ARG3;
+ default:
+ return INVALID_REG;
+ }
+}
// Create a double from a pair of singles.
int ArmMir2Lir::S2d(int low_reg, int high_reg) {