Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions llvm/include/llvm/CodeGen/TargetRegisterInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,15 @@ class TargetRegisterClass {
return MC->contains(Reg1.asMCReg(), Reg2.asMCReg());
}

/// Return the cost of copying a value between two registers in this class.
/// A negative number means the register class is very expensive
/// to copy e.g. status flag register classes.
int getCopyCost() const { return MC->getCopyCost(); }
/// Return the cost of copying a value between two registers in this class. If
/// this is the maximum value, the register may be impossible to copy.
uint8_t getCopyCost() const { return MC->getCopyCost(); }

/// \return true if register class is very expensive to copy e.g. status flag
/// register classes.
bool expensiveOrImpossibleToCopy() const {
return MC->getCopyCost() == std::numeric_limits<uint8_t>::max();
}

/// Return true if this register class may be used to create virtual
/// registers.
Expand Down
4 changes: 2 additions & 2 deletions llvm/include/llvm/MC/MCRegisterInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class MCRegisterClass {
const uint16_t RegSetSize;
const uint16_t ID;
const uint16_t RegSizeInBits;
const int8_t CopyCost;
const uint8_t CopyCost;
const bool Allocatable;
const bool BaseClass;

Expand Down Expand Up @@ -94,7 +94,7 @@ class MCRegisterClass {
/// getCopyCost - Return the cost of copying a value between two registers in
/// this class. A negative number means the register class is very expensive
/// to copy e.g. status flag register classes.
int getCopyCost() const { return CopyCost; }
uint8_t getCopyCost() const { return CopyCost; }

/// isAllocatable - Return true if this register class may be used to create
/// virtual registers.
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ void InstrEmitter::EmitCopyFromReg(SDValue Op, bool IsClone, Register SrcReg,

// If all uses are reading from the src physical register and copying the
// register is either impossible or very expensive, then don't create a copy.
if (MatchReg && SrcRC->getCopyCost() < 0) {
if (MatchReg && SrcRC->expensiveOrImpossibleToCopy()) {
VRBase = SrcReg;
} else {
// Create the reg, emit the copy.
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ static void CheckForPhysRegDependency(SDNode *Def, SDNode *User, unsigned Op,
if (PhysReg) {
const TargetRegisterClass *RC =
TRI->getMinimalPhysRegClass(Reg, Def->getSimpleValueType(ResNo));
Cost = RC->getCopyCost();
Cost = RC->expensiveOrImpossibleToCopy() ? -1 : RC->getCopyCost();
}
}

Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/AMDGPU/SIISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18879,7 +18879,7 @@ bool SITargetLowering::checkForPhysRegDependency(
PhysReg = AMDGPU::SCC;
const TargetRegisterClass *RC =
TRI->getMinimalPhysRegClass(PhysReg, Def->getSimpleValueType(ResNo));
Cost = RC->getCopyCost();
Cost = RC->expensiveOrImpossibleToCopy() ? -1 : RC->getCopyCost();
return true;
}
return false;
Expand Down
31 changes: 31 additions & 0 deletions llvm/test/TableGen/RegisterClassCopyCost.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// RUN: llvm-tblgen --gen-register-info -I %p/../../include %s 2>&1 | FileCheck %s
// RUN: not llvm-tblgen --gen-register-info -I %p/../../include -DERROR %s 2>&1 | FileCheck -check-prefix=ERROR %s

// Check that there is no assertion when specifying unsupported
// CopyCost values on register classes. Check that negative CopyCost
// values are saturated to 255.

include "llvm/Target/Target.td"

// CHECK: extern const MCRegisterClass MyTargetMCRegisterClasses[] = {
// CHECK-NEXT: { GPR32, GPR32Bits, 0, 2, sizeof(GPR32Bits), MyTarget::GPR32RegClassID, 32, 1, true, false },
// CHECK-NEXT: { SPECIAL_CLASS, SPECIAL_CLASSBits, 6, 1, sizeof(SPECIAL_CLASSBits), MyTarget::SPECIAL_CLASSRegClassID, 32, 255, true, false },
// CHECK-NEXT: };

def MyTargetISA : InstrInfo;
def MyTarget : Target { let InstructionSet = MyTargetISA; }

def R0 : Register<"r0"> { let Namespace = "MyTarget"; }
def R1 : Register<"r1"> { let Namespace = "MyTarget"; }
def SPECIAL : Register<"special"> { let Namespace = "MyTarget"; }

// ERROR: :[[@LINE+1]]:5: error: 'CopyCost' must be an 8-bit value
def GPR32 : RegisterClass<"MyTarget", [i32], 32, (add R0, R1)> {
#ifdef ERROR
let CopyCost = 256;
#endif
}

def SPECIAL_CLASS : RegisterClass<"MyTarget", [i32], 32, (add SPECIAL)> {
let CopyCost = -1;
}
10 changes: 9 additions & 1 deletion llvm/utils/TableGen/Common/CodeGenRegisters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -744,7 +744,7 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank,
RSI.insertRegSizeForMode(DefaultMode, RI);
}

CopyCost = R->getValueAsInt("CopyCost");
int CopyCostParsed = R->getValueAsInt("CopyCost");
Allocatable = R->getValueAsBit("isAllocatable");
AltOrderSelect = R->getValueAsString("AltOrderSelect");
int AllocationPriority = R->getValueAsInt("AllocationPriority");
Expand All @@ -757,6 +757,14 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank,
const BitsInit *TSF = R->getValueAsBitsInit("TSFlags");
for (auto [Idx, Bit] : enumerate(TSF->getBits()))
TSFlags |= uint8_t(cast<BitInit>(Bit)->getValue()) << Idx;

// Saturate negative costs to the maximum
if (CopyCostParsed < 0)
CopyCost = std::numeric_limits<uint8_t>::max();
else if (!isUInt<8>(CopyCostParsed))
PrintFatalError(R->getLoc(), "'CopyCost' must be an 8-bit value");

CopyCost = CopyCostParsed;
}

// Create an inferred register class that was missing from the .td files.
Expand Down
2 changes: 1 addition & 1 deletion llvm/utils/TableGen/Common/CodeGenRegisters.h
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ class CodeGenRegisterClass {
StringRef Namespace;
SmallVector<ValueTypeByHwMode, 4> VTs;
RegSizeInfoByHwMode RSI;
int CopyCost;
uint8_t CopyCost;
bool Allocatable;
StringRef AltOrderSelect;
uint8_t AllocationPriority;
Expand Down
3 changes: 1 addition & 2 deletions llvm/utils/TableGen/RegisterInfoEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1083,14 +1083,13 @@ void RegisterInfoEmitter::runMCDesc(raw_ostream &OS) {
std::string RCName = Order.empty() ? "nullptr" : RC.getName();
std::string RCBitsName = Order.empty() ? "nullptr" : RC.getName() + "Bits";
std::string RCBitsSize = Order.empty() ? "0" : "sizeof(" + RCBitsName + ")";
assert(isInt<8>(RC.CopyCost) && "Copy cost too large.");
uint32_t RegSize = 0;
if (RC.RSI.isSimple())
RegSize = RC.RSI.getSimple().RegSize;
OS << " { " << RCName << ", " << RCBitsName << ", "
<< RegClassStrings.get(RC.getName()) << ", " << RC.getOrder().size()
<< ", " << RCBitsSize << ", " << RC.getQualifiedIdName() << ", "
<< RegSize << ", " << RC.CopyCost << ", "
<< RegSize << ", " << static_cast<unsigned>(RC.CopyCost) << ", "
<< (RC.Allocatable ? "true" : "false") << ", "
<< (RC.getBaseClassOrder() ? "true" : "false") << " },\n";
}
Expand Down