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/local_optimizations.cc b/compiler/dex/quick/local_optimizations.cc
index 4a918a1..b97ff2a 100644
--- a/compiler/dex/quick/local_optimizations.cc
+++ b/compiler/dex/quick/local_optimizations.cc
@@ -21,8 +21,8 @@
#define DEBUG_OPT(X)
/* Check RAW, WAR, and RAW dependency on the register operands */
-#define CHECK_REG_DEP(use, def, check) ((def & check->u.m.use_mask) || \
- ((use | def) & check->u.m.def_mask))
+#define CHECK_REG_DEP(use, def, check) (def.Intersects(*check->u.m.use_mask)) || \
+ (use.Union(def).Intersects(*check->u.m.def_mask))
/* Scheduler heuristics */
#define MAX_HOIST_DISTANCE 20
@@ -109,20 +109,23 @@
bool is_this_lir_load = target_flags & IS_LOAD;
LIR* check_lir;
/* Use the mem mask to determine the rough memory location */
- uint64_t this_mem_mask = (this_lir->u.m.use_mask | this_lir->u.m.def_mask) & ENCODE_MEM;
+ ResourceMask this_mem_mask = kEncodeMem.Intersection(
+ this_lir->u.m.use_mask->Union(*this_lir->u.m.def_mask));
/*
* Currently only eliminate redundant ld/st for constant and Dalvik
* register accesses.
*/
- if (!(this_mem_mask & (ENCODE_LITERAL | ENCODE_DALVIK_REG))) {
+ if (!this_mem_mask.Intersects(kEncodeLiteral.Union(kEncodeDalvikReg))) {
continue;
}
- uint64_t stop_def_reg_mask = this_lir->u.m.def_mask & ~ENCODE_MEM;
- uint64_t stop_use_reg_mask;
+ ResourceMask stop_def_reg_mask = this_lir->u.m.def_mask->Without(kEncodeMem);
+ ResourceMask stop_use_reg_mask;
if (cu_->instruction_set == kX86 || cu_->instruction_set == kX86_64) {
- stop_use_reg_mask = (IS_BRANCH | this_lir->u.m.use_mask) & ~ENCODE_MEM;
+ // TODO: Stop the abuse of kIsBranch as a bit specification for ResourceMask.
+ stop_use_reg_mask = ResourceMask::Bit(kIsBranch).Union(*this_lir->u.m.use_mask).Without(
+ kEncodeMem);
} else {
/*
* Add pc to the resource mask to prevent this instruction
@@ -130,7 +133,7 @@
* region bits since stop_mask is used to check data/control
* dependencies.
*/
- stop_use_reg_mask = (GetPCUseDefEncoding() | this_lir->u.m.use_mask) & ~ENCODE_MEM;
+ stop_use_reg_mask = GetPCUseDefEncoding().Union(*this_lir->u.m.use_mask).Without(kEncodeMem);
}
for (check_lir = NEXT_LIR(this_lir); check_lir != tail_lir; check_lir = NEXT_LIR(check_lir)) {
@@ -142,8 +145,9 @@
continue;
}
- uint64_t check_mem_mask = (check_lir->u.m.use_mask | check_lir->u.m.def_mask) & ENCODE_MEM;
- uint64_t alias_condition = this_mem_mask & check_mem_mask;
+ ResourceMask check_mem_mask = kEncodeMem.Intersection(
+ check_lir->u.m.use_mask->Union(*check_lir->u.m.def_mask));
+ ResourceMask alias_condition = this_mem_mask.Intersection(check_mem_mask);
bool stop_here = false;
/*
@@ -153,9 +157,9 @@
// TUNING: Support instructions with multiple register targets.
if ((check_flags & (REG_DEF0 | REG_DEF1)) == (REG_DEF0 | REG_DEF1)) {
stop_here = true;
- } else if (check_mem_mask != ENCODE_MEM && alias_condition != 0) {
+ } else if (!check_mem_mask.Equals(kEncodeMem) && !alias_condition.Equals(kEncodeNone)) {
bool is_check_lir_load = check_flags & IS_LOAD;
- if (alias_condition == ENCODE_LITERAL) {
+ if (alias_condition.Equals(kEncodeLiteral)) {
/*
* Should only see literal loads in the instruction
* stream.
@@ -175,7 +179,7 @@
}
NopLIR(check_lir);
}
- } else if (alias_condition == ENCODE_DALVIK_REG) {
+ } else if (alias_condition.Equals(kEncodeDalvikReg)) {
/* Must alias */
if (check_lir->flags.alias_info == this_lir->flags.alias_info) {
/* Only optimize compatible registers */
@@ -304,7 +308,7 @@
continue;
}
- uint64_t stop_use_all_mask = this_lir->u.m.use_mask;
+ ResourceMask stop_use_all_mask = *this_lir->u.m.use_mask;
if (cu_->instruction_set != kX86 && cu_->instruction_set != kX86_64) {
/*
@@ -313,14 +317,14 @@
* locations are safe to be hoisted. So only mark the heap references
* conservatively here.
*/
- if (stop_use_all_mask & ENCODE_HEAP_REF) {
- stop_use_all_mask |= GetPCUseDefEncoding();
+ if (stop_use_all_mask.HasBit(ResourceMask::kHeapRef)) {
+ stop_use_all_mask.SetBits(GetPCUseDefEncoding());
}
}
/* Similar as above, but just check for pure register dependency */
- uint64_t stop_use_reg_mask = stop_use_all_mask & ~ENCODE_MEM;
- uint64_t stop_def_reg_mask = this_lir->u.m.def_mask & ~ENCODE_MEM;
+ ResourceMask stop_use_reg_mask = stop_use_all_mask.Without(kEncodeMem);
+ ResourceMask stop_def_reg_mask = this_lir->u.m.def_mask->Without(kEncodeMem);
int next_slot = 0;
bool stop_here = false;
@@ -335,22 +339,22 @@
continue;
}
- uint64_t check_mem_mask = check_lir->u.m.def_mask & ENCODE_MEM;
- uint64_t alias_condition = stop_use_all_mask & check_mem_mask;
+ ResourceMask check_mem_mask = check_lir->u.m.def_mask->Intersection(kEncodeMem);
+ ResourceMask alias_condition = stop_use_all_mask.Intersection(check_mem_mask);
stop_here = false;
/* Potential WAR alias seen - check the exact relation */
- if (check_mem_mask != ENCODE_MEM && alias_condition != 0) {
+ if (!check_mem_mask.Equals(kEncodeMem) && !alias_condition.Equals(kEncodeNone)) {
/* We can fully disambiguate Dalvik references */
- if (alias_condition == ENCODE_DALVIK_REG) {
- /* Must alias or partually overlap */
+ if (alias_condition.Equals(kEncodeDalvikReg)) {
+ /* Must alias or partially overlap */
if ((check_lir->flags.alias_info == this_lir->flags.alias_info) ||
IsDalvikRegisterClobbered(this_lir, check_lir)) {
stop_here = true;
}
/* Conservatively treat all heap refs as may-alias */
} else {
- DCHECK_EQ(alias_condition, ENCODE_HEAP_REF);
+ DCHECK(alias_condition.Equals(kEncodeHeapRef));
stop_here = true;
}
/* Memory content may be updated. Stop looking now. */
@@ -413,7 +417,7 @@
LIR* prev_lir = prev_inst_list[slot+1];
/* Check the highest instruction */
- if (prev_lir->u.m.def_mask == ENCODE_ALL) {
+ if (prev_lir->u.m.def_mask->Equals(kEncodeAll)) {
/*
* If the first instruction is a load, don't hoist anything
* above it since it is unlikely to be beneficial.
@@ -443,7 +447,8 @@
*/
bool prev_is_load = IsPseudoLirOp(prev_lir->opcode) ? false :
(GetTargetInstFlags(prev_lir->opcode) & IS_LOAD);
- if (((cur_lir->u.m.use_mask & prev_lir->u.m.def_mask) && prev_is_load) || (slot < LD_LATENCY)) {
+ if ((prev_is_load && (cur_lir->u.m.use_mask->Intersects(*prev_lir->u.m.def_mask))) ||
+ (slot < LD_LATENCY)) {
break;
}
}