[llvm] [SelectionDAG] Add space-optimized forms of OPC_EmitNode/OPC_MorphNodeTo (PR #73502)
Wang Pengcheng via llvm-commits
llvm-commits at lists.llvm.org
Mon Nov 27 03:15:32 PST 2023
https://github.com/wangpc-pp created https://github.com/llvm/llvm-project/pull/73502
If there is only one bit set in EmitNodeInfo, then we can encode it
implicitly to save one byte.
Overall this reduces the llc binary size with all in-tree targets by
about 168K.
>From 5e8ad81551af0d6b4755c17987626a3f1ac6291b Mon Sep 17 00:00:00 2001
From: wangpc <wangpengcheng.pp at bytedance.com>
Date: Mon, 27 Nov 2023 19:14:10 +0800
Subject: [PATCH] [SelectionDAG] Add space-optimized forms of
OPC_EmitNode/OPC_MorphNodeTo
If there is only one bit set in EmitNodeInfo, then we can encode it
implicitly to save one byte.
Overall this reduces the llc binary size with all in-tree targets by
about 168K.
---
llvm/include/llvm/CodeGen/SelectionDAGISel.h | 31 ++++++
.../CodeGen/SelectionDAG/SelectionDAGISel.cpp | 99 +++++++++++++++++--
llvm/test/TableGen/DAGDefaultOps.td | 10 +-
.../TableGen/dag-isel-regclass-emit-enum.td | 6 +-
llvm/test/TableGen/dag-isel-res-order.td | 2 +-
llvm/utils/TableGen/DAGISelMatcherEmitter.cpp | 52 +++++++---
6 files changed, 174 insertions(+), 26 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/SelectionDAGISel.h b/llvm/include/llvm/CodeGen/SelectionDAGISel.h
index e6513eb6abc8749..1793bad8116c831 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAGISel.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAGISel.h
@@ -204,6 +204,37 @@ class SelectionDAGISel : public MachineFunctionPass {
OPC_MorphNodeTo0,
OPC_MorphNodeTo1,
OPC_MorphNodeTo2,
+ // Space-optimized forms that implicitly encode EmitNodeInfo.
+ OPC_EmitNode0None,
+ OPC_EmitNode1None,
+ OPC_EmitNode2None,
+ OPC_MorphNodeTo0None,
+ OPC_MorphNodeTo1None,
+ OPC_MorphNodeTo2None,
+ OPC_EmitNode0Chain,
+ OPC_EmitNode1Chain,
+ OPC_EmitNode2Chain,
+ OPC_MorphNodeTo0Chain,
+ OPC_MorphNodeTo1Chain,
+ OPC_MorphNodeTo2Chain,
+ OPC_EmitNode0GlueInput,
+ OPC_EmitNode1GlueInput,
+ OPC_EmitNode2GlueInput,
+ OPC_MorphNodeTo0GlueInput,
+ OPC_MorphNodeTo1GlueInput,
+ OPC_MorphNodeTo2GlueInput,
+ OPC_EmitNode0GlueOutput,
+ OPC_EmitNode1GlueOutput,
+ OPC_EmitNode2GlueOutput,
+ OPC_MorphNodeTo0GlueOutput,
+ OPC_MorphNodeTo1GlueOutput,
+ OPC_MorphNodeTo2GlueOutput,
+ OPC_EmitNode0MemRefs,
+ OPC_EmitNode1MemRefs,
+ OPC_EmitNode2MemRefs,
+ OPC_MorphNodeTo0MemRefs,
+ OPC_MorphNodeTo1MemRefs,
+ OPC_MorphNodeTo2MemRefs,
OPC_CompleteMatch,
// Contains offset in table for pattern being selected
OPC_Coverage
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index 7d9bebdca127224..2cff2a370a64223 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -3620,20 +3620,97 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,
continue;
}
- case OPC_EmitNode: case OPC_MorphNodeTo:
- case OPC_EmitNode0: case OPC_EmitNode1: case OPC_EmitNode2:
- case OPC_MorphNodeTo0: case OPC_MorphNodeTo1: case OPC_MorphNodeTo2: {
+ case OPC_EmitNode:
+ case OPC_MorphNodeTo:
+ case OPC_EmitNode0:
+ case OPC_EmitNode1:
+ case OPC_EmitNode2:
+ case OPC_MorphNodeTo0:
+ case OPC_MorphNodeTo1:
+ case OPC_MorphNodeTo2:
+ case OPC_EmitNode0None:
+ case OPC_EmitNode1None:
+ case OPC_EmitNode2None:
+ case OPC_MorphNodeTo0None:
+ case OPC_MorphNodeTo1None:
+ case OPC_MorphNodeTo2None:
+ case OPC_EmitNode0Chain:
+ case OPC_EmitNode1Chain:
+ case OPC_EmitNode2Chain:
+ case OPC_MorphNodeTo0Chain:
+ case OPC_MorphNodeTo1Chain:
+ case OPC_MorphNodeTo2Chain:
+ case OPC_EmitNode0GlueInput:
+ case OPC_EmitNode1GlueInput:
+ case OPC_EmitNode2GlueInput:
+ case OPC_MorphNodeTo0GlueInput:
+ case OPC_MorphNodeTo1GlueInput:
+ case OPC_MorphNodeTo2GlueInput:
+ case OPC_EmitNode0GlueOutput:
+ case OPC_EmitNode1GlueOutput:
+ case OPC_EmitNode2GlueOutput:
+ case OPC_MorphNodeTo0GlueOutput:
+ case OPC_MorphNodeTo1GlueOutput:
+ case OPC_MorphNodeTo2GlueOutput:
+ case OPC_EmitNode0MemRefs:
+ case OPC_EmitNode1MemRefs:
+ case OPC_EmitNode2MemRefs:
+ case OPC_MorphNodeTo0MemRefs:
+ case OPC_MorphNodeTo1MemRefs:
+ case OPC_MorphNodeTo2MemRefs: {
uint16_t TargetOpc = MatcherTable[MatcherIndex++];
TargetOpc |= (unsigned short)MatcherTable[MatcherIndex++] << 8;
- unsigned EmitNodeInfo = MatcherTable[MatcherIndex++];
+ unsigned EmitNodeInfo;
+ if (Opcode >= OPC_EmitNode0None && Opcode <= OPC_MorphNodeTo2MemRefs) {
+ if (Opcode >= OPC_EmitNode0Chain && Opcode <= OPC_MorphNodeTo2Chain)
+ EmitNodeInfo = OPFL_Chain;
+ else if (Opcode >= OPC_EmitNode0GlueInput &&
+ Opcode <= OPC_MorphNodeTo2GlueInput)
+ EmitNodeInfo = OPFL_GlueInput;
+ else if (Opcode >= OPC_EmitNode0GlueOutput &&
+ Opcode <= OPC_MorphNodeTo2GlueOutput)
+ EmitNodeInfo = OPFL_GlueOutput;
+ else if (Opcode >= OPC_EmitNode0MemRefs &&
+ Opcode <= OPC_MorphNodeTo2MemRefs)
+ EmitNodeInfo = OPFL_MemRefs;
+ else
+ EmitNodeInfo = OPFL_None;
+ } else
+ EmitNodeInfo = MatcherTable[MatcherIndex++];
// Get the result VT list.
unsigned NumVTs;
// If this is one of the compressed forms, get the number of VTs based
// on the Opcode. Otherwise read the next byte from the table.
if (Opcode >= OPC_MorphNodeTo0 && Opcode <= OPC_MorphNodeTo2)
NumVTs = Opcode - OPC_MorphNodeTo0;
+ else if (Opcode >= OPC_MorphNodeTo0None && Opcode <= OPC_MorphNodeTo2None)
+ NumVTs = Opcode - OPC_MorphNodeTo0None;
+ else if (Opcode >= OPC_MorphNodeTo0Chain &&
+ Opcode <= OPC_MorphNodeTo2Chain)
+ NumVTs = Opcode - OPC_MorphNodeTo0Chain;
+ else if (Opcode >= OPC_MorphNodeTo0GlueInput &&
+ Opcode <= OPC_MorphNodeTo2GlueInput)
+ NumVTs = Opcode - OPC_MorphNodeTo0GlueInput;
+ else if (Opcode >= OPC_MorphNodeTo0GlueOutput &&
+ Opcode <= OPC_MorphNodeTo2GlueOutput)
+ NumVTs = Opcode - OPC_MorphNodeTo0GlueOutput;
+ else if (Opcode >= OPC_MorphNodeTo0MemRefs &&
+ Opcode <= OPC_MorphNodeTo2MemRefs)
+ NumVTs = Opcode - OPC_MorphNodeTo0MemRefs;
else if (Opcode >= OPC_EmitNode0 && Opcode <= OPC_EmitNode2)
NumVTs = Opcode - OPC_EmitNode0;
+ else if (Opcode >= OPC_EmitNode0None && Opcode <= OPC_EmitNode2None)
+ NumVTs = Opcode - OPC_EmitNode0None;
+ else if (Opcode >= OPC_EmitNode0Chain && Opcode <= OPC_EmitNode2Chain)
+ NumVTs = Opcode - OPC_EmitNode0Chain;
+ else if (Opcode >= OPC_EmitNode0GlueInput &&
+ Opcode <= OPC_EmitNode2GlueInput)
+ NumVTs = Opcode - OPC_EmitNode0GlueInput;
+ else if (Opcode >= OPC_EmitNode0GlueOutput &&
+ Opcode <= OPC_EmitNode2GlueOutput)
+ NumVTs = Opcode - OPC_EmitNode0GlueOutput;
+ else if (Opcode >= OPC_EmitNode0MemRefs && Opcode <= OPC_EmitNode2MemRefs)
+ NumVTs = Opcode - OPC_EmitNode0MemRefs;
else
NumVTs = MatcherTable[MatcherIndex++];
SmallVector<EVT, 4> VTs;
@@ -3706,8 +3783,18 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,
// Create the node.
MachineSDNode *Res = nullptr;
- bool IsMorphNodeTo = Opcode == OPC_MorphNodeTo ||
- (Opcode >= OPC_MorphNodeTo0 && Opcode <= OPC_MorphNodeTo2);
+ bool IsMorphNodeTo =
+ Opcode == OPC_MorphNodeTo ||
+ (Opcode >= OPC_MorphNodeTo0 && Opcode <= OPC_MorphNodeTo2) ||
+ (Opcode >= OPC_MorphNodeTo0None && Opcode <= OPC_MorphNodeTo2None) ||
+ (Opcode >= OPC_MorphNodeTo0Chain &&
+ Opcode <= OPC_MorphNodeTo2Chain) ||
+ (Opcode >= OPC_MorphNodeTo0GlueInput &&
+ Opcode <= OPC_MorphNodeTo2GlueInput) ||
+ (Opcode >= OPC_MorphNodeTo0GlueOutput &&
+ Opcode <= OPC_MorphNodeTo2GlueOutput) ||
+ (Opcode >= OPC_MorphNodeTo0MemRefs &&
+ Opcode <= OPC_MorphNodeTo2MemRefs);
if (!IsMorphNodeTo) {
// If this is a normal EmitNode command, just create the new node and
// add the results to the RecordedNodes list.
diff --git a/llvm/test/TableGen/DAGDefaultOps.td b/llvm/test/TableGen/DAGDefaultOps.td
index 88c3f6311feadd9..7da1789f427c262 100644
--- a/llvm/test/TableGen/DAGDefaultOps.td
+++ b/llvm/test/TableGen/DAGDefaultOps.td
@@ -77,20 +77,20 @@ def MulIRRPat : Pat<(mul i32:$x, i32:$y), (MulIRR Reg:$x, Reg:$y)>;
// ADD-NEXT: OPC_RecordChild0
// ADD-NEXT: OPC_RecordChild1
// ADD-NEXT: OPC_EmitInteger, MVT::i32, 0
-// ADD-NEXT: OPC_MorphNodeTo1, TARGET_VAL(::AddRRI)
+// ADD-NEXT: OPC_MorphNodeTo1None, TARGET_VAL(::AddRRI)
// ADDINT: SwitchOpcode{{.*}}TARGET_VAL(ISD::INTRINSIC_WO_CHAIN)
// ADDINT-NEXT: OPC_CheckChild0Integer
// ADDINT-NEXT: OPC_RecordChild1
// ADDINT-NEXT: OPC_RecordChild2
// ADDINT-NEXT: OPC_EmitInteger, MVT::i32, 2
-// ADDINT-NEXT: OPC_MorphNodeTo1, TARGET_VAL(::AddRRI)
+// ADDINT-NEXT: OPC_MorphNodeTo1None, TARGET_VAL(::AddRRI)
// SUB: SwitchOpcode{{.*}}TARGET_VAL(ISD::SUB)
// SUB-NEXT: OPC_RecordChild0
// SUB-NEXT: OPC_RecordChild1
// SUB-NEXT: OPC_EmitInteger, MVT::i32, 0
-// SUB-NEXT: OPC_MorphNodeTo1, TARGET_VAL(::SubRRI)
+// SUB-NEXT: OPC_MorphNodeTo1None, TARGET_VAL(::SubRRI)
// MULINT: SwitchOpcode{{.*}}TARGET_VAL(ISD::INTRINSIC_W_CHAIN)
// MULINT-NEXT: OPC_RecordNode
@@ -99,10 +99,10 @@ def MulIRRPat : Pat<(mul i32:$x, i32:$y), (MulIRR Reg:$x, Reg:$y)>;
// MULINT-NEXT: OPC_RecordChild3
// MULINT-NEXT: OPC_RecordChild4
// MULINT-NEXT: OPC_EmitMergeInputChains
-// MULINT-NEXT: OPC_MorphNodeTo1, TARGET_VAL(::MulRRI)
+// MULINT-NEXT: OPC_MorphNodeTo1Chain, TARGET_VAL(::MulRRI)
// MUL: SwitchOpcode{{.*}}TARGET_VAL(ISD::MUL)
// MUL-NEXT: OPC_EmitInteger, MVT::i32, 0
// MUL-NEXT: OPC_RecordChild0
// MUL-NEXT: OPC_RecordChild1
-// MUL-NEXT: OPC_MorphNodeTo1, TARGET_VAL(::MulRRI)
+// MUL-NEXT: OPC_MorphNodeTo1Chain, TARGET_VAL(::MulRRI)
diff --git a/llvm/test/TableGen/dag-isel-regclass-emit-enum.td b/llvm/test/TableGen/dag-isel-regclass-emit-enum.td
index b4a2db605b9aaee..5f3730bb48dc5e1 100644
--- a/llvm/test/TableGen/dag-isel-regclass-emit-enum.td
+++ b/llvm/test/TableGen/dag-isel-regclass-emit-enum.td
@@ -23,17 +23,17 @@ def GPRAbove127 : RegisterClass<"TestTarget", [i32], 32,
// CHECK: OPC_CheckOpcode, TARGET_VAL(ISD::ADD),
// CHECK-NEXT: OPC_RecordChild0, // #0 = $src
-// CHECK-NEXT: OPC_Scope, 14, /*->20*/ // 2 children in Scope
+// CHECK-NEXT: OPC_Scope, 13, /*->19*/ // 2 children in Scope
// CHECK-NEXT: OPC_CheckChild1Integer, 0,
// CHECK-NEXT: OPC_EmitInteger, MVT::i32, 0|128,2/*256*/,
-// CHECK-NEXT: OPC_MorphNodeTo1, TARGET_VAL(TargetOpcode::COPY_TO_REGCLASS), 0,
+// CHECK-NEXT: OPC_MorphNodeTo1None, TARGET_VAL(TargetOpcode::COPY_TO_REGCLASS),
// CHECK-NEXT: MVT::i32, 2/*#Ops*/, 1, 0,
def : Pat<(i32 (add i32:$src, (i32 0))),
(COPY_TO_REGCLASS GPRAbove127, GPR0:$src)>;
// CHECK: OPC_CheckChild1Integer, 2,
// CHECK-NEXT: OPC_EmitStringInteger, MVT::i32, TestNamespace::GPR127RegClassID,
-// CHECK-NEXT: OPC_MorphNodeTo1, TARGET_VAL(TargetOpcode::COPY_TO_REGCLASS), 0,
+// CHECK-NEXT: OPC_MorphNodeTo1None, TARGET_VAL(TargetOpcode::COPY_TO_REGCLASS),
// CHECK-NEXT: MVT::i32, 2/*#Ops*/, 1, 0,
def : Pat<(i32 (add i32:$src, (i32 1))),
(COPY_TO_REGCLASS GPR127, GPR0:$src)>;
diff --git a/llvm/test/TableGen/dag-isel-res-order.td b/llvm/test/TableGen/dag-isel-res-order.td
index 4da6b6d6867c427..6937dd8c6b807c9 100644
--- a/llvm/test/TableGen/dag-isel-res-order.td
+++ b/llvm/test/TableGen/dag-isel-res-order.td
@@ -12,7 +12,7 @@ def REG : Register<"REG">;
def GPR : RegisterClass<"TestTarget", [i32], 32, (add REG)>;
// CHECK-LABEL: OPC_CheckOpcode, TARGET_VAL(ISD::UDIVREM)
-// CHECK: OPC_EmitNode2, TARGET_VAL(::INSTR)
+// CHECK: OPC_EmitNode2None, TARGET_VAL(::INSTR)
// CHECK: Results = #2 #3
// CHECK: OPC_CompleteMatch, 2, 3, 2
def INSTR : Instruction {
diff --git a/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp b/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp
index 4a11991036efc11..f26be5db4e9b5fb 100644
--- a/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp
+++ b/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp
@@ -776,19 +776,49 @@ EmitMatcher(const Matcher *N, const unsigned Indent, unsigned CurrentIdx,
const EmitNodeMatcherCommon *EN = cast<EmitNodeMatcherCommon>(N);
OS << (isa<EmitNodeMatcher>(EN) ? "OPC_EmitNode" : "OPC_MorphNodeTo");
bool CompressVTs = EN->getNumVTs() < 3;
- if (CompressVTs)
+ bool CompressNodeInfo = false;
+ if (CompressVTs) {
OS << EN->getNumVTs();
+ if (!EN->hasChain() && !EN->hasInGlue() && !EN->hasOutGlue() &&
+ !EN->hasMemRefs() && EN->getNumFixedArityOperands() == -1) {
+ CompressNodeInfo = true;
+ OS << "None";
+ } else if (EN->hasChain() && !EN->hasInGlue() && !EN->hasOutGlue() &&
+ !EN->hasMemRefs() && EN->getNumFixedArityOperands() == -1) {
+ CompressNodeInfo = true;
+ OS << "Chain";
+ } else if (!EN->hasChain() && EN->hasInGlue() && !EN->hasOutGlue() &&
+ !EN->hasMemRefs() && EN->getNumFixedArityOperands() == -1) {
+ CompressNodeInfo = true;
+ OS << "GlueInput";
+ } else if (!EN->hasChain() && !EN->hasInGlue() && EN->hasOutGlue() &&
+ !EN->hasMemRefs() && EN->getNumFixedArityOperands() == -1) {
+ CompressNodeInfo = true;
+ OS << "GlueOutput";
+ } else if (!EN->hasChain() && !EN->hasInGlue() && !EN->hasOutGlue() &&
+ EN->hasMemRefs() && EN->getNumFixedArityOperands() == -1) {
+ CompressNodeInfo = true;
+ OS << "MemRefs";
+ }
+ }
const CodeGenInstruction &CGI = EN->getInstruction();
OS << ", TARGET_VAL(" << CGI.Namespace << "::" << CGI.TheDef->getName()
- << "), 0";
-
- if (EN->hasChain()) OS << "|OPFL_Chain";
- if (EN->hasInGlue()) OS << "|OPFL_GlueInput";
- if (EN->hasOutGlue()) OS << "|OPFL_GlueOutput";
- if (EN->hasMemRefs()) OS << "|OPFL_MemRefs";
- if (EN->getNumFixedArityOperands() != -1)
- OS << "|OPFL_Variadic" << EN->getNumFixedArityOperands();
+ << ")";
+
+ if (!CompressNodeInfo) {
+ OS << ", 0";
+ if (EN->hasChain())
+ OS << "|OPFL_Chain";
+ if (EN->hasInGlue())
+ OS << "|OPFL_GlueInput";
+ if (EN->hasOutGlue())
+ OS << "|OPFL_GlueOutput";
+ if (EN->hasMemRefs())
+ OS << "|OPFL_MemRefs";
+ if (EN->getNumFixedArityOperands() != -1)
+ OS << "|OPFL_Variadic" << EN->getNumFixedArityOperands();
+ }
OS << ",\n";
OS.indent(FullIndexWidth + Indent+4);
@@ -831,8 +861,8 @@ EmitMatcher(const Matcher *N, const unsigned Indent, unsigned CurrentIdx,
} else
OS << '\n';
- return 5 + !CompressVTs + EN->getNumVTs() + NumOperandBytes +
- NumCoveredBytes;
+ return 4 + !CompressVTs + !CompressNodeInfo + EN->getNumVTs() +
+ NumOperandBytes + NumCoveredBytes;
}
case Matcher::CompleteMatch: {
const CompleteMatchMatcher *CM = cast<CompleteMatchMatcher>(N);
More information about the llvm-commits
mailing list