Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(786)

Unified Diff: src/compiler/move-optimizer.cc

Issue 2410673002: [Turbofan] Add concept of FP register aliasing on ARM 32. (Closed)
Patch Set: Fix reg codes (ia32) and register allocator (arm32). Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/compiler/move-optimizer.cc
diff --git a/src/compiler/move-optimizer.cc b/src/compiler/move-optimizer.cc
index 953692dc13b423bce3eef94b5028053d054bb35f..badc90942fb91c10ea319f1d40089ea32a737c3e 100644
--- a/src/compiler/move-optimizer.cc
+++ b/src/compiler/move-optimizer.cc
@@ -27,8 +27,68 @@ struct MoveKeyCompare {
typedef ZoneMap<MoveKey, unsigned, MoveKeyCompare> MoveMap;
typedef ZoneSet<InstructionOperand, CompareOperandModuloType> OperandSet;
-bool Blocks(const OperandSet& set, const InstructionOperand& operand) {
- return set.find(operand) != set.end();
+#define REP_BIT(rep) (1 << static_cast<int>(rep));
+
+bool HasMixedFPReps(int reps) {
+ return reps && !base::bits::IsPowerOfTwo32(reps);
+}
+
+void InsertOp(OperandSet* set, const InstructionOperand& op, int* fp_reg_reps) {
Mircea Trofin 2016/10/12 21:09:26 would it be overkill to define InsertOp as a membe
bbudge 2016/10/12 23:07:17 OperandSet is only a typedef. We could have it inh
Mircea Trofin 2016/10/14 20:58:39 Mind adding a todo on the typedef to investigate d
bbudge 2016/10/15 01:30:25 I replaced the typedef with a class. It's much cle
+ set->insert(op);
+ if (!kSimpleFPAliasing && op.IsFPRegister())
+ *fp_reg_reps |= REP_BIT(LocationOperand::cast(op).representation());
+}
+
+bool ContainsOpOrAlias(const OperandSet& set, const InstructionOperand& op,
Mircea Trofin 2016/10/12 21:09:26 same for this API
bbudge 2016/10/12 23:07:17 Ditto
+ int fp_reg_reps) {
+ if (set.find(op) != set.end()) return true;
+
+ if (!kSimpleFPAliasing && op.IsFPRegister()) {
+ // Platforms where FP registers have complex aliasing need extra checks.
+ const LocationOperand& loc = LocationOperand::cast(op);
+ MachineRepresentation rep = loc.representation();
+ // If we haven't encountered mixed FP registers, skip the extra checks.
+ fp_reg_reps |= REP_BIT(rep);
+ if (!HasMixedFPReps(fp_reg_reps)) return false;
+
+ // Check register against aliasing registers of other FP representations.
+ MachineRepresentation other_rep1, other_rep2;
+ switch (rep) {
+ case MachineRepresentation::kFloat32:
+ other_rep1 = MachineRepresentation::kFloat64;
+ other_rep2 = MachineRepresentation::kSimd128;
+ break;
+ case MachineRepresentation::kFloat64:
+ other_rep1 = MachineRepresentation::kFloat32;
+ other_rep2 = MachineRepresentation::kSimd128;
+ break;
+ case MachineRepresentation::kSimd128:
+ other_rep1 = MachineRepresentation::kFloat32;
+ other_rep2 = MachineRepresentation::kFloat64;
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ const RegisterConfiguration* config = RegisterConfiguration::Turbofan();
+ int base = -1;
+ int aliases =
+ config->GetAliases(rep, loc.register_code(), other_rep1, &base);
+ DCHECK(aliases > 0 || (aliases == 0 && base == -1));
+ while (aliases--) {
+ if (set.find(AllocatedOperand(LocationOperand::REGISTER, other_rep1,
+ base + aliases)) != set.end())
+ return true;
+ }
+ aliases = config->GetAliases(rep, loc.register_code(), other_rep2, &base);
+ DCHECK(aliases > 0 || (aliases == 0 && base == -1));
+ while (aliases--) {
+ if (set.find(AllocatedOperand(LocationOperand::REGISTER, other_rep2,
+ base + aliases)) != set.end())
+ return true;
+ }
+ }
+ return false;
}
int FindFirstNonEmptySlot(const Instruction* instr) {
@@ -94,25 +154,27 @@ void MoveOptimizer::RemoveClobberedDestinations(Instruction* instruction) {
OperandSet outputs(local_zone());
OperandSet inputs(local_zone());
+ int input_fp_reg_reps = 0;
+ int output_fp_reg_reps = 0;
// Outputs and temps are treated together as potentially clobbering a
// destination operand.
for (size_t i = 0; i < instruction->OutputCount(); ++i) {
- outputs.insert(*instruction->OutputAt(i));
+ InsertOp(&outputs, *instruction->OutputAt(i), &output_fp_reg_reps);
}
for (size_t i = 0; i < instruction->TempCount(); ++i) {
- outputs.insert(*instruction->TempAt(i));
+ InsertOp(&outputs, *instruction->TempAt(i), &output_fp_reg_reps);
}
// Input operands block elisions.
for (size_t i = 0; i < instruction->InputCount(); ++i) {
- inputs.insert(*instruction->InputAt(i));
+ InsertOp(&inputs, *instruction->InputAt(i), &input_fp_reg_reps);
}
// Elide moves made redundant by the instruction.
for (MoveOperands* move : *moves) {
- if (outputs.find(move->destination()) != outputs.end() &&
- inputs.find(move->destination()) == inputs.end()) {
+ if (ContainsOpOrAlias(outputs, move->destination(), output_fp_reg_reps) &&
+ !ContainsOpOrAlias(inputs, move->destination(), input_fp_reg_reps)) {
move->Eliminate();
}
}
@@ -121,7 +183,7 @@ void MoveOptimizer::RemoveClobberedDestinations(Instruction* instruction) {
// the one for its input.
if (instruction->IsRet() || instruction->IsTailCall()) {
for (MoveOperands* move : *moves) {
- if (inputs.find(move->destination()) == inputs.end()) {
+ if (!ContainsOpOrAlias(inputs, move->destination(), input_fp_reg_reps)) {
move->Eliminate();
}
}
@@ -136,11 +198,13 @@ void MoveOptimizer::MigrateMoves(Instruction* to, Instruction* from) {
OperandSet dst_cant_be(local_zone());
OperandSet src_cant_be(local_zone());
+ int dst_fp_reg_reps = 0;
+ int src_fp_reg_reps = 0;
// If an operand is an input to the instruction, we cannot move assignments
// where it appears on the LHS.
for (size_t i = 0; i < from->InputCount(); ++i) {
- dst_cant_be.insert(*from->InputAt(i));
+ InsertOp(&dst_cant_be, *from->InputAt(i), &dst_fp_reg_reps);
}
// If an operand is output to the instruction, we cannot move assignments
// where it appears on the RHS, because we would lose its value before the
@@ -149,10 +213,10 @@ void MoveOptimizer::MigrateMoves(Instruction* to, Instruction* from) {
// The output can't appear on the LHS because we performed
// RemoveClobberedDestinations for the "from" instruction.
for (size_t i = 0; i < from->OutputCount(); ++i) {
- src_cant_be.insert(*from->OutputAt(i));
+ InsertOp(&src_cant_be, *from->OutputAt(i), &src_fp_reg_reps);
}
for (size_t i = 0; i < from->TempCount(); ++i) {
- src_cant_be.insert(*from->TempAt(i));
+ InsertOp(&src_cant_be, *from->TempAt(i), &src_fp_reg_reps);
}
for (MoveOperands* move : *from_moves) {
if (move->IsRedundant()) continue;
@@ -160,7 +224,7 @@ void MoveOptimizer::MigrateMoves(Instruction* to, Instruction* from) {
// move "z = dest", because z would become y rather than "V".
// We assume CompressMoves has happened before this, which means we don't
// have more than one assignment to dest.
- src_cant_be.insert(move->destination());
+ InsertOp(&src_cant_be, move->destination(), &src_fp_reg_reps);
}
ZoneSet<MoveKey, MoveKeyCompare> move_candidates(local_zone());
@@ -168,7 +232,7 @@ void MoveOptimizer::MigrateMoves(Instruction* to, Instruction* from) {
// destination operands are eligible for being moved down.
for (MoveOperands* move : *from_moves) {
if (move->IsRedundant()) continue;
- if (!Blocks(dst_cant_be, move->destination())) {
+ if (!ContainsOpOrAlias(dst_cant_be, move->destination(), dst_fp_reg_reps)) {
MoveKey key = {move->source(), move->destination()};
move_candidates.insert(key);
}
@@ -183,8 +247,8 @@ void MoveOptimizer::MigrateMoves(Instruction* to, Instruction* from) {
auto current = iter;
++iter;
InstructionOperand src = current->source;
- if (Blocks(src_cant_be, src)) {
- src_cant_be.insert(current->destination);
+ if (ContainsOpOrAlias(src_cant_be, src, src_fp_reg_reps)) {
+ InsertOp(&src_cant_be, current->destination, &src_fp_reg_reps);
move_candidates.erase(current);
changed = true;
}
@@ -223,8 +287,7 @@ void MoveOptimizer::CompressMoves(ParallelMove* left, MoveOpVector* right) {
// merging the two gaps.
for (MoveOperands* move : *right) {
if (move->IsRedundant()) continue;
- MoveOperands* to_eliminate = left->PrepareInsertAfter(move);
- if (to_eliminate != nullptr) eliminated.push_back(to_eliminate);
+ left->PrepareInsertAfter(move, &eliminated);
}
// Eliminate dead moves.
for (MoveOperands* to_eliminate : eliminated) {

Powered by Google App Engine
This is Rietveld 408576698