summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/codegen/arm/utility_arm.cc52
-rw-r--r--src/compiler/codegen/gen_loadstore.cc21
-rw-r--r--src/compiler/codegen/mir_to_gbc.cc7
-rw-r--r--src/compiler/codegen/mir_to_lir.cc8
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: