Commit 7cb12682 by John Porto

Subzero. Fixes a bug in the register allocator.

This bug was uncovered While implementing the llvm.nacl.atomic.cmpxchg lowering for i64 for ARM32. For reference, the lowering is retry: ldrexd tmp_i, tmp_i+1 [addr] cmp tmp_i+1, expected_i+1 cmpeq tmp_i, expected_i strexdeq success, new_i, new_i+1, [addr] movne expected_i+1, tmp_i+1 movne expected_i, tmp_i cmpeq success, #0 bne retry mov dest_i+1, tmp_i+1 mov dest_i, tmp_i The register allocator would allocate r4 to both success and new_i, which is clearly wrong (expected_i is alive thought the cmpxchg loop.) Adding a fake-use(new_i) after the loop caused the register allocator to fail due to the impossibility to allocate a register for an infinite weight register. The problem was being caused for not evicting live ranges that were assigned registers that alias the selected register. BUG= R=kschimpf@google.com, stichnot@chromium.org Review URL: https://codereview.chromium.org/1373823006 .
parent 16991847
...@@ -652,17 +652,15 @@ void LinearScan::handleNoFreeRegisters(IterationState &Iter) { ...@@ -652,17 +652,15 @@ void LinearScan::handleNoFreeRegisters(IterationState &Iter) {
} else { } else {
// Evict all live ranges in Active that register number MinWeightIndex is // Evict all live ranges in Active that register number MinWeightIndex is
// assigned to. // assigned to.
const llvm::SmallBitVector &Aliases = *RegAliases[MinWeightIndex];
for (SizeT I = Active.size(); I > 0; --I) { for (SizeT I = Active.size(); I > 0; --I) {
const SizeT Index = I - 1; const SizeT Index = I - 1;
Variable *Item = Active[Index]; Variable *Item = Active[Index];
if (Item->getRegNumTmp() == MinWeightIndex) { int32_t RegNum = Item->getRegNumTmp();
dumpLiveRangeTrace("Evicting ", Item); if (Aliases[RegNum]) {
const llvm::SmallBitVector &Aliases = *RegAliases[MinWeightIndex]; dumpLiveRangeTrace("Evicting A ", Item);
for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0; --RegUses[RegNum];
RegAlias = Aliases.find_next(RegAlias)) { assert(RegUses[RegNum] >= 0);
--RegUses[RegAlias];
assert(RegUses[RegAlias] >= 0);
}
Item->setRegNumTmp(Variable::NoRegister); Item->setRegNumTmp(Variable::NoRegister);
moveItem(Active, Index, Handled); moveItem(Active, Index, Handled);
} }
...@@ -678,16 +676,14 @@ void LinearScan::handleNoFreeRegisters(IterationState &Iter) { ...@@ -678,16 +676,14 @@ void LinearScan::handleNoFreeRegisters(IterationState &Iter) {
// especially bad if we would end up evicting an infinite-weight but // especially bad if we would end up evicting an infinite-weight but
// currently-inactive live range. The most common situation for this // currently-inactive live range. The most common situation for this
// would be a scratch register kill set for call instructions. // would be a scratch register kill set for call instructions.
if (Item->getRegNumTmp() == MinWeightIndex && if (Aliases[Item->getRegNumTmp()] && Item->rangeOverlaps(Iter.Cur)) {
Item->rangeOverlaps(Iter.Cur)) { dumpLiveRangeTrace("Evicting I ", Item);
dumpLiveRangeTrace("Evicting ", Item);
Item->setRegNumTmp(Variable::NoRegister); Item->setRegNumTmp(Variable::NoRegister);
moveItem(Inactive, Index, Handled); moveItem(Inactive, Index, Handled);
} }
} }
// Assign the register to Cur. // Assign the register to Cur.
Iter.Cur->setRegNumTmp(MinWeightIndex); Iter.Cur->setRegNumTmp(MinWeightIndex);
const llvm::SmallBitVector &Aliases = *RegAliases[MinWeightIndex];
for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0; for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
RegAlias = Aliases.find_next(RegAlias)) { RegAlias = Aliases.find_next(RegAlias)) {
assert(RegUses[RegAlias] >= 0); assert(RegUses[RegAlias] >= 0);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment