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 .
diff --git a/src/IceRegAlloc.cpp b/src/IceRegAlloc.cpp
index 50e014a..480b907 100644
--- a/src/IceRegAlloc.cpp
+++ b/src/IceRegAlloc.cpp
@@ -652,17 +652,15 @@
} 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 @@
// 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);