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) {
} else {
// Evict all live ranges in Active that register number MinWeightIndex is
// assigned to.
const llvm::SmallBitVector &Aliases = *RegAliases[MinWeightIndex];
for (SizeT I = Active.size(); I > 0; --I) {
const SizeT Index = I - 1;
Variable *Item = Active[Index];
if (Item->getRegNumTmp() == MinWeightIndex) {
dumpLiveRangeTrace("Evicting ", Item);
const llvm::SmallBitVector &Aliases = *RegAliases[MinWeightIndex];
for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
RegAlias = Aliases.find_next(RegAlias)) {
--RegUses[RegAlias];
assert(RegUses[RegAlias] >= 0);
}
int32_t RegNum = Item->getRegNumTmp();
if (Aliases[RegNum]) {
dumpLiveRangeTrace("Evicting A ", Item);
--RegUses[RegNum];
assert(RegUses[RegNum] >= 0);
Item->setRegNumTmp(Variable::NoRegister);
moveItem(Active, Index, Handled);
}
......@@ -678,16 +676,14 @@ void LinearScan::handleNoFreeRegisters(IterationState &Iter) {
// especially bad if we would end up evicting an infinite-weight but
// currently-inactive live range. The most common situation for this
// would be a scratch register kill set for call instructions.
if (Item->getRegNumTmp() == MinWeightIndex &&
Item->rangeOverlaps(Iter.Cur)) {
dumpLiveRangeTrace("Evicting ", Item);
if (Aliases[Item->getRegNumTmp()] && Item->rangeOverlaps(Iter.Cur)) {
dumpLiveRangeTrace("Evicting I ", Item);
Item->setRegNumTmp(Variable::NoRegister);
moveItem(Inactive, Index, Handled);
}
}
// Assign the register to Cur.
Iter.Cur->setRegNumTmp(MinWeightIndex);
const llvm::SmallBitVector &Aliases = *RegAliases[MinWeightIndex];
for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
RegAlias = Aliases.find_next(RegAlias)) {
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