Rewrite use/def masks to support 128 bits.
Reduce LIR memory usage by holding masks by pointers in the
LIR rather than directly and using pre-defined const masks
for the common cases, allocating very few on the arena.
Change-Id: I0f6d27ef6867acd157184c8c74f9612cebfe6c16
diff --git a/compiler/dex/quick/arm64/arm64_lir.h b/compiler/dex/quick/arm64/arm64_lir.h
index 6a6b0f6..01afc99 100644
--- a/compiler/dex/quick/arm64/arm64_lir.h
+++ b/compiler/dex/quick/arm64/arm64_lir.h
@@ -102,17 +102,14 @@
#define A64_REG_IS_SP(reg_num) ((reg_num) == rwsp || (reg_num) == rsp)
#define A64_REG_IS_ZR(reg_num) ((reg_num) == rwzr || (reg_num) == rxzr)
-enum ArmResourceEncodingPos {
- kArmGPReg0 = 0,
- kArmRegLR = 30,
- kArmRegSP = 31,
- kArmFPReg0 = 32,
- kArmRegEnd = 64,
+enum Arm64ResourceEncodingPos {
+ kArm64GPReg0 = 0,
+ kArm64RegLR = 30,
+ kArm64RegSP = 31,
+ kArm64FPReg0 = 32,
+ kArm64RegEnd = 64,
};
-#define ENCODE_ARM_REG_SP (1ULL << kArmRegSP)
-#define ENCODE_ARM_REG_LR (1ULL << kArmRegLR)
-
#define IS_SIGNED_IMM(size, value) \
((value) >= -(1 << ((size) - 1)) && (value) < (1 << ((size) - 1)))
#define IS_SIGNED_IMM7(value) IS_SIGNED_IMM(7, value)
diff --git a/compiler/dex/quick/arm64/codegen_arm64.h b/compiler/dex/quick/arm64/codegen_arm64.h
index 21db771..75e24fe 100644
--- a/compiler/dex/quick/arm64/codegen_arm64.h
+++ b/compiler/dex/quick/arm64/codegen_arm64.h
@@ -63,7 +63,7 @@
RegLocation LocCReturnDouble();
RegLocation LocCReturnFloat();
RegLocation LocCReturnWide();
- uint64_t GetRegMaskCommon(RegStorage reg);
+ ResourceMask GetRegMaskCommon(const RegStorage& reg) const OVERRIDE;
void AdjustSpillMask();
void ClobberCallerSave();
void FreeCallTemps();
@@ -78,12 +78,13 @@
int AssignInsnOffsets();
void AssignOffsets();
uint8_t* EncodeLIRs(uint8_t* write_pos, LIR* lir);
- void DumpResourceMask(LIR* lir, uint64_t mask, const char* prefix);
- void SetupTargetResourceMasks(LIR* lir, uint64_t flags);
+ void DumpResourceMask(LIR* lir, const ResourceMask& mask, const char* prefix) OVERRIDE;
+ void SetupTargetResourceMasks(LIR* lir, uint64_t flags,
+ ResourceMask* use_mask, ResourceMask* def_mask) OVERRIDE;
const char* GetTargetInstFmt(int opcode);
const char* GetTargetInstName(int opcode);
std::string BuildInsnString(const char* fmt, LIR* lir, unsigned char* base_addr);
- uint64_t GetPCUseDefEncoding();
+ ResourceMask GetPCUseDefEncoding() const OVERRIDE;
uint64_t GetTargetInstFlags(int opcode);
int GetInsnSize(LIR* lir);
bool IsUnconditionalBranch(LIR* lir);
diff --git a/compiler/dex/quick/arm64/int_arm64.cc b/compiler/dex/quick/arm64/int_arm64.cc
index 0a76b9b..1ad0435 100644
--- a/compiler/dex/quick/arm64/int_arm64.cc
+++ b/compiler/dex/quick/arm64/int_arm64.cc
@@ -572,7 +572,7 @@
} else {
NewLIR3(kA64Ldxr2rX, r_tmp.GetReg(), r_ptr.GetReg(), 0);
OpRegReg(kOpSub, r_tmp, rl_expected.reg);
- DCHECK(last_lir_insn_->u.m.def_mask & ENCODE_CCODE);
+ DCHECK(last_lir_insn_->u.m.def_mask->HasBit(ResourceMask::kCCode));
// OpIT(kCondEq, "T");
NewLIR4(kA64Stxr3wrX /* eq */, r_tmp.GetReg(), rl_new_value.reg.GetReg(), r_ptr.GetReg(), 0);
}
@@ -588,7 +588,7 @@
// result := (tmp1 != 0) ? 0 : 1;
RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
OpRegRegImm(kOpRsub, rl_result.reg, r_tmp, 1);
- DCHECK(last_lir_insn_->u.m.def_mask & ENCODE_CCODE);
+ DCHECK(last_lir_insn_->u.m.def_mask->HasBit(ResourceMask::kCCode));
// OpIT(kCondUlt, "");
LoadConstant(rl_result.reg, 0); /* cc */
FreeTemp(r_tmp); // Now unneeded.
@@ -640,7 +640,7 @@
LIR* Arm64Mir2Lir::OpDecAndBranch(ConditionCode c_code, RegStorage reg, LIR* target) {
// Combine sub & test using sub setflags encoding here
OpRegRegImm(kOpSub, reg, reg, 1); // For value == 1, this should set flags.
- DCHECK(last_lir_insn_->u.m.def_mask & ENCODE_CCODE);
+ DCHECK(last_lir_insn_->u.m.def_mask->HasBit(ResourceMask::kCCode));
return OpCondBranch(c_code, target);
}
@@ -673,7 +673,7 @@
// At this point we must have a memory barrier. Mark it as a scheduling barrier as well.
DCHECK(!barrier->flags.use_def_invalid);
- barrier->u.m.def_mask = ENCODE_ALL;
+ barrier->u.m.def_mask = &kEncodeAll;
return ret;
#else
return false;
diff --git a/compiler/dex/quick/arm64/target_arm64.cc b/compiler/dex/quick/arm64/target_arm64.cc
index 439dc8c..e2846ae 100644
--- a/compiler/dex/quick/arm64/target_arm64.cc
+++ b/compiler/dex/quick/arm64/target_arm64.cc
@@ -139,41 +139,43 @@
/*
* Decode the register id. This routine makes assumptions on the encoding made by RegStorage.
*/
-uint64_t Arm64Mir2Lir::GetRegMaskCommon(RegStorage reg) {
+ResourceMask Arm64Mir2Lir::GetRegMaskCommon(const RegStorage& reg) const {
// TODO(Arm64): this function depends too much on the internal RegStorage encoding. Refactor.
- int reg_raw = reg.GetRawBits();
// Check if the shape mask is zero (i.e. invalid).
if (UNLIKELY(reg == rs_wzr || reg == rs_xzr)) {
// The zero register is not a true register. It is just an immediate zero.
- return 0;
+ return kEncodeNone;
}
- return UINT64_C(1) << (reg_raw & RegStorage::kRegTypeMask);
+ return ResourceMask::Bit(
+ // FP register starts at bit position 32.
+ (reg.IsFloat() ? kArm64FPReg0 : 0) + reg.GetRegNum());
}
-uint64_t Arm64Mir2Lir::GetPCUseDefEncoding() {
+ResourceMask Arm64Mir2Lir::GetPCUseDefEncoding() const {
LOG(FATAL) << "Unexpected call to GetPCUseDefEncoding for Arm64";
- return 0ULL;
+ return kEncodeNone;
}
// Arm64 specific setup. TODO: inline?:
-void Arm64Mir2Lir::SetupTargetResourceMasks(LIR* lir, uint64_t flags) {
+void Arm64Mir2Lir::SetupTargetResourceMasks(LIR* lir, uint64_t flags,
+ ResourceMask* use_mask, ResourceMask* def_mask) {
DCHECK_EQ(cu_->instruction_set, kArm64);
DCHECK(!lir->flags.use_def_invalid);
// These flags are somewhat uncommon - bypass if we can.
if ((flags & (REG_DEF_SP | REG_USE_SP | REG_DEF_LR)) != 0) {
if (flags & REG_DEF_SP) {
- lir->u.m.def_mask |= ENCODE_ARM_REG_SP;
+ def_mask->SetBit(kArm64RegSP);
}
if (flags & REG_USE_SP) {
- lir->u.m.use_mask |= ENCODE_ARM_REG_SP;
+ use_mask->SetBit(kArm64RegSP);
}
if (flags & REG_DEF_LR) {
- lir->u.m.def_mask |= ENCODE_ARM_REG_LR;
+ def_mask->SetBit(kArm64RegLR);
}
}
}
@@ -510,44 +512,44 @@
return buf;
}
-void Arm64Mir2Lir::DumpResourceMask(LIR* arm_lir, uint64_t mask, const char* prefix) {
+void Arm64Mir2Lir::DumpResourceMask(LIR* arm_lir, const ResourceMask& mask, const char* prefix) {
char buf[256];
buf[0] = 0;
- if (mask == ENCODE_ALL) {
+ if (mask.Equals(kEncodeAll)) {
strcpy(buf, "all");
} else {
char num[8];
int i;
- for (i = 0; i < kArmRegEnd; i++) {
- if (mask & (1ULL << i)) {
+ for (i = 0; i < kArm64RegEnd; i++) {
+ if (mask.HasBit(i)) {
snprintf(num, arraysize(num), "%d ", i);
strcat(buf, num);
}
}
- if (mask & ENCODE_CCODE) {
+ if (mask.HasBit(ResourceMask::kCCode)) {
strcat(buf, "cc ");
}
- if (mask & ENCODE_FP_STATUS) {
+ if (mask.HasBit(ResourceMask::kFPStatus)) {
strcat(buf, "fpcc ");
}
/* Memory bits */
- if (arm_lir && (mask & ENCODE_DALVIK_REG)) {
+ if (arm_lir && (mask.HasBit(ResourceMask::kDalvikReg))) {
snprintf(buf + strlen(buf), arraysize(buf) - strlen(buf), "dr%d%s",
DECODE_ALIAS_INFO_REG(arm_lir->flags.alias_info),
DECODE_ALIAS_INFO_WIDE(arm_lir->flags.alias_info) ? "(+1)" : "");
}
- if (mask & ENCODE_LITERAL) {
+ if (mask.HasBit(ResourceMask::kLiteral)) {
strcat(buf, "lit ");
}
- if (mask & ENCODE_HEAP_REF) {
+ if (mask.HasBit(ResourceMask::kHeapRef)) {
strcat(buf, "heap ");
}
- if (mask & ENCODE_MUST_NOT_ALIAS) {
+ if (mask.HasBit(ResourceMask::kMustNotAlias)) {
strcat(buf, "noalias ");
}
}
@@ -850,6 +852,8 @@
return;
}
+ // Handle dalvik registers.
+ ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
int start_vreg = cu_->num_dalvik_registers - cu_->num_ins;
for (int i = 0; i < cu_->num_ins; i++) {
PromotionMap* v_map = &promotion_map_[start_vreg + i];
diff --git a/compiler/dex/quick/arm64/utility_arm64.cc b/compiler/dex/quick/arm64/utility_arm64.cc
index 4f0d7bc..ab5014f 100644
--- a/compiler/dex/quick/arm64/utility_arm64.cc
+++ b/compiler/dex/quick/arm64/utility_arm64.cc
@@ -102,9 +102,9 @@
data_target = AddWordData(&literal_list_, value);
}
+ ScopedMemRefType mem_ref_type(this, ResourceMask::kLiteral);
LIR* load_pc_rel = RawLIR(current_dalvik_offset_, kA64Ldr2fp,
r_dest, 0, 0, 0, 0, data_target);
- SetMemRefType(load_pc_rel, true, kLiteral);
AppendLIR(load_pc_rel);
return load_pc_rel;
}
@@ -129,9 +129,9 @@
}
DCHECK(RegStorage::IsFloat(r_dest));
+ ScopedMemRefType mem_ref_type(this, ResourceMask::kLiteral);
LIR* load_pc_rel = RawLIR(current_dalvik_offset_, FWIDE(kA64Ldr2fp),
r_dest, 0, 0, 0, 0, data_target);
- SetMemRefType(load_pc_rel, true, kLiteral);
AppendLIR(load_pc_rel);
return load_pc_rel;
}
@@ -683,9 +683,9 @@
data_target = AddWideData(&literal_list_, val_lo, val_hi);
}
+ ScopedMemRefType mem_ref_type(this, ResourceMask::kLiteral);
LIR* res = RawLIR(current_dalvik_offset_, WIDE(kA64Ldr2rp),
r_dest.GetReg(), 0, 0, 0, 0, data_target);
- SetMemRefType(res, true, kLiteral);
AppendLIR(res);
return res;
}
@@ -905,7 +905,8 @@
}
// TODO: in future may need to differentiate Dalvik accesses w/ spills
- if (r_base == rs_rA64_SP) {
+ if (mem_ref_type_ == ResourceMask::kDalvikReg) {
+ DCHECK(r_base == rs_rA64_SP);
AnnotateDalvikRegAccess(load, displacement >> 2, true /* is_load */, r_dest.Is64Bit());
}
return load;
@@ -986,7 +987,8 @@
}
// TODO: In future, may need to differentiate Dalvik & spill accesses.
- if (r_base == rs_rA64_SP) {
+ if (mem_ref_type_ == ResourceMask::kDalvikReg) {
+ DCHECK(r_base == rs_rA64_SP);
AnnotateDalvikRegAccess(store, displacement >> 2, false /* is_load */, r_src.Is64Bit());
}
return store;