Allow X86 QBE to be extended
Enhancements and updates to allow X86Mir2LIR Backend to be subclassed
for experimentation. Add virtual in a whole bunch of places, and make
some other changes to get this to work.
Change-Id: I0980a19bc5d5725f91660f98c95f1f51c17ee9b6
Signed-off-by: Mark Mendell <mark.p.mendell@intel.com>
diff --git a/compiler/dex/quick/gen_common.cc b/compiler/dex/quick/gen_common.cc
index 350823d..de55a05 100644
--- a/compiler/dex/quick/gen_common.cc
+++ b/compiler/dex/quick/gen_common.cc
@@ -2082,6 +2082,15 @@
}
}
+void Mir2Lir::GenConst(RegLocation rl_dest, int value) {
+ RegLocation rl_result = EvalLoc(rl_dest, kAnyReg, true);
+ LoadConstantNoClobber(rl_result.reg, value);
+ StoreValue(rl_dest, rl_result);
+ if (value == 0) {
+ Workaround7250540(rl_dest, rl_result.reg);
+ }
+}
+
template <size_t pointer_size>
void Mir2Lir::GenConversionCall(ThreadOffset<pointer_size> func_offset,
RegLocation rl_dest, RegLocation rl_src) {
diff --git a/compiler/dex/quick/gen_invoke.cc b/compiler/dex/quick/gen_invoke.cc
index 3662592..721b345 100644
--- a/compiler/dex/quick/gen_invoke.cc
+++ b/compiler/dex/quick/gen_invoke.cc
@@ -1030,9 +1030,9 @@
bytes_to_move = sizeof(uint32_t) * 4;
// Allocate a free xmm temp. Since we are working through the calling sequence,
- // we expect to have an xmm temporary available.
+ // we expect to have an xmm temporary available. AllocTempDouble will abort if
+ // there are no free registers.
RegStorage temp = AllocTempDouble();
- DCHECK(temp.Valid());
LIR* ld1 = nullptr;
LIR* ld2 = nullptr;
@@ -1702,6 +1702,7 @@
const MirMethodLoweringInfo& method_info = mir_graph_->GetMethodLoweringInfo(info->mir);
cu_->compiler_driver->ProcessedInvoke(method_info.GetInvokeType(), method_info.StatsFlags());
+ BeginInvoke(info);
InvokeType original_type = static_cast<InvokeType>(method_info.GetInvokeType());
info->type = static_cast<InvokeType>(method_info.GetSharpType());
bool fast_path = method_info.FastPath();
@@ -1766,6 +1767,7 @@
}
}
}
+ EndInvoke(info);
MarkSafepointPC(call_inst);
ClobberCallerSave();
diff --git a/compiler/dex/quick/mir_to_lir-inl.h b/compiler/dex/quick/mir_to_lir-inl.h
index ba6865d..2f37520 100644
--- a/compiler/dex/quick/mir_to_lir-inl.h
+++ b/compiler/dex/quick/mir_to_lir-inl.h
@@ -149,7 +149,7 @@
/*
* Set up the proper fields in the resource mask
*/
-inline void Mir2Lir::SetupResourceMasks(LIR* lir) {
+inline void Mir2Lir::SetupResourceMasks(LIR* lir, bool leave_mem_ref) {
int opcode = lir->opcode;
if (IsPseudoLirOp(opcode)) {
@@ -170,7 +170,7 @@
lir->flags.size = GetInsnSize(lir);
estimated_native_code_size_ += lir->flags.size;
/* Set up the mask for resources that are updated */
- if (flags & (IS_LOAD | IS_STORE)) {
+ if (!leave_mem_ref && (flags & (IS_LOAD | IS_STORE))) {
/* Default to heap - will catch specialized classes later */
SetMemRefType(lir, flags & IS_LOAD, kHeapRef);
}
diff --git a/compiler/dex/quick/mir_to_lir.cc b/compiler/dex/quick/mir_to_lir.cc
index ea8071d..9fc93d0 100644
--- a/compiler/dex/quick/mir_to_lir.cc
+++ b/compiler/dex/quick/mir_to_lir.cc
@@ -425,21 +425,11 @@
case Instruction::CONST:
case Instruction::CONST_4:
case Instruction::CONST_16:
- rl_result = EvalLoc(rl_dest, kAnyReg, true);
- LoadConstantNoClobber(rl_result.reg, vB);
- StoreValue(rl_dest, rl_result);
- if (vB == 0) {
- Workaround7250540(rl_dest, rl_result.reg);
- }
+ GenConst(rl_dest, vB);
break;
case Instruction::CONST_HIGH16:
- rl_result = EvalLoc(rl_dest, kAnyReg, true);
- LoadConstantNoClobber(rl_result.reg, vB << 16);
- StoreValue(rl_dest, rl_result);
- if (vB == 0) {
- Workaround7250540(rl_dest, rl_result.reg);
- }
+ GenConst(rl_dest, vB << 16);
break;
case Instruction::CONST_WIDE_16:
diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h
index 687c41d..7f0bf30 100644
--- a/compiler/dex/quick/mir_to_lir.h
+++ b/compiler/dex/quick/mir_to_lir.h
@@ -485,6 +485,7 @@
LIRSlowPath(Mir2Lir* m2l, const DexOffset dexpc, LIR* fromfast,
LIR* cont = nullptr) :
m2l_(m2l), cu_(m2l->cu_), current_dex_pc_(dexpc), fromfast_(fromfast), cont_(cont) {
+ m2l->StartSlowPath(cont);
}
virtual ~LIRSlowPath() {}
virtual void Compile() = 0;
@@ -493,6 +494,14 @@
return arena->Alloc(size, kArenaAllocData);
}
+ LIR *GetContinuationLabel() {
+ return cont_;
+ }
+
+ LIR *GetFromFast() {
+ return fromfast_;
+ }
+
protected:
LIR* GenerateTargetLabel(int opcode = kPseudoTargetLabel);
@@ -583,7 +592,7 @@
virtual void Materialize();
virtual CompiledMethod* GetCompiledMethod();
void MarkSafepointPC(LIR* inst);
- void SetupResourceMasks(LIR* lir);
+ void SetupResourceMasks(LIR* lir, bool leave_mem_ref = false);
void SetMemRefType(LIR* lir, bool is_load, int mem_type);
void AnnotateDalvikRegAccess(LIR* lir, int reg_id, bool is_load, bool is64bit);
void SetupRegMask(uint64_t* mask, int reg);
@@ -625,6 +634,12 @@
LIR* InsertCaseLabel(DexOffset vaddr, int keyVal);
void MarkPackedCaseLabels(Mir2Lir::SwitchTable* tab_rec);
void MarkSparseCaseLabels(Mir2Lir::SwitchTable* tab_rec);
+
+ virtual void StartSlowPath(LIR *label) {}
+ virtual void BeginInvoke(CallInfo* info) {}
+ virtual void EndInvoke(CallInfo* info) {}
+
+
// Handle bookkeeping to convert a wide RegLocation to a narow RegLocation. No code generated.
RegLocation NarrowRegLoc(RegLocation loc);
@@ -632,7 +647,7 @@
void ConvertMemOpIntoMove(LIR* orig_lir, RegStorage dest, RegStorage src);
void ApplyLoadStoreElimination(LIR* head_lir, LIR* tail_lir);
void ApplyLoadHoisting(LIR* head_lir, LIR* tail_lir);
- void ApplyLocalOptimizations(LIR* head_lir, LIR* tail_lir);
+ virtual void ApplyLocalOptimizations(LIR* head_lir, LIR* tail_lir);
// Shared by all targets - implemented in ralloc_util.cc
int GetSRegHi(int lowSreg);
@@ -656,18 +671,18 @@
RegStorage AllocPreservedSingle(int s_reg);
virtual RegStorage AllocPreservedDouble(int s_reg);
RegStorage AllocTempBody(GrowableArray<RegisterInfo*> ®s, int* next_temp, bool required);
- RegStorage AllocFreeTemp();
- RegStorage AllocTemp();
- RegStorage AllocTempSingle();
- RegStorage AllocTempDouble();
+ virtual RegStorage AllocFreeTemp();
+ virtual RegStorage AllocTemp();
+ virtual RegStorage AllocTempSingle();
+ virtual RegStorage AllocTempDouble();
void FlushReg(RegStorage reg);
void FlushRegWide(RegStorage reg);
RegStorage AllocLiveReg(int s_reg, int reg_class, bool wide);
RegStorage FindLiveReg(GrowableArray<RegisterInfo*> ®s, int s_reg);
- void FreeTemp(RegStorage reg);
- void FreeRegLocTemps(RegLocation rl_keep, RegLocation rl_free);
- bool IsLive(RegStorage reg);
- bool IsTemp(RegStorage reg);
+ virtual void FreeTemp(RegStorage reg);
+ virtual void FreeRegLocTemps(RegLocation rl_keep, RegLocation rl_free);
+ virtual bool IsLive(RegStorage reg);
+ virtual bool IsTemp(RegStorage reg);
bool IsPromoted(RegStorage reg);
bool IsDirty(RegStorage reg);
void LockTemp(RegStorage reg);
@@ -675,7 +690,7 @@
void NullifyRange(RegStorage reg, int s_reg);
void MarkDef(RegLocation rl, LIR *start, LIR *finish);
void MarkDefWide(RegLocation rl, LIR *start, LIR *finish);
- RegLocation WideToNarrow(RegLocation rl);
+ virtual RegLocation WideToNarrow(RegLocation rl);
void ResetDefLoc(RegLocation rl);
void ResetDefLocWide(RegLocation rl);
void ResetDefTracking();
@@ -692,8 +707,8 @@
void MarkDirty(RegLocation loc);
void MarkInUse(RegStorage reg);
bool CheckCorePoolSanity();
- RegLocation UpdateLoc(RegLocation loc);
- RegLocation UpdateLocWide(RegLocation loc);
+ virtual RegLocation UpdateLoc(RegLocation loc);
+ virtual RegLocation UpdateLocWide(RegLocation loc);
RegLocation UpdateRawLoc(RegLocation loc);
/**
@@ -704,7 +719,7 @@
* @param update Whether the liveness information should be updated.
* @return Returns the properly typed temporary in physical register pairs.
*/
- RegLocation EvalLocWide(RegLocation loc, int reg_class, bool update);
+ virtual RegLocation EvalLocWide(RegLocation loc, int reg_class, bool update);
/**
* @brief Used to prepare a register location to receive a value.
@@ -713,7 +728,7 @@
* @param update Whether the liveness information should be updated.
* @return Returns the properly typed temporary in physical register.
*/
- RegLocation EvalLoc(RegLocation loc, int reg_class, bool update);
+ virtual RegLocation EvalLoc(RegLocation loc, int reg_class, bool update);
void CountRefs(RefCounts* core_counts, RefCounts* fp_counts, size_t num_regs);
void DumpCounts(const RefCounts* arr, int size, const char* msg);
@@ -729,7 +744,7 @@
bool HandleEasyDivRem(Instruction::Code dalvik_opcode, bool is_div,
RegLocation rl_src, RegLocation rl_dest, int lit);
bool HandleEasyMultiply(RegLocation rl_src, RegLocation rl_dest, int lit);
- void HandleSlowPaths();
+ virtual void HandleSlowPaths();
void GenBarrier();
void GenDivZeroException();
// c_code holds condition code that's generated from testing divisor against 0.
@@ -783,8 +798,8 @@
template <size_t pointer_size>
void GenConversionCall(ThreadOffset<pointer_size> func_offset, RegLocation rl_dest,
RegLocation rl_src);
- void GenSuspendTest(int opt_flags);
- void GenSuspendTestAndBranch(int opt_flags, LIR* target);
+ virtual void GenSuspendTest(int opt_flags);
+ virtual void GenSuspendTestAndBranch(int opt_flags, LIR* target);
// This will be overridden by x86 implementation.
virtual void GenConstWide(RegLocation rl_dest, int64_t value);
@@ -914,41 +929,41 @@
// Shared by all targets - implemented in gen_loadstore.cc.
RegLocation LoadCurrMethod();
void LoadCurrMethodDirect(RegStorage r_tgt);
- LIR* LoadConstant(RegStorage r_dest, int value);
+ virtual LIR* LoadConstant(RegStorage r_dest, int value);
// Natural word size.
- LIR* LoadWordDisp(RegStorage r_base, int displacement, RegStorage r_dest) {
+ virtual LIR* LoadWordDisp(RegStorage r_base, int displacement, RegStorage r_dest) {
return LoadBaseDisp(r_base, displacement, r_dest, kWord);
}
// Load 32 bits, regardless of target.
- LIR* Load32Disp(RegStorage r_base, int displacement, RegStorage r_dest) {
+ virtual LIR* Load32Disp(RegStorage r_base, int displacement, RegStorage r_dest) {
return LoadBaseDisp(r_base, displacement, r_dest, k32);
}
// Load a reference at base + displacement and decompress into register.
- LIR* LoadRefDisp(RegStorage r_base, int displacement, RegStorage r_dest) {
+ virtual LIR* LoadRefDisp(RegStorage r_base, int displacement, RegStorage r_dest) {
return LoadBaseDisp(r_base, displacement, r_dest, kReference);
}
// Load Dalvik value with 32-bit memory storage. If compressed object reference, decompress.
- RegLocation LoadValue(RegLocation rl_src, RegisterClass op_kind);
+ virtual RegLocation LoadValue(RegLocation rl_src, RegisterClass op_kind);
// Load Dalvik value with 64-bit memory storage.
- RegLocation LoadValueWide(RegLocation rl_src, RegisterClass op_kind);
+ virtual RegLocation LoadValueWide(RegLocation rl_src, RegisterClass op_kind);
// Load Dalvik value with 32-bit memory storage. If compressed object reference, decompress.
- void LoadValueDirect(RegLocation rl_src, RegStorage r_dest);
+ virtual void LoadValueDirect(RegLocation rl_src, RegStorage r_dest);
// Load Dalvik value with 32-bit memory storage. If compressed object reference, decompress.
- void LoadValueDirectFixed(RegLocation rl_src, RegStorage r_dest);
+ virtual void LoadValueDirectFixed(RegLocation rl_src, RegStorage r_dest);
// Load Dalvik value with 64-bit memory storage.
- void LoadValueDirectWide(RegLocation rl_src, RegStorage r_dest);
+ virtual void LoadValueDirectWide(RegLocation rl_src, RegStorage r_dest);
// Load Dalvik value with 64-bit memory storage.
- void LoadValueDirectWideFixed(RegLocation rl_src, RegStorage r_dest);
+ virtual void LoadValueDirectWideFixed(RegLocation rl_src, RegStorage r_dest);
// Store an item of natural word size.
- LIR* StoreWordDisp(RegStorage r_base, int displacement, RegStorage r_src) {
+ virtual LIR* StoreWordDisp(RegStorage r_base, int displacement, RegStorage r_src) {
return StoreBaseDisp(r_base, displacement, r_src, kWord);
}
// Store an uncompressed reference into a compressed 32-bit container.
- LIR* StoreRefDisp(RegStorage r_base, int displacement, RegStorage r_src) {
+ virtual LIR* StoreRefDisp(RegStorage r_base, int displacement, RegStorage r_src) {
return StoreBaseDisp(r_base, displacement, r_src, kReference);
}
// Store 32 bits, regardless of target.
- LIR* Store32Disp(RegStorage r_base, int displacement, RegStorage r_src) {
+ virtual LIR* Store32Disp(RegStorage r_base, int displacement, RegStorage r_src) {
return StoreBaseDisp(r_base, displacement, r_src, k32);
}
@@ -957,7 +972,7 @@
* @param rl_dest The destination dalvik register location.
* @param rl_src The source register location. Can be either physical register or dalvik register.
*/
- void StoreValue(RegLocation rl_dest, RegLocation rl_src);
+ virtual void StoreValue(RegLocation rl_dest, RegLocation rl_src);
/**
* @brief Used to do the final store in a wide destination as per bytecode semantics.
@@ -966,7 +981,7 @@
* @param rl_src The source register location. Can be either physical register or dalvik
* register.
*/
- void StoreValueWide(RegLocation rl_dest, RegLocation rl_src);
+ virtual void StoreValueWide(RegLocation rl_dest, RegLocation rl_src);
/**
* @brief Used to do the final store to a destination as per bytecode semantics.
@@ -978,7 +993,7 @@
* register value that now needs to be properly registered. This is used to avoid an
* extra register copy that would result if StoreValue was called.
*/
- void StoreFinalValue(RegLocation rl_dest, RegLocation rl_src);
+ virtual void StoreFinalValue(RegLocation rl_dest, RegLocation rl_src);
/**
* @brief Used to do the final store in a wide destination as per bytecode semantics.
@@ -990,14 +1005,14 @@
* register values that now need to be properly registered. This is used to avoid an
* extra pair of register copies that would result if StoreValueWide was called.
*/
- void StoreFinalValueWide(RegLocation rl_dest, RegLocation rl_src);
+ virtual void StoreFinalValueWide(RegLocation rl_dest, RegLocation rl_src);
// Shared by all targets - implemented in mir_to_lir.cc.
void CompileDalvikInstruction(MIR* mir, BasicBlock* bb, LIR* label_list);
- void HandleExtendedMethodMIR(BasicBlock* bb, MIR* mir);
+ virtual void HandleExtendedMethodMIR(BasicBlock* bb, MIR* mir);
bool MethodBlockCodeGen(BasicBlock* bb);
bool SpecialMIR2LIR(const InlineMethod& special);
- void MethodMIR2LIR();
+ virtual void MethodMIR2LIR();
// Update LIR for verbose listings.
void UpdateLIROffsets();
@@ -1345,14 +1360,14 @@
* @param loc location of result
* @returns update location
*/
- RegLocation ForceTemp(RegLocation loc);
+ virtual RegLocation ForceTemp(RegLocation loc);
/*
* @brief Force a wide location (in registers) into temporary registers
* @param loc location of result
* @returns update location
*/
- RegLocation ForceTempWide(RegLocation loc);
+ virtual RegLocation ForceTempWide(RegLocation loc);
static constexpr OpSize LoadStoreOpSize(bool wide, bool ref) {
return wide ? k64 : ref ? kReference : k32;
@@ -1398,7 +1413,7 @@
*/
virtual bool GenSpecialCase(BasicBlock* bb, MIR* mir, const InlineMethod& special);
- private:
+ protected:
void ClobberBody(RegisterInfo* p);
void SetCurrentDexPc(DexOffset dexpc) {
current_dalvik_offset_ = dexpc;
@@ -1457,7 +1472,14 @@
// Copy arg0 and arg1 to kArg0 and kArg1 safely, possibly using
// kArg2 as temp.
- void CopyToArgumentRegs(RegStorage arg0, RegStorage arg1);
+ virtual void CopyToArgumentRegs(RegStorage arg0, RegStorage arg1);
+
+ /**
+ * @brief Load Constant into RegLocation
+ * @param rl_dest Destination RegLocation
+ * @param value Constant value
+ */
+ virtual void GenConst(RegLocation rl_dest, int value);
public:
// TODO: add accessors for these.
diff --git a/compiler/dex/quick/x86/codegen_x86.h b/compiler/dex/quick/x86/codegen_x86.h
index 52c870b..e717638 100644
--- a/compiler/dex/quick/x86/codegen_x86.h
+++ b/compiler/dex/quick/x86/codegen_x86.h
@@ -22,7 +22,7 @@
namespace art {
-class X86Mir2Lir FINAL : public Mir2Lir {
+class X86Mir2Lir : public Mir2Lir {
public:
X86Mir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena, bool gen64bit);
@@ -175,8 +175,8 @@
* @param op The DEX opcode for the operation.
* @param is_commutative The sources can be swapped if needed.
*/
- void GenLongArith(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2,
- Instruction::Code op, bool is_commutative);
+ virtual void GenLongArith(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2,
+ Instruction::Code op, bool is_commutative);
/**
* @brief Generate a two operand long arithmetic operation.
@@ -192,7 +192,7 @@
* @param rl_src The other operand. May be in a register or in memory.
* @param op The DEX opcode for the operation.
*/
- void GenLongRegOrMemOp(RegLocation rl_dest, RegLocation rl_src, Instruction::Code op);
+ virtual void GenLongRegOrMemOp(RegLocation rl_dest, RegLocation rl_src, Instruction::Code op);
/**
* @brief Implement instanceof a final class with x86 specific code.
@@ -265,6 +265,12 @@
bool InexpensiveConstantDouble(int64_t value);
/*
+ * @brief Should try to optimize for two address instructions?
+ * @return true if we try to avoid generating three operand instructions.
+ */
+ virtual bool GenerateTwoOperandInstructions() const { return true; }
+
+ /*
* @brief x86 specific codegen for int operations.
* @param opcode Operation to perform.
* @param rl_dest Destination for the result.
@@ -304,7 +310,7 @@
* @param type How the method will be invoked.
* @returns Call instruction
*/
- LIR * CallWithLinkerFixup(const MethodReference& target_method, InvokeType type);
+ virtual LIR * CallWithLinkerFixup(const MethodReference& target_method, InvokeType type);
/*
* @brief Handle x86 specific literals
@@ -323,7 +329,7 @@
*/
std::vector<uint8_t>* ReturnCallFrameInformation();
- private:
+ protected:
size_t ComputeSize(const X86EncodingMap* entry, int base, int displacement, bool has_sib);
void EmitPrefix(const X86EncodingMap* entry);
void EmitOpcode(const X86EncodingMap* entry);
@@ -398,6 +404,12 @@
static bool ProvidesFullMemoryBarrier(X86OpCode opcode);
/*
+ * @brief Ensure that a temporary register is byte addressable.
+ * @returns a temporary guarenteed to be byte addressable.
+ */
+ virtual RegStorage AllocateByteRegister();
+
+ /*
* @brief generate inline code for fast case of Strng.indexOf.
* @param info Call parameters
* @param zero_based 'true' if the index into the string is 0.
@@ -533,7 +545,7 @@
* @param rl_src The source of the long.
* @param is_double 'true' if dealing with double, 'false' for float.
*/
- void GenLongToFP(RegLocation rl_dest, RegLocation rl_src, bool is_double);
+ virtual void GenLongToFP(RegLocation rl_dest, RegLocation rl_src, bool is_double);
/*
* @brief Perform MIR analysis before compiling method.
@@ -579,7 +591,7 @@
* @param bb Basic block containing instruction.
* @param mir Instruction to analyze.
*/
- void AnalyzeMIR(int opcode, BasicBlock * bb, MIR *mir);
+ virtual void AnalyzeMIR(int opcode, BasicBlock * bb, MIR *mir);
/*
* @brief Analyze one MIR float/double instruction
diff --git a/compiler/dex/quick/x86/int_x86.cc b/compiler/dex/quick/x86/int_x86.cc
index 71a3962..a6ccc99 100644
--- a/compiler/dex/quick/x86/int_x86.cc
+++ b/compiler/dex/quick/x86/int_x86.cc
@@ -1292,8 +1292,12 @@
case Instruction::AND_LONG_2ADDR:
case Instruction::OR_LONG_2ADDR:
case Instruction::XOR_LONG_2ADDR:
- GenLongArith(rl_dest, rl_src2, op);
- return;
+ if (GenerateTwoOperandInstructions()) {
+ GenLongArith(rl_dest, rl_src2, op);
+ return;
+ }
+ break;
+
default:
break;
}
@@ -1532,7 +1536,7 @@
RegLocation X86Mir2Lir::GenShiftImmOpLong(Instruction::Code opcode, RegLocation rl_dest,
RegLocation rl_src, int shift_amount) {
- RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
+ RegLocation rl_result = EvalLocWide(rl_dest, kCoreReg, true);
switch (opcode) {
case Instruction::SHL_LONG:
case Instruction::SHL_LONG_2ADDR:
@@ -1641,7 +1645,11 @@
case Instruction::XOR_LONG_2ADDR:
case Instruction::AND_LONG_2ADDR:
if (rl_src2.is_const) {
- GenLongImm(rl_dest, rl_src2, opcode);
+ if (GenerateTwoOperandInstructions()) {
+ GenLongImm(rl_dest, rl_src2, opcode);
+ } else {
+ GenLongLongImm(rl_dest, rl_src1, rl_src2, opcode);
+ }
} else {
DCHECK(rl_src1.is_const);
GenLongLongImm(rl_dest, rl_src2, rl_src1, opcode);
@@ -1869,7 +1877,7 @@
// SETcc only works with EAX..EDX.
if (result_reg == object.reg || result_reg.GetRegNum() >= rs_rX86_SP.GetRegNum()) {
- result_reg = AllocTypedTemp(false, kCoreReg);
+ result_reg = AllocateByteRegister();
DCHECK_LT(result_reg.GetRegNum(), rs_rX86_SP.GetRegNum());
}
@@ -2110,12 +2118,16 @@
LOG(FATAL) << "Invalid word arith op: " << opcode;
}
- // Can we convert to a two address instruction?
+ // Can we convert to a two address instruction?
if (!is_two_addr &&
(mir_graph_->SRegToVReg(rl_dest.s_reg_low) ==
mir_graph_->SRegToVReg(rl_lhs.s_reg_low))) {
- is_two_addr = true;
- }
+ is_two_addr = true;
+ }
+
+ if (!GenerateTwoOperandInstructions()) {
+ is_two_addr = false;
+ }
// Get the div/rem stuff out of the way.
if (is_div_rem) {
@@ -2212,6 +2224,8 @@
if (mir_graph_->SRegToVReg(rl_dest.s_reg_low) == mir_graph_->SRegToVReg(rl_lhs.s_reg_low)) {
rl_lhs = LoadValue(rl_lhs, kCoreReg);
rl_result = EvalLoc(rl_dest, kCoreReg, true);
+ // No-op if these are the same.
+ OpRegCopy(rl_result.reg, rl_lhs.reg);
} else {
rl_result = EvalLoc(rl_dest, kCoreReg, true);
LoadValueDirect(rl_lhs, rl_result.reg);
diff --git a/compiler/dex/quick/x86/target_x86.cc b/compiler/dex/quick/x86/target_x86.cc
index 8f06791..9ddeb68 100644
--- a/compiler/dex/quick/x86/target_x86.cc
+++ b/compiler/dex/quick/x86/target_x86.cc
@@ -423,6 +423,10 @@
UNIMPLEMENTED(FATAL) << "MarkPreservedDouble";
}
+RegStorage X86Mir2Lir::AllocateByteRegister() {
+ return AllocTypedTemp(false, kCoreReg);
+}
+
/* Clobber all regs that might be used by an external C call */
void X86Mir2Lir::ClobberCallerSave() {
Clobber(rs_rAX);
diff --git a/compiler/dex/quick/x86/utility_x86.cc b/compiler/dex/quick/x86/utility_x86.cc
index e9592a6..fed31c1 100644
--- a/compiler/dex/quick/x86/utility_x86.cc
+++ b/compiler/dex/quick/x86/utility_x86.cc
@@ -161,6 +161,22 @@
case kOpMul:
opcode = byte_imm ? kX86Imul32RRI8 : kX86Imul32RRI;
return NewLIR3(opcode, r_dest_src1.GetReg(), r_dest_src1.GetReg(), value);
+ case kOp2Byte:
+ opcode = kX86Mov32RI;
+ value = static_cast<int8_t>(value);
+ break;
+ case kOp2Short:
+ opcode = kX86Mov32RI;
+ value = static_cast<int16_t>(value);
+ break;
+ case kOp2Char:
+ opcode = kX86Mov32RI;
+ value = static_cast<uint16_t>(value);
+ break;
+ case kOpNeg:
+ opcode = kX86Mov32RI;
+ value = -value;
+ break;
default:
LOG(FATAL) << "Bad case in OpRegImm " << op;
}
@@ -523,7 +539,7 @@
int32_t val_hi = High32Bits(value);
int32_t low_reg_val = r_dest.IsPair() ? r_dest.GetLowReg() : r_dest.GetReg();
LIR *res;
- bool is_fp = RegStorage::IsFloat(low_reg_val);
+ bool is_fp = r_dest.IsFloat();
// TODO: clean this up once we fully recognize 64-bit storage containers.
if (is_fp) {
if (value == 0) {