Skip to content

Commit 38ac08d

Browse files
committed
Switch to using a list of StringAttr
1 parent b0a46cb commit 38ac08d

File tree

6 files changed

+77
-74
lines changed

6 files changed

+77
-74
lines changed

mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -938,15 +938,17 @@ def LLVM_VScaleRangeAttr : LLVM_Attr<"VScaleRange", "vscale_range"> {
938938
// TargetFeaturesAttr
939939
//===----------------------------------------------------------------------===//
940940

941-
def LLVM_TargetFeaturesAttr : LLVM_Attr<"TargetFeatures", "target_features"> {
941+
def LLVM_TargetFeaturesAttr : LLVM_Attr<"TargetFeatures", "target_features">
942+
{
942943
let summary = "LLVM target features attribute";
943944

944945
let description = [{
945-
Represents the LLVM target features in a manner that is efficient to query.
946+
Represents the LLVM target features as a list that can be checked within
947+
passes/rewrites.
946948

947949
Example:
948950
```mlir
949-
#llvm.target_features<"+sme,+sve,+sme-f64f64">
951+
#llvm.target_features<["+sme", "+sve", "+sme-f64f64"]>
950952
```
951953

952954
Then within a pass or rewrite the features active at an op can be queried:
@@ -959,19 +961,22 @@ def LLVM_TargetFeaturesAttr : LLVM_Attr<"TargetFeatures", "target_features"> {
959961
```
960962
}];
961963

962-
let parameters = (ins
963-
ArrayRefOfSelfAllocationParameter<"TargetFeature", "">:$features);
964+
let parameters = (ins OptionalArrayRefParameter<"StringAttr">:$features);
964965

965966
let builders = [
966-
TypeBuilder<(ins "::llvm::ArrayRef<TargetFeature>":$features)>,
967-
TypeBuilder<(ins "::llvm::StringRef":$features)>
967+
TypeBuilder<(ins "::llvm::StringRef":$features)>,
968+
TypeBuilder<(ins "::llvm::ArrayRef<::llvm::StringRef>":$features)>
968969
];
969970

970971
let extraClassDeclaration = [{
971972
/// Checks if a feature is contained within the features list.
972-
bool contains(TargetFeature) const;
973-
bool contains(StringRef feature) const {
974-
return contains(TargetFeature{feature});
973+
/// Note: Using a StringAttr allows doing pointer-comparisons.
974+
bool contains(::mlir::StringAttr feature) const;
975+
bool contains(::llvm::StringRef feature) const;
976+
977+
bool nullOrEmpty() const {
978+
// Checks if this attribute is fasly, or the features are empty.
979+
return !bool(*this) || getFeatures().empty();
975980
}
976981

977982
/// Returns the list of features as an LLVM-compatible string.
@@ -987,8 +992,8 @@ def LLVM_TargetFeaturesAttr : LLVM_Attr<"TargetFeatures", "target_features"> {
987992
}
988993
}];
989994

990-
let hasCustomAssemblyFormat = 1;
991-
let skipDefaultBuilders = 1;
995+
let assemblyFormat = "`<` `[` (`]`) : ($features^ `]`)? `>`";
996+
let genVerifyDecl = 1;
992997
}
993998

994999
#endif // LLVMIR_ATTRDEFS

mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -74,31 +74,6 @@ class TBAANodeAttr : public Attribute {
7474
}
7575
};
7676

77-
/// This struct represents a single LLVM target feature.
78-
struct TargetFeature {
79-
StringRef feature;
80-
81-
// Support allocating this struct into MLIR storage to ensure the feature
82-
// string remains valid.
83-
TargetFeature allocateInto(TypeStorageAllocator &alloc) const {
84-
return TargetFeature{alloc.copyInto(feature)};
85-
}
86-
87-
operator StringRef() const { return feature; }
88-
89-
bool operator==(TargetFeature const &other) const {
90-
return feature == other.feature;
91-
}
92-
93-
bool operator<(TargetFeature const &other) const {
94-
return feature < other.feature;
95-
}
96-
};
97-
98-
inline llvm::hash_code hash_value(const TargetFeature &feature) {
99-
return llvm::hash_value(feature.feature);
100-
}
101-
10277
// Inline the LLVM generated Linkage enum and utility.
10378
// This is only necessary to isolate the "enum generated code" from the
10479
// attribute definition itself.

mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,7 @@
1919
#include "llvm/ADT/TypeSwitch.h"
2020
#include "llvm/BinaryFormat/Dwarf.h"
2121
#include "llvm/IR/DebugInfoMetadata.h"
22-
#include <algorithm>
2322
#include <optional>
24-
#include <set>
2523

2624
using namespace mlir;
2725
using namespace mlir::LLVM;
@@ -191,53 +189,55 @@ void printExpressionArg(AsmPrinter &printer, uint64_t opcode,
191189
// TargetFeaturesAttr
192190
//===----------------------------------------------------------------------===//
193191

194-
Attribute TargetFeaturesAttr::parse(mlir::AsmParser &parser, mlir::Type) {
195-
std::string targetFeatures;
196-
if (parser.parseLess() || parser.parseString(&targetFeatures) ||
197-
parser.parseGreater())
198-
return {};
199-
return get(parser.getContext(), targetFeatures);
200-
}
201-
202-
void TargetFeaturesAttr::print(mlir::AsmPrinter &printer) const {
203-
printer << "<\"";
204-
llvm::interleave(
205-
getFeatures(), printer,
206-
[&](auto &feature) { printer << StringRef(feature); }, ",");
207-
printer << "\">";
208-
}
209-
210-
TargetFeaturesAttr
211-
TargetFeaturesAttr::get(MLIRContext *context,
212-
llvm::ArrayRef<TargetFeature> featuresRef) {
213-
// Sort and de-duplicate target features.
214-
std::set<TargetFeature> features(featuresRef.begin(), featuresRef.end());
215-
return Base::get(context, llvm::to_vector(features));
192+
TargetFeaturesAttr TargetFeaturesAttr::get(MLIRContext *context,
193+
llvm::ArrayRef<StringRef> features) {
194+
return Base::get(context,
195+
llvm::map_to_vector(features, [&](StringRef feature) {
196+
return StringAttr::get(context, feature);
197+
}));
216198
}
217199

218200
TargetFeaturesAttr TargetFeaturesAttr::get(MLIRContext *context,
219201
StringRef targetFeatures) {
220202
SmallVector<StringRef> features;
221203
targetFeatures.split(features, ',', /*MaxSplit=*/-1,
222204
/*KeepEmpty=*/false);
223-
return get(context, llvm::map_to_vector(features, [](StringRef feature) {
224-
return TargetFeature{feature};
225-
}));
205+
return get(context, features);
206+
}
207+
208+
LogicalResult
209+
TargetFeaturesAttr::verify(function_ref<InFlightDiagnostic()> emitError,
210+
llvm::ArrayRef<StringAttr> features) {
211+
for (StringAttr featureAttr : features) {
212+
if (!featureAttr || featureAttr.empty())
213+
return emitError() << "target features can not be null or empty";
214+
auto feature = featureAttr.strref();
215+
if (feature[0] != '+' && feature[0] != '-')
216+
return emitError() << "target features must start with '+' or '-'";
217+
if (feature.contains(','))
218+
return emitError() << "target features can not contain ','";
219+
}
220+
return success();
221+
}
222+
223+
bool TargetFeaturesAttr::contains(StringAttr feature) const {
224+
if (nullOrEmpty())
225+
return false;
226+
// Note: Using StringAttr does pointer comparisons.
227+
return llvm::is_contained(getFeatures(), feature);
226228
}
227229

228-
bool TargetFeaturesAttr::contains(TargetFeature feature) const {
229-
if (!bool(*this))
230-
return false; // Allows checking null target features.
231-
ArrayRef<TargetFeature> features = getFeatures();
232-
// Note: The attribute getter ensures the feature list is sorted.
233-
return std::binary_search(features.begin(), features.end(), feature);
230+
bool TargetFeaturesAttr::contains(StringRef feature) const {
231+
if (nullOrEmpty())
232+
return false;
233+
return llvm::is_contained(getFeatures(), feature);
234234
}
235235

236236
std::string TargetFeaturesAttr::getFeaturesString() const {
237237
std::string featuresString;
238238
llvm::raw_string_ostream ss(featuresString);
239239
llvm::interleave(
240-
getFeatures(), ss, [&](auto &feature) { ss << StringRef(feature); }, ",");
240+
getFeatures(), ss, [&](auto &feature) { ss << feature.strref(); }, ",");
241241
return ss.str();
242242
}
243243

mlir/test/Target/LLVMIR/Import/target-features.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
; RUN: mlir-translate -import-llvm -split-input-file %s | FileCheck %s
22

33
; CHECK-LABEL: llvm.func @target_features()
4-
; CHECK-SAME: #llvm.target_features<"+sme,+sme-f64f64,+sve">
4+
; CHECK-SAME: #llvm.target_features<["+sme", "+sme-f64f64", "+sve"]>
55
define void @target_features() #0 {
66
ret void
77
}

mlir/test/Target/LLVMIR/llvmir-invalid.mlir

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,27 @@ llvm.func @stepvector_intr_wrong_type() -> vector<7xf32> {
261261

262262
// -----
263263

264+
// expected-error @below{{target features can not contain ','}}
265+
llvm.func @invalid_target_feature() attributes { target_features = #llvm.target_features<["+bad,feature", "+test"]> }
266+
{
267+
}
268+
269+
// -----
270+
271+
// expected-error @below{{target features must start with '+' or '-'}}
272+
llvm.func @missing_target_feature_prefix() attributes { target_features = #llvm.target_features<["sme"]> }
273+
{
274+
}
275+
276+
// -----
277+
278+
// expected-error @below{{target features can not be null or empty}}
279+
llvm.func @empty_target_feature() attributes { target_features = #llvm.target_features<["", "+sve"]> }
280+
{
281+
}
282+
283+
// -----
284+
264285
llvm.comdat @__llvm_comdat {
265286
llvm.comdat_selector @foo any
266287
}
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
22

33
// CHECK-LABEL: define void @target_features
4-
// CHECK: attributes #{{.*}} = { "target-features"="+sme,+sme-f64f64,+sve" }
5-
llvm.func @target_features() attributes { target_features = #llvm.target_features<"+sme,+sve,+sme-f64f64"> } {
4+
// CHECK: attributes #{{.*}} = { "target-features"="+sme,+sve,+sme-f64f64" }
5+
llvm.func @target_features() attributes {
6+
target_features = #llvm.target_features<["+sme", "+sve", "+sme-f64f64"]>
7+
} {
68
llvm.return
79
}

0 commit comments

Comments
 (0)