-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[SelectionDAG] Wire up -gen-sdnode-info TableGen backend #125358
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
4b2c60b
[SelectionDAG] Wire up -gen-sdnode-info TableGen backend
s-barannikov c233ee9
Make VerifySDNode a member function
s-barannikov 1f9d21d
Use smaller types for SDTC/NumResults/NumOperands
s-barannikov ae09fa6
Merge commit '44923d8631fb28b4de54d4210762f256c3894cef' into sdag/sdn…
s-barannikov 1c2529d
Fix includes & include guard
s-barannikov File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
//==------------------------------------------------------------------------==// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef LLVM_CODEGEN_SDNODEINFO_H | ||
#define LLVM_CODEGEN_SDNODEINFO_H | ||
|
||
#include "llvm/ADT/ArrayRef.h" | ||
#include "llvm/ADT/StringTable.h" | ||
#include "llvm/CodeGen/ISDOpcodes.h" | ||
#include "llvm/CodeGenTypes/MachineValueType.h" | ||
|
||
namespace llvm { | ||
|
||
class SDNode; | ||
class SelectionDAG; | ||
|
||
enum SDNP { | ||
SDNPHasChain, | ||
SDNPOutGlue, | ||
SDNPInGlue, | ||
SDNPOptInGlue, | ||
SDNPMemOperand, | ||
SDNPVariadic, | ||
}; | ||
|
||
enum SDTC : uint8_t { | ||
SDTCisVT, | ||
SDTCisPtrTy, | ||
SDTCisInt, | ||
SDTCisFP, | ||
SDTCisVec, | ||
SDTCisSameAs, | ||
SDTCisVTSmallerThanOp, | ||
SDTCisOpSmallerThanOp, | ||
SDTCisEltOfVec, | ||
SDTCisSubVecOfVec, | ||
SDTCVecEltisVT, | ||
SDTCisSameNumEltsAs, | ||
SDTCisSameSizeAs, | ||
}; | ||
|
||
enum SDNF { | ||
SDNFIsStrictFP, | ||
}; | ||
|
||
struct SDTypeConstraint { | ||
SDTC Kind; | ||
uint8_t OpNo; | ||
uint8_t OtherOpNo; | ||
MVT::SimpleValueType VT; | ||
}; | ||
|
||
struct SDNodeDesc { | ||
uint16_t NumResults; | ||
int16_t NumOperands; | ||
uint32_t Properties; | ||
uint32_t Flags; | ||
uint32_t TSFlags; | ||
unsigned NameOffset; | ||
unsigned ConstraintOffset; | ||
unsigned ConstraintCount; | ||
|
||
bool hasProperty(SDNP Property) const { return Properties & (1 << Property); } | ||
|
||
bool hasFlag(SDNF Flag) const { return Flags & (1 << Flag); } | ||
}; | ||
|
||
class SDNodeInfo final { | ||
unsigned NumOpcodes; | ||
const SDNodeDesc *Descs; | ||
StringTable Names; | ||
const SDTypeConstraint *Constraints; | ||
|
||
public: | ||
constexpr SDNodeInfo(unsigned NumOpcodes, const SDNodeDesc *Descs, | ||
StringTable Names, const SDTypeConstraint *Constraints) | ||
: NumOpcodes(NumOpcodes), Descs(Descs), Names(Names), | ||
Constraints(Constraints) {} | ||
|
||
/// Returns true if there is a generated description for a node with the given | ||
/// target-specific opcode. | ||
bool hasDesc(unsigned Opcode) const { | ||
assert(Opcode >= ISD::BUILTIN_OP_END && "Expected target-specific opcode"); | ||
return Opcode < ISD::BUILTIN_OP_END + NumOpcodes; | ||
} | ||
|
||
/// Returns the description of a node with the given opcode. | ||
const SDNodeDesc &getDesc(unsigned Opcode) const { | ||
assert(hasDesc(Opcode)); | ||
return Descs[Opcode - ISD::BUILTIN_OP_END]; | ||
} | ||
|
||
/// Returns operand constraints for a node with the given opcode. | ||
ArrayRef<SDTypeConstraint> getConstraints(unsigned Opcode) const { | ||
const SDNodeDesc &Desc = getDesc(Opcode); | ||
return ArrayRef(&Constraints[Desc.ConstraintOffset], Desc.ConstraintCount); | ||
} | ||
|
||
/// Returns the name of the given target-specific opcode, suitable for | ||
/// debug printing. | ||
StringRef getName(unsigned Opcode) const { | ||
return Names[getDesc(Opcode).NameOffset]; | ||
} | ||
|
||
void verifyNode(const SelectionDAG &DAG, const SDNode *N) const; | ||
}; | ||
|
||
} // namespace llvm | ||
|
||
#endif // LLVM_CODEGEN_SDNODEINFO_H |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
//==------------------------------------------------------------------------==// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "llvm/CodeGen/SDNodeInfo.h" | ||
#include "llvm/CodeGen/SelectionDAGNodes.h" | ||
|
||
using namespace llvm; | ||
|
||
static void reportNodeError(const SelectionDAG &DAG, const SDNode *N, | ||
const Twine &Msg) { | ||
std::string S; | ||
raw_string_ostream SS(S); | ||
SS << "invalid node: " << Msg << '\n'; | ||
N->printrWithDepth(SS, &DAG, 2); | ||
report_fatal_error(StringRef(S)); | ||
} | ||
|
||
static void checkResultType(const SelectionDAG &DAG, const SDNode *N, | ||
unsigned ResIdx, EVT ExpectedVT) { | ||
EVT ActualVT = N->getValueType(ResIdx); | ||
if (ActualVT != ExpectedVT) | ||
reportNodeError( | ||
DAG, N, | ||
"result #" + Twine(ResIdx) + " has invalid type; expected " + | ||
ExpectedVT.getEVTString() + ", got " + ActualVT.getEVTString()); | ||
} | ||
|
||
static void checkOperandType(const SelectionDAG &DAG, const SDNode *N, | ||
unsigned OpIdx, EVT ExpectedVT) { | ||
EVT ActualVT = N->getOperand(OpIdx).getValueType(); | ||
if (ActualVT != ExpectedVT) | ||
reportNodeError( | ||
DAG, N, | ||
"operand #" + Twine(OpIdx) + " has invalid type; expected " + | ||
ExpectedVT.getEVTString() + ", got " + ActualVT.getEVTString()); | ||
} | ||
|
||
void SDNodeInfo::verifyNode(const SelectionDAG &DAG, const SDNode *N) const { | ||
const SDNodeDesc &Desc = getDesc(N->getOpcode()); | ||
bool HasChain = Desc.hasProperty(SDNPHasChain); | ||
bool HasOutGlue = Desc.hasProperty(SDNPOutGlue); | ||
bool HasInGlue = Desc.hasProperty(SDNPInGlue); | ||
bool HasOptInGlue = Desc.hasProperty(SDNPOptInGlue); | ||
bool IsVariadic = Desc.hasProperty(SDNPVariadic); | ||
|
||
unsigned ActualNumResults = N->getNumValues(); | ||
unsigned ExpectedNumResults = Desc.NumResults + HasChain + HasOutGlue; | ||
|
||
if (ActualNumResults != ExpectedNumResults) | ||
reportNodeError(DAG, N, | ||
"invalid number of results; expected " + | ||
Twine(ExpectedNumResults) + ", got " + | ||
Twine(ActualNumResults)); | ||
|
||
// Chain result comes after all normal results. | ||
if (HasChain) { | ||
unsigned ChainResIdx = Desc.NumResults; | ||
checkResultType(DAG, N, ChainResIdx, MVT::Other); | ||
} | ||
|
||
// Glue result comes last. | ||
if (HasOutGlue) { | ||
unsigned GlueResIdx = Desc.NumResults + HasChain; | ||
checkResultType(DAG, N, GlueResIdx, MVT::Glue); | ||
} | ||
|
||
// In the most general case, the operands of a node go in the following order: | ||
// chain, fix#0, ..., fix#M-1, var#0, ... var#N-1, glue | ||
// If the number of operands is < 0, M can be any; | ||
// If the node has SDNPVariadic property, N can be any. | ||
bool HasOptionalOperands = Desc.NumOperands < 0 || IsVariadic; | ||
|
||
unsigned ActualNumOperands = N->getNumOperands(); | ||
unsigned ExpectedMinNumOperands = | ||
(Desc.NumOperands >= 0 ? Desc.NumOperands : 0) + HasChain + HasInGlue; | ||
|
||
// Check the lower bound. | ||
if (ActualNumOperands < ExpectedMinNumOperands) { | ||
StringRef How = HasOptionalOperands ? "at least " : ""; | ||
reportNodeError(DAG, N, | ||
"invalid number of operands; expected " + How + | ||
Twine(ExpectedMinNumOperands) + ", got " + | ||
Twine(ActualNumOperands)); | ||
} | ||
|
||
// Check the upper bound. We can only do this if the number of fixed operands | ||
// is known and there are no variadic operands. | ||
if (Desc.NumOperands >= 0 && !IsVariadic) { | ||
// Account for optional input glue. | ||
unsigned ExpectedMaxNumOperands = ExpectedMinNumOperands + HasOptInGlue; | ||
if (ActualNumOperands > ExpectedMaxNumOperands) { | ||
StringRef How = HasOptInGlue ? "at most " : ""; | ||
reportNodeError(DAG, N, | ||
"invalid number of operands; expected " + How + | ||
Twine(ExpectedMaxNumOperands) + ", got " + | ||
Twine(ActualNumOperands)); | ||
} | ||
} | ||
|
||
// Chain operand comes first. | ||
if (HasChain) | ||
checkOperandType(DAG, N, 0, MVT::Other); | ||
|
||
// Glue operand comes last. | ||
if (HasInGlue) | ||
checkOperandType(DAG, N, ActualNumOperands - 1, MVT::Glue); | ||
if (HasOptInGlue && ActualNumOperands >= 1 && | ||
N->getOperand(ActualNumOperands - 1).getValueType() == MVT::Glue) | ||
HasInGlue = true; | ||
|
||
// Check variadic operands. These should be Register or RegisterMask. | ||
if (IsVariadic && Desc.NumOperands >= 0) { | ||
unsigned VarOpStart = HasChain + Desc.NumOperands; | ||
unsigned VarOpEnd = ActualNumOperands - HasInGlue; | ||
for (unsigned OpIdx = VarOpStart; OpIdx != VarOpEnd; ++OpIdx) { | ||
unsigned OpOpcode = N->getOperand(OpIdx).getOpcode(); | ||
if (OpOpcode != ISD::Register && OpOpcode != ISD::RegisterMask) | ||
reportNodeError(DAG, N, | ||
"variadic operand #" + Twine(OpIdx) + | ||
" must be Register or RegisterMask"); | ||
} | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently this only verifies basic SDNode "prototype" -- the number of operands/results and the types of chain/glue operands/results. I refrained from making use of the imported SDTypeProfile in this patch to keep it smaller (and I need to spend more time on implementing proper type profile checking anyway).