[llvm] r344392 - [llvm-mca] Correctly set aliases for register writes introduced by optimized register moves.
Andrea Di Biagio via llvm-commits
llvm-commits at lists.llvm.org
Fri Oct 12 11:18:53 PDT 2018
Author: adibiagio
Date: Fri Oct 12 11:18:53 2018
New Revision: 344392
URL: http://llvm.org/viewvc/llvm-project?rev=344392&view=rev
Log:
[llvm-mca] Correctly set aliases for register writes introduced by optimized register moves.
This fixes a problem introduced by r344334. A write from a non-zero move
eliminated at register renaming stage was not correctly handled by the PRF. This
would have led to an assertion failure if the processor model declares a PRF
that enables non-zero move elimination.
Modified:
llvm/trunk/tools/llvm-mca/include/HardwareUnits/RegisterFile.h
llvm/trunk/tools/llvm-mca/lib/HardwareUnits/RegisterFile.cpp
llvm/trunk/tools/llvm-mca/lib/Stages/DispatchStage.cpp
Modified: llvm/trunk/tools/llvm-mca/include/HardwareUnits/RegisterFile.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/include/HardwareUnits/RegisterFile.h?rev=344392&r1=344391&r2=344392&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/include/HardwareUnits/RegisterFile.h (original)
+++ llvm/trunk/tools/llvm-mca/include/HardwareUnits/RegisterFile.h Fri Oct 12 11:18:53 2018
@@ -109,12 +109,18 @@ class RegisterFile : public HardwareUnit
//
// Field `AllowMoveElimination` is set for registers that are used as
// destination by optimizable register moves.
+ //
+ // Field `AliasRegID` is set by writes from register moves that have been
+ // eliminated at register renaming stage. A move eliminated at register
+ // renaming stage is effectively bypassed, and its write aliases the source
+ // register definition.
struct RegisterRenamingInfo {
IndexPlusCostPairTy IndexPlusCost;
llvm::MCPhysReg RenameAs;
+ llvm::MCPhysReg AliasRegID;
bool AllowMoveElimination;
RegisterRenamingInfo()
- : IndexPlusCost(std::make_pair(0U, 1U)), RenameAs(0U),
+ : IndexPlusCost(std::make_pair(0U, 1U)), RenameAs(0U), AliasRegID(0U),
AllowMoveElimination(false) {}
};
Modified: llvm/trunk/tools/llvm-mca/lib/HardwareUnits/RegisterFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/lib/HardwareUnits/RegisterFile.cpp?rev=344392&r1=344391&r2=344392&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/lib/HardwareUnits/RegisterFile.cpp (original)
+++ llvm/trunk/tools/llvm-mca/lib/HardwareUnits/RegisterFile.cpp Fri Oct 12 11:18:53 2018
@@ -171,7 +171,8 @@ void RegisterFile::addRegisterWrite(Writ
// implicitly clears the upper portion of the underlying register.
// If a write clears its super-registers, then it is renamed as `RenameAs`.
bool IsWriteZero = WS.isWriteZero();
- bool ShouldAllocatePhysRegs = !IsWriteZero;
+ bool IsEliminated = WS.isEliminated();
+ bool ShouldAllocatePhysRegs = !IsWriteZero && !IsEliminated;
const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
if (RRI.RenameAs && RRI.RenameAs != RegID) {
@@ -187,6 +188,7 @@ void RegisterFile::addRegisterWrite(Writ
if (OtherWrite.getWriteState() &&
(OtherWrite.getSourceIndex() != Write.getSourceIndex())) {
// This partial write has a false dependency on RenameAs.
+ assert(!IsEliminated && "Unexpected partial update!");
WS.setDependentWrite(OtherWrite.getWriteState());
}
}
@@ -205,22 +207,33 @@ void RegisterFile::addRegisterWrite(Writ
ZeroRegisters.clearBit(*I);
}
- // Update the mapping for register RegID including its sub-registers.
- RegisterMappings[RegID].first = Write;
- for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I)
- RegisterMappings[*I].first = Write;
-
- // No physical registers are allocated for instructions that are optimized in
- // hardware. For example, zero-latency data-dependency breaking instructions
- // don't consume physical registers.
- if (ShouldAllocatePhysRegs)
- allocatePhysRegs(RegisterMappings[RegID].second, UsedPhysRegs);
+ // If this is move has been eliminated, then the call to tryEliminateMove
+ // should have already updated all the register mappings.
+ if (!IsEliminated) {
+ // Update the mapping for register RegID including its sub-registers.
+ RegisterMappings[RegID].first = Write;
+ RegisterMappings[RegID].second.AliasRegID = 0U;
+ for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I) {
+ RegisterMappings[*I].first = Write;
+ RegisterMappings[*I].second.AliasRegID = 0U;
+ }
+
+ // No physical registers are allocated for instructions that are optimized in
+ // hardware. For example, zero-latency data-dependency breaking instructions
+ // don't consume physical registers.
+ if (ShouldAllocatePhysRegs)
+ allocatePhysRegs(RegisterMappings[RegID].second, UsedPhysRegs);
+ }
if (!WS.clearsSuperRegisters())
return;
for (MCSuperRegIterator I(RegID, &MRI); I.isValid(); ++I) {
- RegisterMappings[*I].first = Write;
+ if (!IsEliminated) {
+ RegisterMappings[*I].first = Write;
+ RegisterMappings[*I].second.AliasRegID = 0U;
+ }
+
if (IsWriteZero)
ZeroRegisters.setBit(*I);
else
@@ -230,6 +243,11 @@ void RegisterFile::addRegisterWrite(Writ
void RegisterFile::removeRegisterWrite(
const WriteState &WS, MutableArrayRef<unsigned> FreedPhysRegs) {
+ // Early exit if this write was eliminated. A write eliminated at register
+ // renaming stage generates an alias, and it is not added to the PRF.
+ if (WS.isEliminated())
+ return;
+
unsigned RegID = WS.getRegisterID();
assert(RegID != 0 && "Invalidating an already invalid register?");
@@ -313,10 +331,29 @@ bool RegisterFile::tryEliminateMove(Writ
if (RMT.AllowZeroMoveEliminationOnly && !IsZeroMove)
return false;
+ MCPhysReg FromReg = RS.getRegisterID();
+ MCPhysReg ToReg = WS.getRegisterID();
+
+ // Construct an alias.
+ MCPhysReg AliasReg = FromReg;
+ if (RRIFrom.RenameAs)
+ AliasReg = RRIFrom.RenameAs;
+
+ const RegisterRenamingInfo &RMAlias = RegisterMappings[AliasReg].second;
+ if (RMAlias.AliasRegID)
+ AliasReg = RMAlias.AliasRegID;
+
+ if (AliasReg != ToReg) {
+ RegisterMappings[ToReg].second.AliasRegID = AliasReg;
+ for (MCSubRegIterator I(ToReg, &MRI); I.isValid(); ++I)
+ RegisterMappings[*I].second.AliasRegID = AliasReg;
+ }
+
RMT.NumMoveEliminated++;
if (IsZeroMove)
WS.setWriteZero();
WS.setEliminated();
+
return true;
}
@@ -325,6 +362,12 @@ void RegisterFile::collectWrites(SmallVe
assert(RegID && RegID < RegisterMappings.size());
LLVM_DEBUG(dbgs() << "RegisterFile: collecting writes for register "
<< MRI.getName(RegID) << '\n');
+
+ // Check if this is an alias.
+ const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
+ if (RRI.AliasRegID)
+ RegID = RRI.AliasRegID;
+
const WriteRef &WR = RegisterMappings[RegID].first;
if (WR.isValid())
Writes.push_back(WR);
Modified: llvm/trunk/tools/llvm-mca/lib/Stages/DispatchStage.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/lib/Stages/DispatchStage.cpp?rev=344392&r1=344391&r2=344392&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/lib/Stages/DispatchStage.cpp (original)
+++ llvm/trunk/tools/llvm-mca/lib/Stages/DispatchStage.cpp Fri Oct 12 11:18:53 2018
@@ -101,10 +101,11 @@ Error DispatchStage::dispatch(InstRef IR
}
// Check if this is an optimizable reg-reg move.
+ bool IsEliminated = false;
if (IS.isOptimizableMove()) {
assert(IS.getDefs().size() == 1 && "Expected a single input!");
assert(IS.getUses().size() == 1 && "Expected a single output!");
- PRF.tryEliminateMove(*IS.getDefs()[0], *IS.getUses()[0]);
+ IsEliminated = PRF.tryEliminateMove(*IS.getDefs()[0], *IS.getUses()[0]);
}
// A dependency-breaking instruction doesn't have to wait on the register
@@ -113,9 +114,15 @@ Error DispatchStage::dispatch(InstRef IR
// instruction. A dependency-breaking instruction is a zero-latency
// instruction that doesn't consume hardware resources.
// An example of dependency-breaking instruction on X86 is a zero-idiom XOR.
- for (std::unique_ptr<ReadState> &RS : IS.getUses())
- if (!RS->isIndependentFromDef())
- updateRAWDependencies(*RS, STI);
+ //
+ // We also don't update data dependencies for instructions that have been
+ // eliminated at register renaming stage.
+ if (!IsEliminated) {
+ for (std::unique_ptr<ReadState> &RS : IS.getUses()) {
+ if (!RS->isIndependentFromDef())
+ updateRAWDependencies(*RS, STI);
+ }
+ }
// By default, a dependency-breaking zero-idiom is expected to be optimized
// at register renaming stage. That means, no physical register is allocated
More information about the llvm-commits
mailing list