let assemblyFormat = "`<` struct(params) `>`";
}
+def LoopPeeledAttr : LLVM_Attr<"LoopPeeled", "loop_peeled"> {
+ let description = [{
+ This attribute defines pipelining specific loop annotations that map to
+ the "!llvm.loop.peeled" metadata.
+ }];
+
+ let parameters = (ins
+ OptionalParameter<"IntegerAttr">:$count
+ );
+
+ let assemblyFormat = "`<` struct(params) `>`";
+}
+
+def LoopUnswitchAttr : LLVM_Attr<"LoopUnswitch", "loop_unswitch"> {
+ let description = [{
+ This attribute defines pipelining specific loop annotations that map to
+ the "!llvm.loop.unswitch" metadata.
+ }];
+
+ let parameters = (ins
+ OptionalParameter<"BoolAttr">:$partialDisable
+ );
+
+ let assemblyFormat = "`<` struct(params) `>`";
+}
+
def LoopAnnotationAttr : LLVM_Attr<"LoopAnnotation", "loop_annotation"> {
let description = [{
This attributes encapsulates "loop metadata". It is meant to decorate
OptionalParameter<"LoopLICMAttr">:$licm,
OptionalParameter<"LoopDistributeAttr">:$distribute,
OptionalParameter<"LoopPipelineAttr">:$pipeline,
+ OptionalParameter<"LoopPeeledAttr">:$peeled,
+ OptionalParameter<"LoopUnswitchAttr">:$unswitch,
OptionalParameter<"BoolAttr">:$mustProgress,
OptionalParameter<"BoolAttr">:$isVectorized,
OptionalArrayRefParameter<"SymbolRefAttr">:$parallelAccesses
DISubprogramAttr, DISubroutineTypeAttr, LoopAnnotationAttr,
LoopVectorizeAttr, LoopInterleaveAttr, LoopUnrollAttr,
LoopUnrollAndJamAttr, LoopLICMAttr, LoopDistributeAttr,
- LoopPipelineAttr>([&](auto attr) {
- os << decltype(attr)::getMnemonic();
- return AliasResult::OverridableAlias;
- })
+ LoopPipelineAttr, LoopPeeledAttr, LoopUnswitchAttr>(
+ [&](auto attr) {
+ os << decltype(attr)::getMnemonic();
+ return AliasResult::OverridableAlias;
+ })
.Default([](Attribute) { return AliasResult::NoAlias; });
}
};
FailureOr<LoopLICMAttr> convertLICMAttr();
FailureOr<LoopDistributeAttr> convertDistributeAttr();
FailureOr<LoopPipelineAttr> convertPipelineAttr();
+ FailureOr<LoopPeeledAttr> convertPeeledAttr();
+ FailureOr<LoopUnswitchAttr> convertUnswitchAttr();
FailureOr<SmallVector<SymbolRefAttr>> convertParallelAccesses();
llvm::StringMap<const llvm::MDNode *> propertyMap;
return createIfNonNull<LoopPipelineAttr>(ctx, disable, initiationinterval);
}
+FailureOr<LoopPeeledAttr> LoopMetadataConversion::convertPeeledAttr() {
+ FailureOr<IntegerAttr> count = lookupIntNode("llvm.loop.peeled.count");
+ return createIfNonNull<LoopPeeledAttr>(ctx, count);
+}
+
+FailureOr<LoopUnswitchAttr> LoopMetadataConversion::convertUnswitchAttr() {
+ FailureOr<BoolAttr> partialDisable =
+ lookupUnitNode("llvm.loop.unswitch.partial.disable");
+ return createIfNonNull<LoopUnswitchAttr>(ctx, partialDisable);
+}
+
FailureOr<SmallVector<SymbolRefAttr>>
LoopMetadataConversion::convertParallelAccesses() {
FailureOr<SmallVector<llvm::MDNode *>> nodes =
FailureOr<LoopLICMAttr> licmAttr = convertLICMAttr();
FailureOr<LoopDistributeAttr> distributeAttr = convertDistributeAttr();
FailureOr<LoopPipelineAttr> pipelineAttr = convertPipelineAttr();
+ FailureOr<LoopPeeledAttr> peeledAttr = convertPeeledAttr();
+ FailureOr<LoopUnswitchAttr> unswitchAttr = convertUnswitchAttr();
FailureOr<BoolAttr> mustProgress = lookupUnitNode("llvm.loop.mustprogress");
FailureOr<BoolAttr> isVectorized =
lookupIntNodeAsBoolAttr("llvm.loop.isvectorized");
return createIfNonNull<LoopAnnotationAttr>(
ctx, disableNonForced, vecAttr, interleaveAttr, unrollAttr,
- unrollAndJamAttr, licmAttr, distributeAttr, pipelineAttr, mustProgress,
- isVectorized, parallelAccesses);
+ unrollAndJamAttr, licmAttr, distributeAttr, pipelineAttr, peeledAttr,
+ unswitchAttr, mustProgress, isVectorized, parallelAccesses);
}
LoopAnnotationAttr
void convertLoopOptions(LoopLICMAttr options);
void convertLoopOptions(LoopDistributeAttr options);
void convertLoopOptions(LoopPipelineAttr options);
+ void convertLoopOptions(LoopPeeledAttr options);
+ void convertLoopOptions(LoopUnswitchAttr options);
LoopAnnotationAttr attr;
ModuleTranslation &moduleTranslation;
options.getInitiationinterval());
}
+void LoopAnnotationConversion::convertLoopOptions(LoopPeeledAttr options) {
+ convertI32Node("llvm.loop.peeled.count", options.getCount());
+}
+
+void LoopAnnotationConversion::convertLoopOptions(LoopUnswitchAttr options) {
+ addUnitNode("llvm.loop.unswitch.partial.disable",
+ options.getPartialDisable());
+}
+
llvm::MDNode *LoopAnnotationConversion::convert() {
// Reserve operand 0 for loop id self reference.
convertLoopOptions(options);
if (auto options = attr.getPipeline())
convertLoopOptions(options);
+ if (auto options = attr.getPeeled())
+ convertLoopOptions(options);
+ if (auto options = attr.getUnswitch())
+ convertLoopOptions(options);
ArrayRef<SymbolRefAttr> parallelAccessGroups = attr.getParallelAccesses();
if (!parallelAccessGroups.empty()) {
// CHECK-DAG: #[[PIPELINE:.*]] = #llvm.loop_pipeline<disable = true, initiationinterval = 1 : i32>
#pipeline = #llvm.loop_pipeline<disable = true, initiationinterval = 1 : i32>
+// CHECK-DAG: #[[PEELED:.*]] = #llvm.loop_peeled<count = 8 : i32>
+#peeled = #llvm.loop_peeled<count = 8 : i32>
+
+// CHECK-DAG: #[[UNSWITCH:.*]] = #llvm.loop_unswitch<partialDisable = true>
+#unswitch = #llvm.loop_unswitch<partialDisable = true>
+
// CHECK: #[[LOOP_ANNOT:.*]] = #llvm.loop_annotation<
// CHECK-DAG: disableNonforced = false
// CHECK-DAG: mustProgress = true
// CHECK-DAG: licm = #[[LICM]]
// CHECK-DAG: distribute = #[[DISTRIBUTE]]
// CHECK-DAG: pipeline = #[[PIPELINE]]
+// CHECK-DAG: peeled = #[[PEELED]]
+// CHECK-DAG: unswitch = #[[UNSWITCH]]
// CHECK-DAG: isVectorized = false
// CHECK-DAG: parallelAccesses = @metadata::@group1, @metadata::@group2>
#loopMD = #llvm.loop_annotation<disableNonforced = false,
licm = #licm,
distribute = #distribute,
pipeline = #pipeline,
+ peeled = #peeled,
+ unswitch = #unswitch,
isVectorized = false,
parallelAccesses = @metadata::@group1, @metadata::@group2>
; // -----
+; CHECK-DAG: #[[PEELED_ATTR:.*]] = #llvm.loop_peeled<count = 5 : i32>
+; CHECK-DAG: #[[$ANNOT_ATTR:.*]] = #llvm.loop_annotation<peeled = #[[PEELED_ATTR]]>
+
+; CHECK-LABEL: @peeled
+define void @peeled(i64 %n, ptr %A) {
+entry:
+; CHECK: llvm.br ^{{.*}} {llvm.loop = #[[$ANNOT_ATTR]]}
+ br label %end, !llvm.loop !1
+end:
+ ret void
+}
+
+!1 = distinct !{!1, !2}
+!2 = !{!"llvm.loop.peeled.count", i32 5}
+
+; // -----
+
+; CHECK-DAG: #[[UNSWITCH_ATTR:.*]] = #llvm.loop_unswitch<partialDisable = true>
+; CHECK-DAG: #[[$ANNOT_ATTR:.*]] = #llvm.loop_annotation<unswitch = #[[UNSWITCH_ATTR]]>
+
+; CHECK-LABEL: @unswitched
+define void @unswitched(i64 %n, ptr %A) {
+entry:
+; CHECK: llvm.br ^{{.*}} {llvm.loop = #[[$ANNOT_ATTR]]}
+ br label %end, !llvm.loop !1
+end:
+ ret void
+}
+
+!1 = distinct !{!1, !2}
+!2 = !{!"llvm.loop.unswitch.partial.disable"}
+
+; // -----
+
; CHECK: #[[$ANNOT_ATTR:.*]] = #llvm.loop_annotation<parallelAccesses = @__llvm_global_metadata::@[[GROUP0:.*]]>
; CHECK: llvm.metadata @__llvm_global_metadata {
// -----
+// CHECK-LABEL: @peeledOptions
+llvm.func @peeledOptions() {
+ // CHECK: br {{.*}} !llvm.loop ![[LOOP_NODE:[0-9]+]]
+ llvm.br ^bb1 {llvm.loop = #llvm.loop_annotation<peeled = <count = 3 : i32>>}
+^bb1:
+ llvm.return
+}
+
+// CHECK: ![[LOOP_NODE]] = distinct !{![[LOOP_NODE]], !{{[0-9]+}}}
+// CHECK-DAG: ![[VEC_NODE0:[0-9]+]] = !{!"llvm.loop.peeled.count", i32 3}
+
+// -----
+
+// CHECK-LABEL: @unswitchOptions
+llvm.func @unswitchOptions() {
+ // CHECK: br {{.*}} !llvm.loop ![[LOOP_NODE:[0-9]+]]
+ llvm.br ^bb1 {llvm.loop = #llvm.loop_annotation<unswitch = <partialDisable = true>>}
+^bb1:
+ llvm.return
+}
+
+// CHECK: ![[LOOP_NODE]] = distinct !{![[LOOP_NODE]], !{{[0-9]+}}}
+// CHECK-DAG: ![[VEC_NODE0:[0-9]+]] = !{!"llvm.loop.unswitch.partial.disable"}
+
+// -----
+
// CHECK-LABEL: @loopOptions
llvm.func @loopOptions(%arg1 : i32, %arg2 : i32) {
%0 = llvm.mlir.constant(0 : i32) : i32