Skip to content
Open
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
22 changes: 22 additions & 0 deletions llvm/include/llvm/CodeGen/SelectionDAGISel.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ class SelectionDAGISel {
bool MatchFilterFuncName = false;
StringRef FuncName;

unsigned HwMode;

explicit SelectionDAGISel(TargetMachine &tm,
CodeGenOptLevel OL = CodeGenOptLevel::Default);
virtual ~SelectionDAGISel();
Expand Down Expand Up @@ -202,7 +204,9 @@ class SelectionDAGISel {
// Space-optimized forms that implicitly encode VT.
OPC_CheckTypeI32,
OPC_CheckTypeI64,
OPC_CheckTypeByHwMode,
OPC_CheckTypeRes,
OPC_CheckTypeResByHwMode,
OPC_SwitchType,
OPC_CheckChild0Type,
OPC_CheckChild1Type,
Expand Down Expand Up @@ -231,6 +235,15 @@ class SelectionDAGISel {
OPC_CheckChild6TypeI64,
OPC_CheckChild7TypeI64,

OPC_CheckChild0TypeByHwMode,
OPC_CheckChild1TypeByHwMode,
OPC_CheckChild2TypeByHwMode,
OPC_CheckChild3TypeByHwMode,
OPC_CheckChild4TypeByHwMode,
OPC_CheckChild5TypeByHwMode,
OPC_CheckChild6TypeByHwMode,
OPC_CheckChild7TypeByHwMode,

OPC_CheckInteger,
OPC_CheckChild0Integer,
OPC_CheckChild1Integer,
Expand Down Expand Up @@ -261,10 +274,13 @@ class SelectionDAGISel {
OPC_EmitIntegerI16,
OPC_EmitIntegerI32,
OPC_EmitIntegerI64,
OPC_EmitIntegerByHwMode,
OPC_EmitRegister,
OPC_EmitRegisterI32,
OPC_EmitRegisterI64,
OPC_EmitRegisterByHwMode,
OPC_EmitRegister2,
OPC_EmitRegisterByHwMode2,
OPC_EmitConvertToTarget,
OPC_EmitConvertToTarget0,
OPC_EmitConvertToTarget1,
Expand All @@ -290,6 +306,7 @@ class SelectionDAGISel {
OPC_EmitCopyToRegTwoByte,
OPC_EmitNodeXForm,
OPC_EmitNode,
OPC_EmitNodeByHwMode,
// Space-optimized forms that implicitly encode number of result VTs.
OPC_EmitNode0,
OPC_EmitNode1,
Expand All @@ -302,6 +319,7 @@ class SelectionDAGISel {
OPC_EmitNode1Chain,
OPC_EmitNode2Chain,
OPC_MorphNodeTo,
OPC_MorphNodeToByHwMode,
// Space-optimized forms that implicitly encode number of result VTs.
OPC_MorphNodeTo0,
OPC_MorphNodeTo1,
Expand Down Expand Up @@ -448,6 +466,10 @@ class SelectionDAGISel {
llvm_unreachable("Tblgen should generate this!");
}

virtual MVT getValueTypeByHwMode(unsigned Index) const {
llvm_unreachable("Tblgen should generate the implementation of this!");
}

void SelectCodeCommon(SDNode *NodeToMatch, const uint8_t *MatcherTable,
unsigned TableSize);

Expand Down
123 changes: 117 additions & 6 deletions llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,8 @@ void SelectionDAGISel::initializeAnalysisResults(
SP = &FAM.getResult<SSPLayoutAnalysis>(Fn);

TTI = &FAM.getResult<TargetIRAnalysis>(Fn);

HwMode = MF->getSubtarget().getHwMode();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is supposed to be queried with a specific hw mode kind (which seems to be a stalled project from who knows when)

Copy link
Collaborator Author

@topperc topperc Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, ValueTypeByHwMode and RegClassInfo/RegClassByHwMode use different hw mode kinds but they both affect the VT in CodeGenDAGPatterns so I don't how to make that work.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed this as well in my recent tablegen changes and am not really sure why it is useful to have separate namespaces for this. It seems to be basically the same anyway?

}

void SelectionDAGISel::initializeAnalysisResults(MachineFunctionPass &MFP) {
Expand Down Expand Up @@ -588,6 +590,8 @@ void SelectionDAGISel::initializeAnalysisResults(MachineFunctionPass &MFP) {
SP = &MFP.getAnalysis<StackProtector>().getLayoutInfo();

TTI = &MFP.getAnalysis<TargetTransformInfoWrapperPass>().getTTI(Fn);

HwMode = MF->getSubtarget().getHwMode();
}

bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) {
Expand Down Expand Up @@ -2747,6 +2751,18 @@ getSimpleVT(const uint8_t *MatcherTable, unsigned &MatcherIndex) {
return static_cast<MVT::SimpleValueType>(SimpleVT);
}

/// getSimpleVT - Decode a value in MatcherTable, if it's a VBR encoded value,
/// use GetVBR to decode it.
LLVM_ATTRIBUTE_ALWAYS_INLINE static MVT
getHwModeVT(const uint8_t *MatcherTable, unsigned &MatcherIndex,
const SelectionDAGISel &SDISel) {
unsigned Index = MatcherTable[MatcherIndex++];
if (Index & 128)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible that we have such a large Index?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I doubt. I can make it a fatal error in tablegen if you want.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it is always small, I prefer to to make it fixed to save some compile time.

Index = GetVBR(Index, MatcherTable, MatcherIndex);

return SDISel.getValueTypeByHwMode(Index);
}

void SelectionDAGISel::Select_JUMP_TABLE_DEBUG_INFO(SDNode *N) {
SDLoc dl(N);
CurDAG->SelectNodeTo(N, TargetOpcode::JUMP_TABLE_DEBUG_INFO, MVT::Glue,
Expand Down Expand Up @@ -3150,12 +3166,25 @@ static unsigned IsPredicateKnownToFail(
Result = !::CheckType(VT, N, SDISel.TLI, SDISel.CurDAG->getDataLayout());
return Index;
}
case SelectionDAGISel::OPC_CheckTypeByHwMode: {
MVT VT = getHwModeVT(Table, Index, SDISel);
Result = !::CheckType(VT.SimpleTy, N, SDISel.TLI,
SDISel.CurDAG->getDataLayout());
return Index;
}
case SelectionDAGISel::OPC_CheckTypeRes: {
unsigned Res = Table[Index++];
Result = !::CheckType(getSimpleVT(Table, Index), N.getValue(Res),
SDISel.TLI, SDISel.CurDAG->getDataLayout());
return Index;
}
case SelectionDAGISel::OPC_CheckTypeResByHwMode: {
unsigned Res = Table[Index++];
MVT VT = getHwModeVT(Table, Index, SDISel);
Result = !::CheckType(VT.SimpleTy, N.getValue(Res), SDISel.TLI,
SDISel.CurDAG->getDataLayout());
return Index;
}
case SelectionDAGISel::OPC_CheckChild0Type:
case SelectionDAGISel::OPC_CheckChild1Type:
case SelectionDAGISel::OPC_CheckChild2Type:
Expand Down Expand Up @@ -3198,6 +3227,20 @@ static unsigned IsPredicateKnownToFail(
SDISel.CurDAG->getDataLayout(), ChildNo);
return Index;
}
case SelectionDAGISel::OPC_CheckChild0TypeByHwMode:
case SelectionDAGISel::OPC_CheckChild1TypeByHwMode:
case SelectionDAGISel::OPC_CheckChild2TypeByHwMode:
case SelectionDAGISel::OPC_CheckChild3TypeByHwMode:
case SelectionDAGISel::OPC_CheckChild4TypeByHwMode:
case SelectionDAGISel::OPC_CheckChild5TypeByHwMode:
case SelectionDAGISel::OPC_CheckChild6TypeByHwMode:
case SelectionDAGISel::OPC_CheckChild7TypeByHwMode: {
MVT VT = getHwModeVT(Table, Index, SDISel);
unsigned ChildNo = Opcode - SelectionDAGISel::OPC_CheckChild0TypeByHwMode;
Result = !::CheckChildType(VT.SimpleTy, N, SDISel.TLI,
SDISel.CurDAG->getDataLayout(), ChildNo);
return Index;
}
case SelectionDAGISel::OPC_CheckCondCode:
Result = !::CheckCondCode(Table, Index, N);
return Index;
Expand Down Expand Up @@ -3718,6 +3761,12 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,
break;
continue;
}
case OPC_CheckTypeByHwMode: {
MVT VT = getHwModeVT(MatcherTable, MatcherIndex, *this);
if (!::CheckType(VT.SimpleTy, N, TLI, CurDAG->getDataLayout()))
break;
continue;
}

case OPC_CheckTypeRes: {
unsigned Res = MatcherTable[MatcherIndex++];
Expand All @@ -3726,6 +3775,14 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,
break;
continue;
}
case OPC_CheckTypeResByHwMode: {
unsigned Res = MatcherTable[MatcherIndex++];
MVT VT = getHwModeVT(MatcherTable, MatcherIndex, *this);
if (!::CheckType(VT.SimpleTy, N.getValue(Res), TLI,
CurDAG->getDataLayout()))
break;
continue;
}

case OPC_SwitchOpcode: {
unsigned CurNodeOpcode = N.getOpcode();
Expand Down Expand Up @@ -3832,6 +3889,21 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,
break;
continue;
}
case OPC_CheckChild0TypeByHwMode:
case OPC_CheckChild1TypeByHwMode:
case OPC_CheckChild2TypeByHwMode:
case OPC_CheckChild3TypeByHwMode:
case OPC_CheckChild4TypeByHwMode:
case OPC_CheckChild5TypeByHwMode:
case OPC_CheckChild6TypeByHwMode:
case OPC_CheckChild7TypeByHwMode: {
MVT VT = getHwModeVT(MatcherTable, MatcherIndex, *this);
unsigned ChildNo = Opcode - OPC_CheckChild0TypeByHwMode;
if (!::CheckChildType(VT.SimpleTy, N, TLI, CurDAG->getDataLayout(),
ChildNo))
break;
continue;
}
case OPC_CheckCondCode:
if (!::CheckCondCode(MatcherTable, MatcherIndex, N)) break;
continue;
Expand Down Expand Up @@ -3920,12 +3992,24 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,
break;
}
int64_t Val = GetSignedVBR(MatcherTable, MatcherIndex);
Val = SignExtend64(Val, MVT(VT).getFixedSizeInBits());
RecordedNodes.emplace_back(
CurDAG->getSignedConstant(Val, SDLoc(NodeToMatch), VT,
/*isTarget=*/true),
nullptr);
continue;
}
case OPC_EmitIntegerByHwMode: {
MVT VT = getHwModeVT(MatcherTable, MatcherIndex, *this);
int64_t Val = GetSignedVBR(MatcherTable, MatcherIndex);
Val = SignExtend64(Val, MVT(VT).getFixedSizeInBits());
RecordedNodes.emplace_back(
CurDAG->getSignedConstant(Val, SDLoc(NodeToMatch), VT.SimpleTy,
/*isTarget=*/true),
nullptr);
continue;
}

case OPC_EmitRegister:
case OPC_EmitRegisterI32:
case OPC_EmitRegisterI64: {
Expand All @@ -3945,6 +4029,12 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,
RecordedNodes.emplace_back(CurDAG->getRegister(RegNo, VT), nullptr);
continue;
}
case OPC_EmitRegisterByHwMode: {
MVT VT = getHwModeVT(MatcherTable, MatcherIndex, *this);
unsigned RegNo = MatcherTable[MatcherIndex++];
RecordedNodes.emplace_back(CurDAG->getRegister(RegNo, VT), nullptr);
continue;
}
case OPC_EmitRegister2: {
// For targets w/ more than 256 register names, the register enum
// values are stored in two bytes in the matcher table (just like
Expand All @@ -3955,6 +4045,16 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,
RecordedNodes.emplace_back(CurDAG->getRegister(RegNo, VT), nullptr);
continue;
}
case OPC_EmitRegisterByHwMode2: {
// For targets w/ more than 256 register names, the register enum
// values are stored in two bytes in the matcher table (just like
// opcodes).
MVT VT = getHwModeVT(MatcherTable, MatcherIndex, *this);
unsigned RegNo = MatcherTable[MatcherIndex++];
RegNo |= MatcherTable[MatcherIndex++] << 8;
RecordedNodes.emplace_back(CurDAG->getRegister(RegNo, VT), nullptr);
continue;
}

case OPC_EmitConvertToTarget:
case OPC_EmitConvertToTarget0:
Expand Down Expand Up @@ -4114,6 +4214,7 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,
}

case OPC_EmitNode:
case OPC_EmitNodeByHwMode:
case OPC_EmitNode0:
case OPC_EmitNode1:
case OPC_EmitNode2:
Expand All @@ -4124,6 +4225,7 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,
case OPC_EmitNode1Chain:
case OPC_EmitNode2Chain:
case OPC_MorphNodeTo:
case OPC_MorphNodeToByHwMode:
case OPC_MorphNodeTo0:
case OPC_MorphNodeTo1:
case OPC_MorphNodeTo2:
Expand Down Expand Up @@ -4187,11 +4289,20 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,
else
NumVTs = MatcherTable[MatcherIndex++];
SmallVector<EVT, 4> VTs;
for (unsigned i = 0; i != NumVTs; ++i) {
MVT::SimpleValueType VT = getSimpleVT(MatcherTable, MatcherIndex);
if (VT == MVT::iPTR)
VT = TLI->getPointerTy(CurDAG->getDataLayout()).SimpleTy;
VTs.push_back(VT);
if (Opcode == OPC_EmitNodeByHwMode || Opcode == OPC_MorphNodeToByHwMode) {
for (unsigned i = 0; i != NumVTs; ++i) {
MVT VT = getHwModeVT(MatcherTable, MatcherIndex, *this);
if (VT == MVT::iPTR)
VT = TLI->getPointerTy(CurDAG->getDataLayout());
VTs.push_back(VT);
}
} else {
for (unsigned i = 0; i != NumVTs; ++i) {
MVT::SimpleValueType VT = getSimpleVT(MatcherTable, MatcherIndex);
if (VT == MVT::iPTR)
VT = TLI->getPointerTy(CurDAG->getDataLayout()).SimpleTy;
VTs.push_back(VT);
}
}

if (EmitNodeInfo & OPFL_Chain)
Expand Down Expand Up @@ -4258,7 +4369,7 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,
// Create the node.
MachineSDNode *Res = nullptr;
bool IsMorphNodeTo =
Opcode == OPC_MorphNodeTo ||
Opcode == OPC_MorphNodeTo || Opcode == OPC_MorphNodeToByHwMode ||
(Opcode >= OPC_MorphNodeTo0 && Opcode <= OPC_MorphNodeTo2GlueOutput);
if (!IsMorphNodeTo) {
// If this is a normal EmitNode command, just create the new node and
Expand Down
52 changes: 5 additions & 47 deletions llvm/test/TableGen/RegClassByHwMode.td
Original file line number Diff line number Diff line change
Expand Up @@ -192,66 +192,24 @@ include "Common/RegClassByHwModeCommon.td"
// ISEL-SDAG-NEXT: OPC_RecordMemRef,
// ISEL-SDAG-NEXT: OPC_RecordNode, // #0 = 'st' chained node
// ISEL-SDAG-NEXT: OPC_RecordChild1, // #1 = $val
// ISEL-SDAG-NEXT: OPC_CheckChild1TypeI64,
// ISEL-SDAG-NEXT: OPC_CheckChild1TypeByHwMode, /*{(*:i64),(m1:i64),(m2:i64)}*/0,
// ISEL-SDAG-NEXT: OPC_RecordChild2, // #2 = $src
// ISEL-SDAG-NEXT: OPC_Scope, {{[0-9]+}}, /*->{{[0-9]+}}*/ // 2 children in Scope
// ISEL-SDAG-NEXT: OPC_CheckChild2TypeI32,
// ISEL-SDAG-NEXT: OPC_CheckChild2TypeByHwMode, /*{(*:i32),(m3:i64)}*/1,
// ISEL-SDAG-NEXT: OPC_CheckPredicate0, // Predicate_unindexedstore
// ISEL-SDAG-NEXT: OPC_CheckPredicate1, // Predicate_store
// ISEL-SDAG-NEXT: OPC_Scope, {{[0-9]+}}, /*->{{[0-9]+}}*/ // 3 children in Scope
// ISEL-SDAG-NEXT: OPC_CheckPatternPredicate0, // (Subtarget->hasAlignedRegisters())
// ISEL-SDAG-NEXT: OPC_EmitMergeInputChains1_0,
// ISEL-SDAG-NEXT: OPC_MorphNodeTo0, TARGET_VAL(MyTarget::MY_STORE), 0|OPFL_Chain|OPFL_MemRefs,

// ISEL-SDAG: /*Scope*/
// ISEL-SDAG: OPC_CheckPatternPredicate1, // (Subtarget->hasUnalignedRegisters())
// ISEL-SDAG-NEXT: OPC_EmitMergeInputChains1_0,
// ISEL-SDAG-NEXT: OPC_MorphNodeTo0, TARGET_VAL(MyTarget::MY_STORE), 0|OPFL_Chain|OPFL_MemRefs,

// ISEL-SDAG: /*Scope*/
// ISEL-SDAG: OPC_CheckPatternPredicate2, // !((Subtarget->hasAlignedRegisters())) && !((Subtarget->hasUnalignedRegisters())) && !((Subtarget->isPtr64()))
// ISEL-SDAG-NEXT: OPC_EmitMergeInputChains1_0,
// ISEL-SDAG-NEXT: OPC_MorphNodeTo0, TARGET_VAL(MyTarget::MY_STORE), 0|OPFL_Chain|OPFL_MemRefs,

// ISEL-SDAG: /*Scope*/
// ISEL-SDAG-NEXT: OPC_CheckChild2TypeI64,
// ISEL-SDAG-NEXT: OPC_CheckPredicate0, // Predicate_unindexedstore
// ISEL-SDAG-NEXT: OPC_CheckPredicate1, // Predicate_store
// ISEL-SDAG-NEXT: OPC_CheckPatternPredicate3, // (Subtarget->isPtr64())
// ISEL-SDAG-NEXT: OPC_EmitMergeInputChains1_0,
// ISEL-SDAG-NEXT: OPC_MorphNodeTo0, TARGET_VAL(MyTarget::MY_STORE), 0|OPFL_Chain|OPFL_MemRefs,

// ISEL-SDAG: /*SwitchOpcode*/ {{[0-9]+}}, TARGET_VAL(ISD::LOAD),
// ISEL-SDAG-NEXT: OPC_RecordMemRef,
// ISEL-SDAG-NEXT: OPC_RecordNode, // #0 = 'ld' chained node
// ISEL-SDAG-NEXT: OPC_RecordChild1, // #1 = $src
// ISEL-SDAG-NEXT: OPC_CheckTypeI64,
// ISEL-SDAG-NEXT: OPC_Scope, {{[0-9]+}}, /*->{{[0-9]+}}*/ // 2 children in Scope
// ISEL-SDAG-NEXT: OPC_CheckChild1TypeI32,
// ISEL-SDAG-NEXT: OPC_CheckPredicate2, // Predicate_unindexedload
// ISEL-SDAG-NEXT: OPC_CheckPredicate3, // Predicate_load
// ISEL-SDAG-NEXT: OPC_Scope, {{[0-9]+}}, /*->{{[0-9]+}}*/ // 3 children in Scope
// ISEL-SDAG-NEXT: OPC_CheckPatternPredicate0, // (Subtarget->hasAlignedRegisters())
// ISEL-SDAG-NEXT: OPC_EmitMergeInputChains1_0,
// ISEL-SDAG-NEXT: OPC_MorphNodeTo1, TARGET_VAL(MyTarget::MY_LOAD), 0|OPFL_Chain|OPFL_MemRefs,

// ISEL-SDAG: /*Scope*/
// ISEL-SDAG: OPC_CheckPatternPredicate1, // (Subtarget->hasUnalignedRegisters())
// ISEL-SDAG-NEXT: OPC_EmitMergeInputChains1_0,
// ISEL-SDAG-NEXT: OPC_MorphNodeTo1, TARGET_VAL(MyTarget::MY_LOAD), 0|OPFL_Chain|OPFL_MemRefs,

// ISEL-SDAG: /*Scope*/
// ISEL-SDAG: OPC_CheckPatternPredicate2, // !((Subtarget->hasAlignedRegisters())) && !((Subtarget->hasUnalignedRegisters())) && !((Subtarget->isPtr64()))
// ISEL-SDAG-NEXT: OPC_EmitMergeInputChains1_0,
// ISEL-SDAG-NEXT: OPC_MorphNodeTo1, TARGET_VAL(MyTarget::MY_LOAD), 0|OPFL_Chain|OPFL_MemRefs,

// ISEL-SDAG: /*Scope*/
// ISEL-SDAG-NEXT: OPC_CheckChild1TypeI64,
// ISEL-SDAG-NEXT: OPC_CheckChild1TypeByHwMode, /*{(*:i32),(m3:i64)}*/1,
// ISEL-SDAG-NEXT: OPC_CheckPredicate2, // Predicate_unindexedload
// ISEL-SDAG-NEXT: OPC_CheckPredicate3, // Predicate_load
// ISEL-SDAG-NEXT: OPC_CheckPatternPredicate3, // (Subtarget->isPtr64())
// ISEL-SDAG-NEXT: OPC_CheckTypeI64,
// ISEL-SDAG-NEXT: OPC_EmitMergeInputChains1_0,
// ISEL-SDAG-NEXT: OPC_MorphNodeTo1, TARGET_VAL(MyTarget::MY_LOAD), 0|OPFL_Chain|OPFL_MemRefs,
// ISEL-SDAG-NEXT: OPC_MorphNodeToByHwMode, TARGET_VAL(MyTarget::MY_LOAD), 0|OPFL_Chain|OPFL_MemRefs,



Expand Down
Loading