Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
d2220d7
Use ValueTypeByHwMode in PatternSortingPredicate.
topperc Dec 30, 2025
0649d2c
Use VVT in getPatternSize.
topperc Dec 30, 2025
2ca3b81
Move SignExtend64 for EmitInteger to isel.
topperc Dec 30, 2025
be086a3
[SelectionDAG][WIP] Move HwMode expansion from tablegen to SelectionI…
topperc Jan 5, 2026
32006c2
fixup! Fix missing checks for RegClassByHwMode.
topperc Jan 5, 2026
97e5bb0
fixup! clang-format
topperc Jan 6, 2026
80e54fe
Merge remote-tracking branch 'origin/main' into pr/valuetypebyhwmode
topperc Jan 6, 2026
4b3edca
Merge remote-tracking branch 'origin/main' into pr/valuetypebyhwmode
topperc Jan 8, 2026
1b54474
Merge remote-tracking branch 'origin/main' into pr/valuetypebyhwmode
topperc Jan 9, 2026
2a207fa
Add emitValueTypeByHwMode.
topperc Jan 9, 2026
3ed711a
fixup! clang-format
topperc Jan 9, 2026
31e3738
fixup! Refactor emission of Matcher::CheckType.
topperc Jan 9, 2026
8de22bf
Only allow 256 indices for the value type look up instead of using a …
topperc Jan 9, 2026
4c73031
fixup! clang-format
topperc Jan 9, 2026
c057b01
Merge remote-tracking branch 'origin/main' into pr/valuetypebyhwmode
topperc Jan 12, 2026
a06c618
fixup! fix include path after rebase.
topperc Jan 12, 2026
e8dd6fb
Merge remote-tracking branch 'origin/main' into pr/valuetypebyhwmode
topperc Jan 13, 2026
d9bbb63
fixup! address review comment
topperc Jan 13, 2026
8c4b460
fixup! Another review comment
topperc Jan 13, 2026
d3516a0
fixup! Address review comments
topperc Jan 14, 2026
c90a5d7
fixup! address review comment
topperc Jan 15, 2026
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
24 changes: 24 additions & 0 deletions llvm/include/llvm/CodeGen/SelectionDAGISel.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ class SelectionDAGISel {
bool MatchFilterFuncName = false;
StringRef FuncName;

// HwMode to be used by getValueTypeForHwMode. This will be initialized
// based on the subtarget used by the MachineFunction.
unsigned HwMode;

explicit SelectionDAGISel(TargetMachine &tm,
CodeGenOptLevel OL = CodeGenOptLevel::Default);
virtual ~SelectionDAGISel();
Expand Down Expand Up @@ -202,7 +206,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 +237,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 +276,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 +308,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 @@ -301,6 +320,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 @@ -444,6 +464,10 @@ class SelectionDAGISel {
llvm_unreachable("Tblgen should generate this!");
}

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

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

Expand Down
136 changes: 108 additions & 28 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,14 @@ getSimpleVT(const uint8_t *MatcherTable, unsigned &MatcherIndex) {
return static_cast<MVT::SimpleValueType>(SimpleVT);
}

/// Decode a HwMode VT in MatcherTable by calling getValueTypeForHwMode.
LLVM_ATTRIBUTE_ALWAYS_INLINE static MVT
getHwModeVT(const uint8_t *MatcherTable, unsigned &MatcherIndex,
const SelectionDAGISel &SDISel) {
unsigned Index = MatcherTable[MatcherIndex++];
return SDISel.getValueTypeForHwMode(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 @@ -3134,26 +3146,35 @@ static unsigned IsPredicateKnownToFail(
return Index;
case SelectionDAGISel::OPC_CheckType:
case SelectionDAGISel::OPC_CheckTypeI32:
case SelectionDAGISel::OPC_CheckTypeI64: {
MVT::SimpleValueType VT;
case SelectionDAGISel::OPC_CheckTypeI64:
case SelectionDAGISel::OPC_CheckTypeByHwMode: {
MVT VT;
switch (Opcode) {
case SelectionDAGISel::OPC_CheckTypeI32:
VT = MVT::i32;
break;
case SelectionDAGISel::OPC_CheckTypeI64:
VT = MVT::i64;
break;
case SelectionDAGISel::OPC_CheckTypeByHwMode:
VT = getHwModeVT(Table, Index, SDISel);
break;
default:
VT = getSimpleVT(Table, Index);
break;
}
Result = !::CheckType(VT, N, SDISel.TLI, SDISel.CurDAG->getDataLayout());
Result = !::CheckType(VT.SimpleTy, N, SDISel.TLI,
SDISel.CurDAG->getDataLayout());
return Index;
}
case SelectionDAGISel::OPC_CheckTypeRes: {
case SelectionDAGISel::OPC_CheckTypeRes:
case SelectionDAGISel::OPC_CheckTypeResByHwMode: {
unsigned Res = Table[Index++];
Result = !::CheckType(getSimpleVT(Table, Index), N.getValue(Res),
SDISel.TLI, SDISel.CurDAG->getDataLayout());
MVT VT = Opcode == SelectionDAGISel::OPC_CheckTypeResByHwMode
? getHwModeVT(Table, Index, SDISel)
: getSimpleVT(Table, Index);
Result = !::CheckType(VT.SimpleTy, N.getValue(Res), SDISel.TLI,
SDISel.CurDAG->getDataLayout());
return Index;
}
case SelectionDAGISel::OPC_CheckChild0Type:
Expand All @@ -3179,8 +3200,16 @@ static unsigned IsPredicateKnownToFail(
case SelectionDAGISel::OPC_CheckChild4TypeI64:
case SelectionDAGISel::OPC_CheckChild5TypeI64:
case SelectionDAGISel::OPC_CheckChild6TypeI64:
case SelectionDAGISel::OPC_CheckChild7TypeI64: {
MVT::SimpleValueType VT;
case SelectionDAGISel::OPC_CheckChild7TypeI64:
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;
unsigned ChildNo;
if (Opcode >= SelectionDAGISel::OPC_CheckChild0TypeI32 &&
Opcode <= SelectionDAGISel::OPC_CheckChild7TypeI32) {
Expand All @@ -3190,11 +3219,15 @@ static unsigned IsPredicateKnownToFail(
Opcode <= SelectionDAGISel::OPC_CheckChild7TypeI64) {
VT = MVT::i64;
ChildNo = Opcode - SelectionDAGISel::OPC_CheckChild0TypeI64;
} else if (Opcode >= SelectionDAGISel::OPC_CheckChild0TypeByHwMode &&
Opcode <= SelectionDAGISel::OPC_CheckChild7TypeByHwMode) {
VT = getHwModeVT(Table, Index, SDISel);
ChildNo = Opcode - SelectionDAGISel::OPC_CheckChild0TypeByHwMode;
} else {
VT = getSimpleVT(Table, Index);
ChildNo = Opcode - SelectionDAGISel::OPC_CheckChild0Type;
}
Result = !::CheckChildType(VT, N, SDISel.TLI,
Result = !::CheckChildType(VT.SimpleTy, N, SDISel.TLI,
SDISel.CurDAG->getDataLayout(), ChildNo);
return Index;
}
Expand Down Expand Up @@ -3701,28 +3734,36 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,

case OPC_CheckType:
case OPC_CheckTypeI32:
case OPC_CheckTypeI64: {
MVT::SimpleValueType VT;
case OPC_CheckTypeI64:
case OPC_CheckTypeByHwMode: {
MVT VT;
switch (Opcode) {
case OPC_CheckTypeI32:
VT = MVT::i32;
break;
case OPC_CheckTypeI64:
VT = MVT::i64;
break;
case OPC_CheckTypeByHwMode:
VT = getHwModeVT(MatcherTable, MatcherIndex, *this);
break;
default:
VT = getSimpleVT(MatcherTable, MatcherIndex);
break;
}
if (!::CheckType(VT, N, TLI, CurDAG->getDataLayout()))
if (!::CheckType(VT.SimpleTy, N, TLI, CurDAG->getDataLayout()))
break;
continue;
}

case OPC_CheckTypeRes: {
case OPC_CheckTypeRes:
case OPC_CheckTypeResByHwMode: {
unsigned Res = MatcherTable[MatcherIndex++];
if (!::CheckType(getSimpleVT(MatcherTable, MatcherIndex), N.getValue(Res),
TLI, CurDAG->getDataLayout()))
MVT VT = Opcode == OPC_CheckTypeResByHwMode
? getHwModeVT(MatcherTable, MatcherIndex, *this)
: getSimpleVT(MatcherTable, MatcherIndex);
if (!::CheckType(VT.SimpleTy, N.getValue(Res), TLI,
CurDAG->getDataLayout()))
break;
continue;
}
Expand Down Expand Up @@ -3832,6 +3873,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 @@ -3900,8 +3956,9 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,
case OPC_EmitIntegerI8:
case OPC_EmitIntegerI16:
case OPC_EmitIntegerI32:
case OPC_EmitIntegerI64: {
MVT::SimpleValueType VT;
case OPC_EmitIntegerI64:
case OPC_EmitIntegerByHwMode: {
MVT VT;
switch (Opcode) {
case OPC_EmitIntegerI8:
VT = MVT::i8;
Expand All @@ -3915,28 +3972,37 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,
case OPC_EmitIntegerI64:
VT = MVT::i64;
break;
case OPC_EmitIntegerByHwMode:
VT = getHwModeVT(MatcherTable, MatcherIndex, *this);
break;
default:
VT = getSimpleVT(MatcherTable, MatcherIndex);
break;
}
int64_t Val = GetSignedVBR(MatcherTable, MatcherIndex);
Val = SignExtend64(Val, MVT(VT).getFixedSizeInBits());
RecordedNodes.emplace_back(
CurDAG->getSignedConstant(Val, SDLoc(NodeToMatch), VT,
CurDAG->getSignedConstant(Val, SDLoc(NodeToMatch), VT.SimpleTy,
/*isTarget=*/true),
nullptr);
continue;
}

case OPC_EmitRegister:
case OPC_EmitRegisterI32:
case OPC_EmitRegisterI64: {
MVT::SimpleValueType VT;
case OPC_EmitRegisterI64:
case OPC_EmitRegisterByHwMode: {
MVT VT;
switch (Opcode) {
case OPC_EmitRegisterI32:
VT = MVT::i32;
break;
case OPC_EmitRegisterI64:
VT = MVT::i64;
break;
case OPC_EmitRegisterByHwMode:
VT = getHwModeVT(MatcherTable, MatcherIndex, *this);
break;
default:
VT = getSimpleVT(MatcherTable, MatcherIndex);
break;
Expand All @@ -3945,11 +4011,14 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,
RecordedNodes.emplace_back(CurDAG->getRegister(RegNo, VT), nullptr);
continue;
}
case OPC_EmitRegister2: {
case OPC_EmitRegister2:
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::SimpleValueType VT = getSimpleVT(MatcherTable, MatcherIndex);
MVT VT = Opcode == OPC_EmitRegisterByHwMode2
? getHwModeVT(MatcherTable, MatcherIndex, *this)
: getSimpleVT(MatcherTable, MatcherIndex);
unsigned RegNo = MatcherTable[MatcherIndex++];
RegNo |= MatcherTable[MatcherIndex++] << 8;
RecordedNodes.emplace_back(CurDAG->getRegister(RegNo, VT), nullptr);
Expand Down Expand Up @@ -4114,6 +4183,7 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,
}

case OPC_EmitNode:
case OPC_EmitNodeByHwMode:
case OPC_EmitNode0:
case OPC_EmitNode1:
case OPC_EmitNode2:
Expand All @@ -4123,6 +4193,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 @@ -4183,11 +4254,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 @@ -4254,7 +4334,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
Loading