Index: src/IceTargetLoweringX8632.cpp |
diff --git a/src/IceTargetLoweringX8632.cpp b/src/IceTargetLoweringX8632.cpp |
index 35792aaac0aebc38cafca62a0744a7e8c9fe4572..ea56ee84da3b686489a3968fa1dc0c1e8019d7c4 100644 |
--- a/src/IceTargetLoweringX8632.cpp |
+++ b/src/IceTargetLoweringX8632.cpp |
@@ -4145,9 +4145,7 @@ void TargetX8632::postLower() { |
return; |
// TODO: Avoid recomputing WhiteList every instruction. |
RegSetMask RegInclude = RegSet_All; |
- RegSetMask RegExclude = RegSet_None; |
- if (hasFramePointer()) |
- RegExclude |= RegSet_FramePointer; |
+ RegSetMask RegExclude = RegSet_FramePointer; |
llvm::SmallBitVector WhiteList = getRegisterSet(RegInclude, RegExclude); |
// Make one pass to black-list pre-colored registers. TODO: If |
// there was some prior register allocation pass that made register |
@@ -4172,6 +4170,17 @@ void TargetX8632::postLower() { |
} |
} |
// The second pass colors infinite-weight variables. |
+ |
+ // Indices from which to start looking for the next register in the |
+ // free list. |
+ int32_t PrevFreeRegisterForType[IceType_NUM]; |
+ int32_t Uninitialized = -1; |
+ std::fill_n(PrevFreeRegisterForType, IceType_NUM, Uninitialized); |
+ RandomNumberGeneratorWrapper RNG(Ctx->getRNG()); |
+ |
+ // TODO: The randomized register allocation should choose scratch |
+ // registers before callee save registers. |
+ |
llvm::SmallBitVector AvailableRegisters = WhiteList; |
for (InstList::iterator I = Context.getCur(), E = Context.getEnd(); I != E; |
++I) { |
@@ -4187,21 +4196,120 @@ void TargetX8632::postLower() { |
continue; |
if (!Var->getWeight().isInf()) |
continue; |
+ Type Ty = Var->getType(); |
+ |
llvm::SmallBitVector AvailableTypedRegisters = |
- AvailableRegisters & getRegisterSetForType(Var->getType()); |
+ AvailableRegisters & getRegisterSetForType(Ty); |
+ |
if (!AvailableTypedRegisters.any()) { |
// This is a hack in case we run out of physical registers due |
// to an excessively long code sequence, as might happen when |
// lowering arguments in lowerCall(). |
AvailableRegisters = WhiteList; |
AvailableTypedRegisters = |
- AvailableRegisters & getRegisterSetForType(Var->getType()); |
+ AvailableRegisters & getRegisterSetForType(Ty); |
} |
assert(AvailableTypedRegisters.any()); |
- int32_t RegNum = AvailableTypedRegisters.find_first(); |
+ |
+ if (PrevFreeRegisterForType[Ty] == Uninitialized && |
+ RandomizeRegisterAllocation) { |
+ // Start at a random offset in the free list; follow the |
+ // linear order from there. |
+ SizeT StartingRegister = RNG.next(AvailableTypedRegisters.count()); |
+ SizeT Index = -1; |
+ for (size_t I = 0; I < StartingRegister; ++I) { |
+ Index = AvailableTypedRegisters.find_next(Index); |
+ } |
+ PrevFreeRegisterForType[Ty] = Index; |
+ } |
+ |
+ int32_t PrevRegNum = PrevFreeRegisterForType[Ty]; |
+ int32_t RegNum = AvailableTypedRegisters.find_next(PrevRegNum); |
+ if (RegNum == -1) { |
+ // Wraparound |
+ RegNum = AvailableTypedRegisters.find_first(); |
+ } |
+ assert(RegNum != -1); |
+ |
Var->setRegNum(RegNum); |
AvailableRegisters[RegNum] = false; |
+ PrevFreeRegisterForType[Ty] = RegNum; |
+ } |
+ } |
+ } |
+} |
+ |
+void TargetX8632::makeRandomRegisterPermutation( |
+ llvm::SmallVectorImpl<int32_t> &Permutation, |
+ const llvm::SmallBitVector &ExcludeRegisters) { |
+ assert(Permutation.size() >= Reg_NUM); |
+ typedef llvm::SmallVector<int32_t, 8> RegisterList; |
+ typedef std::map<unsigned, RegisterList> EquivalenceClassMap; |
+ EquivalenceClassMap EquivalenceClasses; |
+ SizeT NumShuffled = 0, NumPreserved = 0; |
+ |
+// Build up the equivalence classes of registers by looking at the |
+// register properties as well as whether the registers should be |
+// explicitly excluded from shuffling. |
+#define X(val, init, name, name16, name8, scratch, preserved, stackptr, \ |
+ frameptr, isI8, isInt, isFP) \ |
+ if (ExcludeRegisters[val]) { \ |
+ /* val stays the same in the resulting permutation. */ \ |
+ Permutation[val] = val; \ |
+ ++NumPreserved; \ |
+ } else { \ |
+ union { \ |
+ unsigned ClassNum; \ |
+ struct { \ |
+ unsigned IsScratch : 1; \ |
+ unsigned IsPreserved : 1; \ |
+ unsigned IsI8 : 1; \ |
+ unsigned IsInt : 1; \ |
+ unsigned IsFP : 1; \ |
+ } Bits; \ |
+ } Class = {0}; \ |
+ Class.Bits.IsScratch = scratch; \ |
+ Class.Bits.IsPreserved = preserved; \ |
+ Class.Bits.IsI8 = isI8; \ |
+ Class.Bits.IsInt = isInt; \ |
+ Class.Bits.IsFP = isFP; \ |
+ /* val is assigned to an equivalence class based on its properties. */ \ |
+ EquivalenceClasses[Class.ClassNum].push_back(val); \ |
+ } |
+ REGX8632_TABLE |
+#undef X |
+ |
+ RandomNumberGeneratorWrapper RNG(Ctx->getRNG()); |
+ |
+ // Shuffle the resulting equivalence classes. |
+ for (EquivalenceClassMap::const_iterator I = EquivalenceClasses.begin(), |
+ E = EquivalenceClasses.end(); |
+ I != E; ++I) { |
+ const RegisterList &List = I->second; |
+ RegisterList Shuffled(List); |
+ std::random_shuffle(Shuffled.begin(), Shuffled.end(), RNG); |
+ for (size_t SI = 0, SE = Shuffled.size(); SI < SE; ++SI) { |
+ Permutation[List[SI]] = Shuffled[SI]; |
+ ++NumShuffled; |
+ } |
+ } |
+ |
+ assert(NumShuffled + NumPreserved == Reg_NUM); |
+ |
+ if (Func->getContext()->isVerbose(IceV_Random)) { |
+ Ostream &Str = Func->getContext()->getStrDump(); |
+ Str << "Register equivalence classes:\n"; |
+ for (EquivalenceClassMap::const_iterator I = EquivalenceClasses.begin(), |
+ E = EquivalenceClasses.end(); |
+ I != E; ++I) { |
+ Str << "{"; |
+ const RegisterList &List = I->second; |
+ for (SizeT RI = 0, RE = List.size(); RI != RE; ++RI) { |
+ if (RI > 0) |
+ Str << " "; |
+ Str << getRegName(List[RI], IceType_i32); |
} |
+ Str << "}\n"; |
} |
} |
} |