diff options
| -rw-r--r-- | src/compiler/codegen/arm/utility_arm.cc | 52 | ||||
| -rw-r--r-- | src/compiler/codegen/gen_loadstore.cc | 21 | ||||
| -rw-r--r-- | src/compiler/codegen/mir_to_gbc.cc | 7 | ||||
| -rw-r--r-- | src/compiler/codegen/mir_to_lir.cc | 8 |
4 files changed, 61 insertions, 27 deletions
diff --git a/src/compiler/codegen/arm/utility_arm.cc b/src/compiler/codegen/arm/utility_arm.cc index d1bf14ec53..7f37bea1af 100644 --- a/src/compiler/codegen/arm/utility_arm.cc +++ b/src/compiler/codegen/arm/utility_arm.cc @@ -47,10 +47,19 @@ static int EncodeImmSingle(int value) static LIR* LoadFPConstantValue(CompilationUnit* cu, int r_dest, int value) { - int encoded_imm = EncodeImmSingle(value); DCHECK(ARM_SINGLEREG(r_dest)); - if (encoded_imm >= 0) { - return NewLIR2(cu, kThumb2Vmovs_IMM8, r_dest, encoded_imm); + if (value == 0) { + // TODO: we need better info about the target CPU. a vector exclusive or + // would probably be better here if we could rely on its existance. + // Load an immediate +2.0 (which encodes to 0) + NewLIR2(cu, kThumb2Vmovs_IMM8, r_dest, 0); + // +0.0 = +2.0 - +2.0 + return NewLIR3(cu, kThumb2Vsubs, r_dest, r_dest, r_dest); + } else { + int encoded_imm = EncodeImmSingle(value); + if (encoded_imm >= 0) { + return NewLIR2(cu, kThumb2Vmovs_IMM8, r_dest, encoded_imm); + } } LIR* data_target = ScanLiteralPool(cu->literal_list, value, 0); if (data_target == NULL) { @@ -600,24 +609,33 @@ static int EncodeImmDouble(int val_lo, int val_hi) LIR* ArmCodegen::LoadConstantValueWide(CompilationUnit* cu, int r_dest_lo, int r_dest_hi, int val_lo, int val_hi) { - int encoded_imm = EncodeImmDouble(val_lo, val_hi); LIR* res; + int target_reg = S2d(r_dest_lo, r_dest_hi); if (ARM_FPREG(r_dest_lo)) { - if (encoded_imm >= 0) { - res = NewLIR2(cu, kThumb2Vmovd_IMM8, S2d(r_dest_lo, r_dest_hi), - encoded_imm); + if ((val_lo == 0) && (val_hi == 0)) { + // TODO: we need better info about the target CPU. a vector exclusive or + // would probably be better here if we could rely on its existance. + // Load an immediate +2.0 (which encodes to 0) + NewLIR2(cu, kThumb2Vmovd_IMM8, target_reg, 0); + // +0.0 = +2.0 - +2.0 + res = NewLIR3(cu, kThumb2Vsubd, target_reg, target_reg, target_reg); } else { - LIR* data_target = ScanLiteralPoolWide(cu->literal_list, val_lo, val_hi); - if (data_target == NULL) { - data_target = AddWideData(cu, &cu->literal_list, val_lo, val_hi); + int encoded_imm = EncodeImmDouble(val_lo, val_hi); + if (encoded_imm >= 0) { + res = NewLIR2(cu, kThumb2Vmovd_IMM8, target_reg, encoded_imm); + } else { + LIR* data_target = ScanLiteralPoolWide(cu->literal_list, val_lo, val_hi); + if (data_target == NULL) { + data_target = AddWideData(cu, &cu->literal_list, val_lo, val_hi); + } + LIR* load_pc_rel = + RawLIR(cu, cu->current_dalvik_offset, kThumb2Vldrd, + target_reg, r15pc, 0, 0, 0, data_target); + SetMemRefType(cu, load_pc_rel, true, kLiteral); + load_pc_rel->alias_info = reinterpret_cast<uintptr_t>(data_target); + AppendLIR(cu, load_pc_rel); + res = load_pc_rel; } - LIR* load_pc_rel = - RawLIR(cu, cu->current_dalvik_offset, kThumb2Vldrd, - S2d(r_dest_lo, r_dest_hi), r15pc, 0, 0, 0, data_target); - SetMemRefType(cu, load_pc_rel, true, kLiteral); - load_pc_rel->alias_info = reinterpret_cast<uintptr_t>(data_target); - AppendLIR(cu, load_pc_rel); - res = load_pc_rel; } } else { res = LoadConstantNoClobber(cu, r_dest_lo, val_lo); diff --git a/src/compiler/codegen/gen_loadstore.cc b/src/compiler/codegen/gen_loadstore.cc index 11b4a62469..fe08caa72c 100644 --- a/src/compiler/codegen/gen_loadstore.cc +++ b/src/compiler/codegen/gen_loadstore.cc @@ -40,19 +40,28 @@ LIR* Codegen::LoadConstant(CompilationUnit* cu, int r_dest, int value) * promoted floating point register, also copy a zero into the int/ref identity of * that sreg. */ -void Codegen::Workaround7250540(CompilationUnit* cu, RegLocation rl_dest, int value) +void Codegen::Workaround7250540(CompilationUnit* cu, RegLocation rl_dest, int zero_reg) { - if (rl_dest.fp && (value == 0)) { + if (rl_dest.fp) { int pmap_index = SRegToPMap(cu, rl_dest.s_reg_low); if (cu->promotion_map[pmap_index].fp_location == kLocPhysReg) { + // Now, determine if this vreg is ever used as a reference. If not, we're done. + bool used_as_reference = false; + int base_vreg = SRegToVReg(cu, rl_dest.s_reg_low); + for (int i = 0; !used_as_reference && (i < cu->num_ssa_regs); i++) { + if (SRegToVReg(cu, cu->reg_location[i].s_reg_low) == base_vreg) { + used_as_reference |= cu->reg_location[i].ref; + } + } + if (!used_as_reference) { + return; + } if (cu->promotion_map[pmap_index].core_location == kLocPhysReg) { // Promoted - just copy in a zero - LoadConstant(cu, cu->promotion_map[pmap_index].core_reg, 0); + OpRegCopy(cu, cu->promotion_map[pmap_index].core_reg, zero_reg); } else { // Lives in the frame, need to store. - int temp_reg = AllocTemp(cu); - LoadConstant(cu, temp_reg, 0); - StoreBaseDisp(cu, TargetReg(kSp), SRegOffset(cu, rl_dest.s_reg_low), temp_reg, kWord); + StoreBaseDisp(cu, TargetReg(kSp), SRegOffset(cu, rl_dest.s_reg_low), zero_reg, kWord); } } } diff --git a/src/compiler/codegen/mir_to_gbc.cc b/src/compiler/codegen/mir_to_gbc.cc index 19b069c40d..c1d61d4279 100644 --- a/src/compiler/codegen/mir_to_gbc.cc +++ b/src/compiler/codegen/mir_to_gbc.cc @@ -2574,9 +2574,12 @@ static void CvtConst(CompilationUnit* cu, llvm::CallInst* call_inst) (immval) & 0xffffffff, (immval >> 32) & 0xffffffff); cg->StoreValueWide(cu, rl_dest, rl_result); } else { - cg->LoadConstantNoClobber(cu, rl_result.low_reg, immval & 0xffffffff); + int immediate = immval & 0xffffffff; + cg->LoadConstantNoClobber(cu, rl_result.low_reg, immediate); cg->StoreValue(cu, rl_dest, rl_result); - cg->Workaround7250540(cu, rl_dest, immval & 0xffffffff); + if (immediate == 0) { + cg->Workaround7250540(cu, rl_dest, rl_result.low_reg); + } } } diff --git a/src/compiler/codegen/mir_to_lir.cc b/src/compiler/codegen/mir_to_lir.cc index 3dc6d59a9b..fc3df6ec91 100644 --- a/src/compiler/codegen/mir_to_lir.cc +++ b/src/compiler/codegen/mir_to_lir.cc @@ -141,14 +141,18 @@ static bool CompileDalvikInstruction(CompilationUnit* cu, MIR* mir, BasicBlock* rl_result = EvalLoc(cu, rl_dest, kAnyReg, true); cg->LoadConstantNoClobber(cu, rl_result.low_reg, vB); cg->StoreValue(cu, rl_dest, rl_result); - cg->Workaround7250540(cu, rl_dest, vB); + if (vB == 0) { + cg->Workaround7250540(cu, rl_dest, rl_result.low_reg); + } break; case Instruction::CONST_HIGH16: rl_result = EvalLoc(cu, rl_dest, kAnyReg, true); cg->LoadConstantNoClobber(cu, rl_result.low_reg, vB << 16); cg->StoreValue(cu, rl_dest, rl_result); - cg->Workaround7250540(cu, rl_dest, vB); + if (vB == 0) { + cg->Workaround7250540(cu, rl_dest, rl_result.low_reg); + } break; case Instruction::CONST_WIDE_16: |