Skip to content

Commit ddda37a

Browse files
authoredAug 16, 2024
[TableGen] Refactor Intrinsic handling in TableGen (#103980)
CodeGenIntrinsic changes: - Use `const` Record pointers, and `StringRef` when possible. - Default initialize several fields with their definition instead of in the constructor. - Simplify various string checks in the constructor using StringRef starts_with()/ends_with() functions. - Eliminate first argument to `setDefaultProperties` and use `TheDef` class member instead. IntrinsicEmitter changes: - Emit `namespace llvm::Intrinsic` instead of nested namespaces. - End generated comments with a . - Use range based for loops, and early continue within loops. - Emit `static constexpr` instead of `static const` for arrays. - Change `compareFnAttributes` to use std::tie() to compare intrinsic attributes and return a default value when all attributes are equal. STLExtras: - Add std::replace wrapper which takes a range.
1 parent 97f0ab7 commit ddda37a

11 files changed

+142
-181
lines changed
 

‎llvm/include/llvm/ADT/STLExtras.h

+7
Original file line numberDiff line numberDiff line change
@@ -1843,6 +1843,13 @@ OutputIt replace_copy(R &&Range, OutputIt Out, const T &OldValue,
18431843
NewValue);
18441844
}
18451845

1846+
/// Provide wrappers to std::replace which take ranges instead of having to pass
1847+
/// begin/end explicitly.
1848+
template <typename R, typename T>
1849+
void replace(R &&Range, const T &OldValue, const T &NewValue) {
1850+
return std::replace(adl_begin(Range), adl_end(Range), OldValue, NewValue);
1851+
}
1852+
18461853
/// Provide wrappers to std::move which take ranges instead of having to
18471854
/// pass begin/end explicitly.
18481855
template <typename R, typename OutputIt>

‎llvm/lib/Object/COFFImportFile.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -705,7 +705,7 @@ Error writeImportLibrary(StringRef ImportName, StringRef Path,
705705
Name = std::string(SymbolName);
706706
} else {
707707
Expected<std::string> ReplacedName =
708-
replace(SymbolName, E.Name, E.ExtName);
708+
object::replace(SymbolName, E.Name, E.ExtName);
709709
if (!ReplacedName)
710710
return ReplacedName.takeError();
711711
Name.swap(*ReplacedName);

‎llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp

+27-45
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,16 @@ CodeGenIntrinsicTable::CodeGenIntrinsicTable(const RecordKeeper &RC) {
2929
std::vector<Record *> IntrProperties =
3030
RC.getAllDerivedDefinitions("IntrinsicProperty");
3131

32-
std::vector<Record *> DefaultProperties;
33-
for (Record *Rec : IntrProperties)
32+
std::vector<const Record *> DefaultProperties;
33+
for (const Record *Rec : IntrProperties)
3434
if (Rec->getValueAsBit("IsDefault"))
3535
DefaultProperties.push_back(Rec);
3636

3737
std::vector<Record *> Defs = RC.getAllDerivedDefinitions("Intrinsic");
3838
Intrinsics.reserve(Defs.size());
3939

40-
for (unsigned I = 0, e = Defs.size(); I != e; ++I)
41-
Intrinsics.push_back(CodeGenIntrinsic(Defs[I], DefaultProperties));
40+
for (const Record *Def : Defs)
41+
Intrinsics.push_back(CodeGenIntrinsic(Def, DefaultProperties));
4242

4343
llvm::sort(Intrinsics,
4444
[](const CodeGenIntrinsic &LHS, const CodeGenIntrinsic &RHS) {
@@ -54,61 +54,43 @@ CodeGenIntrinsicTable::CodeGenIntrinsicTable(const RecordKeeper &RC) {
5454
Targets.back().Count = Intrinsics.size() - Targets.back().Offset;
5555
}
5656

57-
CodeGenIntrinsic::CodeGenIntrinsic(Record *R,
58-
ArrayRef<Record *> DefaultProperties) {
59-
TheDef = R;
60-
std::string DefName = std::string(R->getName());
57+
CodeGenIntrinsic::CodeGenIntrinsic(const Record *R,
58+
ArrayRef<const Record *> DefaultProperties)
59+
: TheDef(R) {
60+
StringRef DefName = TheDef->getName();
6161
ArrayRef<SMLoc> DefLoc = R->getLoc();
62-
Properties = 0;
63-
isOverloaded = false;
64-
isCommutative = false;
65-
canThrow = false;
66-
isNoReturn = false;
67-
isNoCallback = false;
68-
isNoSync = false;
69-
isNoFree = false;
70-
isWillReturn = false;
71-
isCold = false;
72-
isNoDuplicate = false;
73-
isNoMerge = false;
74-
isConvergent = false;
75-
isSpeculatable = false;
76-
hasSideEffects = false;
77-
isStrictFP = false;
7862

79-
if (DefName.size() <= 4 || DefName.substr(0, 4) != "int_")
63+
if (!DefName.starts_with("int_"))
8064
PrintFatalError(DefLoc,
8165
"Intrinsic '" + DefName + "' does not start with 'int_'!");
8266

8367
EnumName = DefName.substr(4);
8468

85-
if (R->getValue(
86-
"ClangBuiltinName")) // Ignore a missing ClangBuiltinName field.
87-
ClangBuiltinName = std::string(R->getValueAsString("ClangBuiltinName"));
88-
if (R->getValue("MSBuiltinName")) // Ignore a missing MSBuiltinName field.
89-
MSBuiltinName = std::string(R->getValueAsString("MSBuiltinName"));
69+
// Ignore a missing ClangBuiltinName field.
70+
ClangBuiltinName =
71+
R->getValueAsOptionalString("ClangBuiltinName").value_or("");
72+
// Ignore a missing MSBuiltinName field.
73+
MSBuiltinName = R->getValueAsOptionalString("MSBuiltinName").value_or("");
9074

91-
TargetPrefix = std::string(R->getValueAsString("TargetPrefix"));
92-
Name = std::string(R->getValueAsString("LLVMName"));
75+
TargetPrefix = R->getValueAsString("TargetPrefix");
76+
Name = R->getValueAsString("LLVMName").str();
9377

9478
if (Name == "") {
9579
// If an explicit name isn't specified, derive one from the DefName.
96-
Name = "llvm.";
97-
98-
for (unsigned i = 0, e = EnumName.size(); i != e; ++i)
99-
Name += (EnumName[i] == '_') ? '.' : EnumName[i];
80+
Name = "llvm." + EnumName.str();
81+
llvm::replace(Name, '_', '.');
10082
} else {
10183
// Verify it starts with "llvm.".
102-
if (Name.size() <= 5 || Name.substr(0, 5) != "llvm.")
84+
if (!StringRef(Name).starts_with("llvm."))
10385
PrintFatalError(DefLoc, "Intrinsic '" + DefName +
10486
"'s name does not start with 'llvm.'!");
10587
}
10688

10789
// If TargetPrefix is specified, make sure that Name starts with
10890
// "llvm.<targetprefix>.".
10991
if (!TargetPrefix.empty()) {
110-
if (Name.size() < 6 + TargetPrefix.size() ||
111-
Name.substr(5, 1 + TargetPrefix.size()) != (TargetPrefix + "."))
92+
StringRef Prefix = StringRef(Name).drop_front(5); // Drop llvm.
93+
if (!Prefix.consume_front(TargetPrefix) || !Prefix.starts_with('.'))
11294
PrintFatalError(DefLoc, "Intrinsic '" + DefName +
11395
"' does not start with 'llvm." +
11496
TargetPrefix + ".'!");
@@ -129,15 +111,15 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R,
129111
// Parse the intrinsic properties.
130112
ListInit *PropList = R->getValueAsListInit("IntrProperties");
131113
for (unsigned i = 0, e = PropList->size(); i != e; ++i) {
132-
Record *Property = PropList->getElementAsRecord(i);
114+
const Record *Property = PropList->getElementAsRecord(i);
133115
assert(Property->isSubClassOf("IntrinsicProperty") &&
134116
"Expected a property!");
135117

136118
setProperty(Property);
137119
}
138120

139121
// Set default properties to true.
140-
setDefaultProperties(R, DefaultProperties);
122+
setDefaultProperties(DefaultProperties);
141123

142124
// Also record the SDPatternOperator Properties.
143125
Properties = parseSDPatternOperatorProperties(R);
@@ -148,16 +130,16 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R,
148130
}
149131

150132
void CodeGenIntrinsic::setDefaultProperties(
151-
Record *R, ArrayRef<Record *> DefaultProperties) {
133+
ArrayRef<const Record *> DefaultProperties) {
152134
// opt-out of using default attributes.
153-
if (R->getValueAsBit("DisableDefaultAttributes"))
135+
if (TheDef->getValueAsBit("DisableDefaultAttributes"))
154136
return;
155137

156-
for (Record *Rec : DefaultProperties)
138+
for (const Record *Rec : DefaultProperties)
157139
setProperty(Rec);
158140
}
159141

160-
void CodeGenIntrinsic::setProperty(Record *R) {
142+
void CodeGenIntrinsic::setProperty(const Record *R) {
161143
if (R->getName() == "IntrNoMem")
162144
ME = MemoryEffects::none();
163145
else if (R->getName() == "IntrReadMem") {

‎llvm/utils/TableGen/Basic/CodeGenIntrinsics.h

+31-30
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,12 @@ class Record;
2626
class RecordKeeper;
2727

2828
struct CodeGenIntrinsic {
29-
Record *TheDef; // The actual record defining this intrinsic.
29+
const Record *TheDef; // The actual record defining this intrinsic.
3030
std::string Name; // The name of the LLVM function "llvm.bswap.i32"
31-
std::string EnumName; // The name of the enum "bswap_i32"
32-
std::string ClangBuiltinName; // Name of the corresponding GCC builtin, or "".
33-
std::string MSBuiltinName; // Name of the corresponding MS builtin, or "".
34-
std::string TargetPrefix; // Target prefix, e.g. "ppc" for t-s intrinsics.
31+
StringRef EnumName; // The name of the enum "bswap_i32"
32+
StringRef ClangBuiltinName; // Name of the corresponding GCC builtin, or "".
33+
StringRef MSBuiltinName; // Name of the corresponding MS builtin, or "".
34+
StringRef TargetPrefix; // Target prefix, e.g. "ppc" for t-s intrinsics.
3535

3636
/// This structure holds the return values and parameter values of an
3737
/// intrinsic. If the number of return values is > 1, then the intrinsic
@@ -43,13 +43,13 @@ struct CodeGenIntrinsic {
4343
/// only populated when in the context of a target .td file. When building
4444
/// Intrinsics.td, this isn't available, because we don't know the target
4545
/// pointer size.
46-
std::vector<Record *> RetTys;
46+
std::vector<const Record *> RetTys;
4747

4848
/// The MVT::SimpleValueType for each parameter type. Note that this list is
4949
/// only populated when in the context of a target .td file. When building
5050
/// Intrinsics.td, this isn't available, because we don't know the target
5151
/// pointer size.
52-
std::vector<Record *> ParamTys;
52+
std::vector<const Record *> ParamTys;
5353
};
5454

5555
IntrinsicSignature IS;
@@ -58,54 +58,54 @@ struct CodeGenIntrinsic {
5858
MemoryEffects ME = MemoryEffects::unknown();
5959

6060
/// SDPatternOperator Properties applied to the intrinsic.
61-
unsigned Properties;
61+
unsigned Properties = 0;
6262

6363
/// This is set to true if the intrinsic is overloaded by its argument
6464
/// types.
65-
bool isOverloaded;
65+
bool isOverloaded = false;
6666

6767
/// True if the intrinsic is commutative.
68-
bool isCommutative;
68+
bool isCommutative = false;
6969

7070
/// True if the intrinsic can throw.
71-
bool canThrow;
71+
bool canThrow = false;
7272

7373
/// True if the intrinsic is marked as noduplicate.
74-
bool isNoDuplicate;
74+
bool isNoDuplicate = false;
7575

7676
/// True if the intrinsic is marked as nomerge.
77-
bool isNoMerge;
77+
bool isNoMerge = false;
7878

7979
/// True if the intrinsic is no-return.
80-
bool isNoReturn;
80+
bool isNoReturn = false;
8181

8282
/// True if the intrinsic is no-callback.
83-
bool isNoCallback;
83+
bool isNoCallback = false;
8484

8585
/// True if the intrinsic is no-sync.
86-
bool isNoSync;
86+
bool isNoSync = false;
8787

8888
/// True if the intrinsic is no-free.
89-
bool isNoFree;
89+
bool isNoFree = false;
9090

9191
/// True if the intrinsic is will-return.
92-
bool isWillReturn;
92+
bool isWillReturn = false;
9393

9494
/// True if the intrinsic is cold.
95-
bool isCold;
95+
bool isCold = false;
9696

9797
/// True if the intrinsic is marked as convergent.
98-
bool isConvergent;
98+
bool isConvergent = false;
9999

100100
/// True if the intrinsic has side effects that aren't captured by any
101101
/// of the other flags.
102-
bool hasSideEffects;
102+
bool hasSideEffects = false;
103103

104104
// True if the intrinsic is marked as speculatable.
105-
bool isSpeculatable;
105+
bool isSpeculatable = false;
106106

107107
// True if the intrinsic is marked as strictfp.
108-
bool isStrictFP;
108+
bool isStrictFP = false;
109109

110110
enum ArgAttrKind {
111111
NoCapture,
@@ -139,12 +139,12 @@ struct CodeGenIntrinsic {
139139

140140
bool hasProperty(enum SDNP Prop) const { return Properties & (1 << Prop); }
141141

142-
/// Goes through all IntrProperties that have IsDefault
143-
/// value set and sets the property.
144-
void setDefaultProperties(Record *R, ArrayRef<Record *> DefaultProperties);
142+
/// Goes through all IntrProperties that have IsDefault value set and sets
143+
/// the property.
144+
void setDefaultProperties(ArrayRef<const Record *> DefaultProperties);
145145

146-
/// Helper function to set property \p Name to true;
147-
void setProperty(Record *R);
146+
/// Helper function to set property \p Name to true.
147+
void setProperty(const Record *R);
148148

149149
/// Returns true if the parameter at \p ParamIdx is a pointer type. Returns
150150
/// false if the parameter is not a pointer, or \p ParamIdx is greater than
@@ -155,15 +155,16 @@ struct CodeGenIntrinsic {
155155

156156
bool isParamImmArg(unsigned ParamIdx) const;
157157

158-
CodeGenIntrinsic(Record *R, ArrayRef<Record *> DefaultProperties);
158+
CodeGenIntrinsic(const Record *R,
159+
ArrayRef<const Record *> DefaultProperties = {});
159160
};
160161

161162
class CodeGenIntrinsicTable {
162163
std::vector<CodeGenIntrinsic> Intrinsics;
163164

164165
public:
165166
struct TargetSet {
166-
std::string Name;
167+
StringRef Name;
167168
size_t Offset;
168169
size_t Count;
169170
};

‎llvm/utils/TableGen/Basic/SDNodeProperties.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313

1414
using namespace llvm;
1515

16-
unsigned llvm::parseSDPatternOperatorProperties(Record *R) {
16+
unsigned llvm::parseSDPatternOperatorProperties(const Record *R) {
1717
unsigned Properties = 0;
18-
for (Record *Property : R->getValueAsListOfDefs("Properties")) {
18+
for (const Record *Property : R->getValueAsListOfDefs("Properties")) {
1919
auto Offset = StringSwitch<unsigned>(Property->getName())
2020
.Case("SDNPCommutative", SDNPCommutative)
2121
.Case("SDNPAssociative", SDNPAssociative)

‎llvm/utils/TableGen/Basic/SDNodeProperties.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ enum SDNP {
3232
SDNPWantParent
3333
};
3434

35-
unsigned parseSDPatternOperatorProperties(Record *R);
35+
unsigned parseSDPatternOperatorProperties(const Record *R);
3636

3737
} // namespace llvm
3838

‎llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -1314,7 +1314,7 @@ void IntrinsicIDOperandMatcher::emitPredicateOpcodes(MatchTable &Table,
13141314
Table << MatchTable::Opcode("GIM_CheckIntrinsicID")
13151315
<< MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID)
13161316
<< MatchTable::Comment("Op") << MatchTable::ULEB128Value(OpIdx)
1317-
<< MatchTable::NamedValue(2, "Intrinsic::" + II->EnumName)
1317+
<< MatchTable::NamedValue(2, "Intrinsic::" + II->EnumName.str())
13181318
<< MatchTable::LineBreak;
13191319
}
13201320

@@ -2103,7 +2103,7 @@ void IntrinsicIDRenderer::emitRenderOpcodes(MatchTable &Table,
21032103
RuleMatcher &Rule) const {
21042104
Table << MatchTable::Opcode("GIR_AddIntrinsicID") << MatchTable::Comment("MI")
21052105
<< MatchTable::ULEB128Value(InsnID)
2106-
<< MatchTable::NamedValue(2, "Intrinsic::" + II->EnumName)
2106+
<< MatchTable::NamedValue(2, "Intrinsic::" + II->EnumName.str())
21072107
<< MatchTable::LineBreak;
21082108
}
21092109

‎llvm/utils/TableGen/Common/GlobalISel/PatternParser.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ static const CodeGenIntrinsic *getCodeGenIntrinsic(Record *R) {
112112

113113
auto &Ptr = AllIntrinsics[R];
114114
if (!Ptr)
115-
Ptr = std::make_unique<CodeGenIntrinsic>(R, std::vector<Record *>());
115+
Ptr = std::make_unique<CodeGenIntrinsic>(R);
116116
return Ptr.get();
117117
}
118118

0 commit comments

Comments
 (0)