[clang] [llvm] [HLSL] Add support to branch/flatten attributes to switch (PR #131739)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 17 23:37:50 PDT 2025
https://github.com/joaosaffran created https://github.com/llvm/llvm-project/pull/131739
closes: [#125754](https://github.com/llvm/llvm-project/issues/125754)
>From 145b3b1c10faffa15477083e530fcc50c71ff2ea Mon Sep 17 00:00:00 2001
From: joaosaffran <joao.saffran at microsoft.com>
Date: Tue, 18 Mar 2025 06:14:12 +0000
Subject: [PATCH 1/3] adding support to attr
---
clang/include/clang/Basic/Attr.td | 4 +-
clang/lib/CodeGen/CGStmt.cpp | 23 ++
clang/test/AST/HLSL/HLSLControlFlowHint.hlsl | 59 +++++
clang/test/AST/HLSL/HLSLControlFlowHint.ll | 211 ++++++++++++++++++
.../CodeGen/DirectX/HLSLControlFlowHint.ll | 131 +++++++++++
.../SPIRV/structurizer/HLSLControlFlowHint.ll | 125 ++++++++++-
6 files changed, 548 insertions(+), 5 deletions(-)
create mode 100644 clang/test/AST/HLSL/HLSLControlFlowHint.ll
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index d9840dad6a5e2..948fc99c9b083 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4394,8 +4394,8 @@ def HLSLControlFlowHint: StmtAttr {
/// [branch]
/// [flatten]
let Spellings = [Microsoft<"branch">, Microsoft<"flatten">];
- let Subjects = SubjectList<[IfStmt],
- ErrorDiag, "'if' statements">;
+ let Subjects = SubjectList<[IfStmt, SwitchStmt],
+ ErrorDiag, "'if' and 'switch' statements">;
let LangOpts = [HLSL];
let Documentation = [InternalOnly];
}
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index 9860f23dc9e28..ef963fc4984d4 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -2276,6 +2276,29 @@ void CodeGenFunction::EmitSwitchStmt(const SwitchStmt &S) {
// failure.
llvm::BasicBlock *DefaultBlock = createBasicBlock("sw.default");
SwitchInsn = Builder.CreateSwitch(CondV, DefaultBlock);
+ switch (HLSLControlFlowAttr) {
+ case HLSLControlFlowHintAttr::Microsoft_branch:
+ case HLSLControlFlowHintAttr::Microsoft_flatten: {
+ llvm::MDBuilder MDHelper(CGM.getLLVMContext());
+
+ llvm::ConstantInt *BranchHintConstant =
+ HLSLControlFlowAttr ==
+ HLSLControlFlowHintAttr::Spelling::Microsoft_branch
+ ? llvm::ConstantInt::get(CGM.Int32Ty, 1)
+ : llvm::ConstantInt::get(CGM.Int32Ty, 2);
+
+ SmallVector<llvm::Metadata *, 2> Vals(
+ {MDHelper.createString("hlsl.controlflow.hint"),
+ MDHelper.createConstant(BranchHintConstant)});
+ SwitchInsn->setMetadata("hlsl.controlflow.hint",
+ llvm::MDNode::get(CGM.getLLVMContext(), Vals));
+ break;
+ }
+ // This is required to avoid warnings during compilation
+ case HLSLControlFlowHintAttr::SpellingNotCalculated:
+ break;
+ }
+
if (PGO.haveRegionCounts()) {
// Walk the SwitchCase list to find how many there are.
uint64_t DefaultCount = 0;
diff --git a/clang/test/AST/HLSL/HLSLControlFlowHint.hlsl b/clang/test/AST/HLSL/HLSLControlFlowHint.hlsl
index c1e6d969c8d31..18263bedbe3ec 100644
--- a/clang/test/AST/HLSL/HLSLControlFlowHint.hlsl
+++ b/clang/test/AST/HLSL/HLSLControlFlowHint.hlsl
@@ -41,3 +41,62 @@ export int no_attr(int X){
return resp;
}
+
+// CHECK: FunctionDecl {{.*}} used flatten_switch 'int (int)'
+// CHECK: AttributedStmt
+// CHECK-NEXT: HLSLControlFlowHintAttr {{.*}} flatten
+export int flatten_switch(int X){
+ int resp;
+ [flatten]
+ switch (X) {
+ case 0:
+ resp = -X;
+ break;
+ case 1:
+ resp = X+X;
+ break;
+ case 2:
+ resp = X * X; break;
+ }
+
+ return resp;
+}
+
+// CHECK: FunctionDecl {{.*}} used branch_switch 'int (int)'
+// CHECK: AttributedStmt
+// CHECK-NEXT: HLSLControlFlowHintAttr {{.*}} branch
+export int branch_switch(int X){
+ int resp;
+ [branch]
+ switch (X) {
+ case 0:
+ resp = -X;
+ break;
+ case 1:
+ resp = X+X;
+ break;
+ case 2:
+ resp = X * X; break;
+ }
+
+ return resp;
+}
+
+// CHECK: FunctionDecl {{.*}} used no_attr_switch 'int (int)'
+// CHECK-NOT: AttributedStmt
+// CHECK-NOT: HLSLControlFlowHintAttr
+export int no_attr_switch(int X){
+ int resp;
+ switch (X) {
+ case 0:
+ resp = -X;
+ break;
+ case 1:
+ resp = X+X;
+ break;
+ case 2:
+ resp = X * X; break;
+ }
+
+ return resp;
+}
diff --git a/clang/test/AST/HLSL/HLSLControlFlowHint.ll b/clang/test/AST/HLSL/HLSLControlFlowHint.ll
new file mode 100644
index 0000000000000..0314f9d2c4751
--- /dev/null
+++ b/clang/test/AST/HLSL/HLSLControlFlowHint.ll
@@ -0,0 +1,211 @@
+; ModuleID = '/workspace/llvm-project/clang/test/AST/HLSL/HLSLControlFlowHint.hlsl'
+source_filename = "/workspace/llvm-project/clang/test/AST/HLSL/HLSLControlFlowHint.hlsl"
+target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64"
+target triple = "dxilv1.3-pc-shadermodel6.3-compute"
+
+; Function Attrs: alwaysinline convergent mustprogress norecurse nounwind
+define noundef i32 @_Z6branchi(i32 noundef %X) #0 {
+entry:
+ %X.addr = alloca i32, align 4
+ %resp = alloca i32, align 4
+ store i32 %X, ptr %X.addr, align 4
+ %0 = load i32, ptr %X.addr, align 4
+ %cmp = icmp sgt i32 %0, 0
+ br i1 %cmp, label %if.then, label %if.else, !hlsl.controlflow.hint !3
+
+if.then: ; preds = %entry
+ %1 = load i32, ptr %X.addr, align 4
+ %sub = sub nsw i32 0, %1
+ store i32 %sub, ptr %resp, align 4
+ br label %if.end
+
+if.else: ; preds = %entry
+ %2 = load i32, ptr %X.addr, align 4
+ %mul = mul nsw i32 %2, 2
+ store i32 %mul, ptr %resp, align 4
+ br label %if.end
+
+if.end: ; preds = %if.else, %if.then
+ %3 = load i32, ptr %resp, align 4
+ ret i32 %3
+}
+
+; Function Attrs: alwaysinline convergent mustprogress norecurse nounwind
+define noundef i32 @_Z7flatteni(i32 noundef %X) #0 {
+entry:
+ %X.addr = alloca i32, align 4
+ %resp = alloca i32, align 4
+ store i32 %X, ptr %X.addr, align 4
+ %0 = load i32, ptr %X.addr, align 4
+ %cmp = icmp sgt i32 %0, 0
+ br i1 %cmp, label %if.then, label %if.else, !hlsl.controlflow.hint !4
+
+if.then: ; preds = %entry
+ %1 = load i32, ptr %X.addr, align 4
+ %sub = sub nsw i32 0, %1
+ store i32 %sub, ptr %resp, align 4
+ br label %if.end
+
+if.else: ; preds = %entry
+ %2 = load i32, ptr %X.addr, align 4
+ %mul = mul nsw i32 %2, 2
+ store i32 %mul, ptr %resp, align 4
+ br label %if.end
+
+if.end: ; preds = %if.else, %if.then
+ %3 = load i32, ptr %resp, align 4
+ ret i32 %3
+}
+
+; Function Attrs: alwaysinline convergent mustprogress norecurse nounwind
+define noundef i32 @_Z7no_attri(i32 noundef %X) #0 {
+entry:
+ %X.addr = alloca i32, align 4
+ %resp = alloca i32, align 4
+ store i32 %X, ptr %X.addr, align 4
+ %0 = load i32, ptr %X.addr, align 4
+ %cmp = icmp sgt i32 %0, 0
+ br i1 %cmp, label %if.then, label %if.else
+
+if.then: ; preds = %entry
+ %1 = load i32, ptr %X.addr, align 4
+ %sub = sub nsw i32 0, %1
+ store i32 %sub, ptr %resp, align 4
+ br label %if.end
+
+if.else: ; preds = %entry
+ %2 = load i32, ptr %X.addr, align 4
+ %mul = mul nsw i32 %2, 2
+ store i32 %mul, ptr %resp, align 4
+ br label %if.end
+
+if.end: ; preds = %if.else, %if.then
+ %3 = load i32, ptr %resp, align 4
+ ret i32 %3
+}
+
+; Function Attrs: alwaysinline convergent mustprogress norecurse nounwind
+define noundef i32 @_Z14flatten_switchi(i32 noundef %X) #0 {
+entry:
+ %X.addr = alloca i32, align 4
+ %resp = alloca i32, align 4
+ store i32 %X, ptr %X.addr, align 4
+ %0 = load i32, ptr %X.addr, align 4
+ switch i32 %0, label %sw.epilog [
+ i32 0, label %sw.bb
+ i32 1, label %sw.bb1
+ i32 2, label %sw.bb2
+ ], !hlsl.controlflow.hint !4
+
+sw.bb: ; preds = %entry
+ %1 = load i32, ptr %X.addr, align 4
+ %sub = sub nsw i32 0, %1
+ store i32 %sub, ptr %resp, align 4
+ br label %sw.epilog
+
+sw.bb1: ; preds = %entry
+ %2 = load i32, ptr %X.addr, align 4
+ %3 = load i32, ptr %X.addr, align 4
+ %add = add nsw i32 %2, %3
+ store i32 %add, ptr %resp, align 4
+ br label %sw.epilog
+
+sw.bb2: ; preds = %entry
+ %4 = load i32, ptr %X.addr, align 4
+ %5 = load i32, ptr %X.addr, align 4
+ %mul = mul nsw i32 %4, %5
+ store i32 %mul, ptr %resp, align 4
+ br label %sw.epilog
+
+sw.epilog: ; preds = %entry, %sw.bb2, %sw.bb1, %sw.bb
+ %6 = load i32, ptr %resp, align 4
+ ret i32 %6
+}
+
+; Function Attrs: alwaysinline convergent mustprogress norecurse nounwind
+define noundef i32 @_Z13branch_switchi(i32 noundef %X) #0 {
+entry:
+ %X.addr = alloca i32, align 4
+ %resp = alloca i32, align 4
+ store i32 %X, ptr %X.addr, align 4
+ %0 = load i32, ptr %X.addr, align 4
+ switch i32 %0, label %sw.epilog [
+ i32 0, label %sw.bb
+ i32 1, label %sw.bb1
+ i32 2, label %sw.bb2
+ ], !hlsl.controlflow.hint !3
+
+sw.bb: ; preds = %entry
+ %1 = load i32, ptr %X.addr, align 4
+ %sub = sub nsw i32 0, %1
+ store i32 %sub, ptr %resp, align 4
+ br label %sw.epilog
+
+sw.bb1: ; preds = %entry
+ %2 = load i32, ptr %X.addr, align 4
+ %3 = load i32, ptr %X.addr, align 4
+ %add = add nsw i32 %2, %3
+ store i32 %add, ptr %resp, align 4
+ br label %sw.epilog
+
+sw.bb2: ; preds = %entry
+ %4 = load i32, ptr %X.addr, align 4
+ %5 = load i32, ptr %X.addr, align 4
+ %mul = mul nsw i32 %4, %5
+ store i32 %mul, ptr %resp, align 4
+ br label %sw.epilog
+
+sw.epilog: ; preds = %entry, %sw.bb2, %sw.bb1, %sw.bb
+ %6 = load i32, ptr %resp, align 4
+ ret i32 %6
+}
+
+; Function Attrs: alwaysinline convergent mustprogress norecurse nounwind
+define noundef i32 @_Z14no_attr_switchi(i32 noundef %X) #0 {
+entry:
+ %X.addr = alloca i32, align 4
+ %resp = alloca i32, align 4
+ store i32 %X, ptr %X.addr, align 4
+ %0 = load i32, ptr %X.addr, align 4
+ switch i32 %0, label %sw.epilog [
+ i32 0, label %sw.bb
+ i32 1, label %sw.bb1
+ i32 2, label %sw.bb2
+ ]
+
+sw.bb: ; preds = %entry
+ %1 = load i32, ptr %X.addr, align 4
+ %sub = sub nsw i32 0, %1
+ store i32 %sub, ptr %resp, align 4
+ br label %sw.epilog
+
+sw.bb1: ; preds = %entry
+ %2 = load i32, ptr %X.addr, align 4
+ %3 = load i32, ptr %X.addr, align 4
+ %add = add nsw i32 %2, %3
+ store i32 %add, ptr %resp, align 4
+ br label %sw.epilog
+
+sw.bb2: ; preds = %entry
+ %4 = load i32, ptr %X.addr, align 4
+ %5 = load i32, ptr %X.addr, align 4
+ %mul = mul nsw i32 %4, %5
+ store i32 %mul, ptr %resp, align 4
+ br label %sw.epilog
+
+sw.epilog: ; preds = %entry, %sw.bb2, %sw.bb1, %sw.bb
+ %6 = load i32, ptr %resp, align 4
+ ret i32 %6
+}
+
+attributes #0 = { alwaysinline convergent mustprogress norecurse nounwind "approx-func-fp-math"="true" "hlsl.export" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
+
+!llvm.module.flags = !{!0}
+!dx.valver = !{!1}
+!llvm.ident = !{!2}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 1, i32 8}
+!2 = !{!"clang version 21.0.0git (https://github.com/joaosaffran/llvm-project.git fe0db909f0b0d61dbc0d2f7a3313138808c20194)"}
+!3 = !{!"hlsl.controlflow.hint", i32 1}
+!4 = !{!"hlsl.controlflow.hint", i32 2}
diff --git a/llvm/test/CodeGen/DirectX/HLSLControlFlowHint.ll b/llvm/test/CodeGen/DirectX/HLSLControlFlowHint.ll
index 6a5274429930e..00dd374daf460 100644
--- a/llvm/test/CodeGen/DirectX/HLSLControlFlowHint.ll
+++ b/llvm/test/CodeGen/DirectX/HLSLControlFlowHint.ll
@@ -91,6 +91,137 @@ if.end: ; preds = %if.else, %if.then
%3 = load i32, ptr %resp, align 4
ret i32 %3
}
+
+; CHECK: define i32 @flatten_switch(i32 %X)
+; CHECK-NOT: hlsl.controlflow.hint
+; CHECK: switch i32 %0, label %sw.epilog [
+; CHECK-NEXT: i32 0, label %sw.bb
+; CHECK-NEXT: i32 1, label %sw.bb1
+; CHECK-NEXT: i32 2, label %sw.bb2
+; CHECK-NEXT: ], !dx.controlflow.hints [[HINT_FLATTEN]]
+define i32 @flatten_switch(i32 %X) #0 {
+entry:
+ %X.addr = alloca i32, align 4
+ %resp = alloca i32, align 4
+ store i32 %X, ptr %X.addr, align 4
+ %0 = load i32, ptr %X.addr, align 4
+ switch i32 %0, label %sw.epilog [
+ i32 0, label %sw.bb
+ i32 1, label %sw.bb1
+ i32 2, label %sw.bb2
+ ], !hlsl.controlflow.hint !1
+
+sw.bb: ; preds = %entry
+ %1 = load i32, ptr %X.addr, align 4
+ %sub = sub nsw i32 0, %1
+ store i32 %sub, ptr %resp, align 4
+ br label %sw.epilog
+
+sw.bb1: ; preds = %entry
+ %2 = load i32, ptr %X.addr, align 4
+ %3 = load i32, ptr %X.addr, align 4
+ %add = add nsw i32 %2, %3
+ store i32 %add, ptr %resp, align 4
+ br label %sw.epilog
+
+sw.bb2: ; preds = %entry
+ %4 = load i32, ptr %X.addr, align 4
+ %5 = load i32, ptr %X.addr, align 4
+ %mul = mul nsw i32 %4, %5
+ store i32 %mul, ptr %resp, align 4
+ br label %sw.epilog
+
+sw.epilog: ; preds = %entry, %sw.bb2, %sw.bb1, %sw.bb
+ %6 = load i32, ptr %resp, align 4
+ ret i32 %6
+}
+
+
+; CHECK: define i32 @branch_switch(i32 %X)
+; CHECK-NOT: hlsl.controlflow.hint
+; CHECK: switch i32 %0, label %sw.epilog [
+; CHECK-NEXT: i32 0, label %sw.bb
+; CHECK-NEXT: i32 1, label %sw.bb1
+; CHECK-NEXT: i32 2, label %sw.bb2
+; CHECK-NEXT: ], !dx.controlflow.hints [[HINT_BRANCH]]
+define i32 @branch_switch(i32 %X) #0 {
+entry:
+ %X.addr = alloca i32, align 4
+ %resp = alloca i32, align 4
+ store i32 %X, ptr %X.addr, align 4
+ %0 = load i32, ptr %X.addr, align 4
+ switch i32 %0, label %sw.epilog [
+ i32 0, label %sw.bb
+ i32 1, label %sw.bb1
+ i32 2, label %sw.bb2
+ ], !hlsl.controlflow.hint !0
+
+sw.bb: ; preds = %entry
+ %1 = load i32, ptr %X.addr, align 4
+ %sub = sub nsw i32 0, %1
+ store i32 %sub, ptr %resp, align 4
+ br label %sw.epilog
+
+sw.bb1: ; preds = %entry
+ %2 = load i32, ptr %X.addr, align 4
+ %3 = load i32, ptr %X.addr, align 4
+ %add = add nsw i32 %2, %3
+ store i32 %add, ptr %resp, align 4
+ br label %sw.epilog
+
+sw.bb2: ; preds = %entry
+ %4 = load i32, ptr %X.addr, align 4
+ %5 = load i32, ptr %X.addr, align 4
+ %mul = mul nsw i32 %4, %5
+ store i32 %mul, ptr %resp, align 4
+ br label %sw.epilog
+
+sw.epilog: ; preds = %entry, %sw.bb2, %sw.bb1, %sw.bb
+ %6 = load i32, ptr %resp, align 4
+ ret i32 %6
+}
+
+
+; CHECK: define i32 @no_attr_switch(i32 %X)
+; CHECK-NOT: hlsl.controlflow.hint
+; CHECK-NOT: !dx.controlflow.hints
+define i32 @no_attr_switch(i32 %X) #0 {
+entry:
+ %X.addr = alloca i32, align 4
+ %resp = alloca i32, align 4
+ store i32 %X, ptr %X.addr, align 4
+ %0 = load i32, ptr %X.addr, align 4
+ switch i32 %0, label %sw.epilog [
+ i32 0, label %sw.bb
+ i32 1, label %sw.bb1
+ i32 2, label %sw.bb2
+ ]
+
+sw.bb: ; preds = %entry
+ %1 = load i32, ptr %X.addr, align 4
+ %sub = sub nsw i32 0, %1
+ store i32 %sub, ptr %resp, align 4
+ br label %sw.epilog
+
+sw.bb1: ; preds = %entry
+ %2 = load i32, ptr %X.addr, align 4
+ %3 = load i32, ptr %X.addr, align 4
+ %add = add nsw i32 %2, %3
+ store i32 %add, ptr %resp, align 4
+ br label %sw.epilog
+
+sw.bb2: ; preds = %entry
+ %4 = load i32, ptr %X.addr, align 4
+ %5 = load i32, ptr %X.addr, align 4
+ %mul = mul nsw i32 %4, %5
+ store i32 %mul, ptr %resp, align 4
+ br label %sw.epilog
+
+sw.epilog: ; preds = %entry, %sw.bb2, %sw.bb1, %sw.bb
+ %6 = load i32, ptr %resp, align 4
+ ret i32 %6
+}
+
; CHECK-NOT: hlsl.controlflow.hint
; CHECK: [[HINT_BRANCH]] = !{!"dx.controlflow.hints", i32 1}
; CHECK: [[HINT_FLATTEN]] = !{!"dx.controlflow.hints", i32 2}
diff --git a/llvm/test/CodeGen/SPIRV/structurizer/HLSLControlFlowHint.ll b/llvm/test/CodeGen/SPIRV/structurizer/HLSLControlFlowHint.ll
index 848eaf70f5a19..300b1c9672c8d 100644
--- a/llvm/test/CodeGen/SPIRV/structurizer/HLSLControlFlowHint.ll
+++ b/llvm/test/CodeGen/SPIRV/structurizer/HLSLControlFlowHint.ll
@@ -5,7 +5,7 @@
define spir_func noundef i32 @test_branch(i32 noundef %X) {
entry:
; CHECK-LABEL: ; -- Begin function test_branch
-; OpSelectionMerge %[[#]] DontFlatten
+ ; CHECK: OpSelectionMerge %[[#]] DontFlatten
%X.addr = alloca i32, align 4
%resp = alloca i32, align 4
store i32 %X, ptr %X.addr, align 4
@@ -34,7 +34,7 @@ if.end: ; preds = %if.else, %if.then
define spir_func noundef i32 @test_flatten(i32 noundef %X) {
entry:
; CHECK-LABEL: ; -- Begin function test_flatten
-; OpSelectionMerge %[[#]] Flatten
+ ; CHECK: OpSelectionMerge %[[#]] Flatten
%X.addr = alloca i32, align 4
%resp = alloca i32, align 4
store i32 %X, ptr %X.addr, align 4
@@ -62,7 +62,7 @@ if.end: ; preds = %if.else, %if.then
define spir_func noundef i32 @test_no_attr(i32 noundef %X) {
entry:
; CHECK-LABEL: ; -- Begin function test_no_attr
-; OpSelectionMerge %[[#]] None
+ ; CHECK: OpSelectionMerge %[[#]] None
%X.addr = alloca i32, align 4
%resp = alloca i32, align 4
store i32 %X, ptr %X.addr, align 4
@@ -87,5 +87,124 @@ if.end: ; preds = %if.else, %if.then
ret i32 %3
}
+define spir_func noundef i32 @flatten_switch(i32 noundef %X) {
+entry:
+; CHECK-LABEL: ; -- Begin function flatten_switch
+ ; CHECK: OpSelectionMerge %[[#]] Flatten
+ %X.addr = alloca i32, align 4
+ %resp = alloca i32, align 4
+ store i32 %X, ptr %X.addr, align 4
+ %0 = load i32, ptr %X.addr, align 4
+ switch i32 %0, label %sw.epilog [
+ i32 0, label %sw.bb
+ i32 1, label %sw.bb1
+ i32 2, label %sw.bb2
+ ], !hlsl.controlflow.hint !1
+
+sw.bb: ; preds = %entry
+ %1 = load i32, ptr %X.addr, align 4
+ %sub = sub nsw i32 0, %1
+ store i32 %sub, ptr %resp, align 4
+ br label %sw.epilog
+
+sw.bb1: ; preds = %entry
+ %2 = load i32, ptr %X.addr, align 4
+ %3 = load i32, ptr %X.addr, align 4
+ %add = add nsw i32 %2, %3
+ store i32 %add, ptr %resp, align 4
+ br label %sw.epilog
+
+sw.bb2: ; preds = %entry
+ %4 = load i32, ptr %X.addr, align 4
+ %5 = load i32, ptr %X.addr, align 4
+ %mul = mul nsw i32 %4, %5
+ store i32 %mul, ptr %resp, align 4
+ br label %sw.epilog
+
+sw.epilog: ; preds = %entry, %sw.bb2, %sw.bb1, %sw.bb
+ %6 = load i32, ptr %resp, align 4
+ ret i32 %6
+}
+
+
+define spir_func noundef i32 @branch_switch(i32 noundef %X) {
+ entry:
+ ; CHECK-LABEL: ; -- Begin function branch_switch
+ ; CHECK: OpSelectionMerge %[[#]] DontFlatten
+ %X.addr = alloca i32, align 4
+ %resp = alloca i32, align 4
+ store i32 %X, ptr %X.addr, align 4
+ %0 = load i32, ptr %X.addr, align 4
+ switch i32 %0, label %sw.epilog [
+ i32 0, label %sw.bb
+ i32 1, label %sw.bb1
+ i32 2, label %sw.bb2
+ ], !hlsl.controlflow.hint !0
+
+sw.bb: ; preds = %entry
+ %1 = load i32, ptr %X.addr, align 4
+ %sub = sub nsw i32 0, %1
+ store i32 %sub, ptr %resp, align 4
+ br label %sw.epilog
+
+sw.bb1: ; preds = %entry
+ %2 = load i32, ptr %X.addr, align 4
+ %3 = load i32, ptr %X.addr, align 4
+ %add = add nsw i32 %2, %3
+ store i32 %add, ptr %resp, align 4
+ br label %sw.epilog
+
+sw.bb2: ; preds = %entry
+ %4 = load i32, ptr %X.addr, align 4
+ %5 = load i32, ptr %X.addr, align 4
+ %mul = mul nsw i32 %4, %5
+ store i32 %mul, ptr %resp, align 4
+ br label %sw.epilog
+
+sw.epilog: ; preds = %entry, %sw.bb2, %sw.bb1, %sw.bb
+ %6 = load i32, ptr %resp, align 4
+ ret i32 %6
+}
+
+
+define spir_func noundef i32 @no_attr_switch(i32 noundef %X) {
+ ; CHECK-LABEL: ; -- Begin function no_attr_switch
+ ; CHECK: OpSelectionMerge %[[#]] None
+entry:
+ %X.addr = alloca i32, align 4
+ %resp = alloca i32, align 4
+ store i32 %X, ptr %X.addr, align 4
+ %0 = load i32, ptr %X.addr, align 4
+ switch i32 %0, label %sw.epilog [
+ i32 0, label %sw.bb
+ i32 1, label %sw.bb1
+ i32 2, label %sw.bb2
+ ]
+
+sw.bb: ; preds = %entry
+ %1 = load i32, ptr %X.addr, align 4
+ %sub = sub nsw i32 0, %1
+ store i32 %sub, ptr %resp, align 4
+ br label %sw.epilog
+
+sw.bb1: ; preds = %entry
+ %2 = load i32, ptr %X.addr, align 4
+ %3 = load i32, ptr %X.addr, align 4
+ %add = add nsw i32 %2, %3
+ store i32 %add, ptr %resp, align 4
+ br label %sw.epilog
+
+sw.bb2: ; preds = %entry
+ %4 = load i32, ptr %X.addr, align 4
+ %5 = load i32, ptr %X.addr, align 4
+ %mul = mul nsw i32 %4, %5
+ store i32 %mul, ptr %resp, align 4
+ br label %sw.epilog
+
+sw.epilog: ; preds = %entry, %sw.bb2, %sw.bb1, %sw.bb
+ %6 = load i32, ptr %resp, align 4
+ ret i32 %6
+}
+
!0 = !{!"hlsl.controlflow.hint", i32 1}
!1 = !{!"hlsl.controlflow.hint", i32 2}
>From 814687fa0181f0401484328727a5a2c5e4ac95ee Mon Sep 17 00:00:00 2001
From: joaosaffran <joao.saffran at microsoft.com>
Date: Tue, 18 Mar 2025 06:33:59 +0000
Subject: [PATCH 2/3] removing file
---
clang/test/AST/HLSL/HLSLControlFlowHint.ll | 211 ---------------------
1 file changed, 211 deletions(-)
delete mode 100644 clang/test/AST/HLSL/HLSLControlFlowHint.ll
diff --git a/clang/test/AST/HLSL/HLSLControlFlowHint.ll b/clang/test/AST/HLSL/HLSLControlFlowHint.ll
deleted file mode 100644
index 0314f9d2c4751..0000000000000
--- a/clang/test/AST/HLSL/HLSLControlFlowHint.ll
+++ /dev/null
@@ -1,211 +0,0 @@
-; ModuleID = '/workspace/llvm-project/clang/test/AST/HLSL/HLSLControlFlowHint.hlsl'
-source_filename = "/workspace/llvm-project/clang/test/AST/HLSL/HLSLControlFlowHint.hlsl"
-target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64"
-target triple = "dxilv1.3-pc-shadermodel6.3-compute"
-
-; Function Attrs: alwaysinline convergent mustprogress norecurse nounwind
-define noundef i32 @_Z6branchi(i32 noundef %X) #0 {
-entry:
- %X.addr = alloca i32, align 4
- %resp = alloca i32, align 4
- store i32 %X, ptr %X.addr, align 4
- %0 = load i32, ptr %X.addr, align 4
- %cmp = icmp sgt i32 %0, 0
- br i1 %cmp, label %if.then, label %if.else, !hlsl.controlflow.hint !3
-
-if.then: ; preds = %entry
- %1 = load i32, ptr %X.addr, align 4
- %sub = sub nsw i32 0, %1
- store i32 %sub, ptr %resp, align 4
- br label %if.end
-
-if.else: ; preds = %entry
- %2 = load i32, ptr %X.addr, align 4
- %mul = mul nsw i32 %2, 2
- store i32 %mul, ptr %resp, align 4
- br label %if.end
-
-if.end: ; preds = %if.else, %if.then
- %3 = load i32, ptr %resp, align 4
- ret i32 %3
-}
-
-; Function Attrs: alwaysinline convergent mustprogress norecurse nounwind
-define noundef i32 @_Z7flatteni(i32 noundef %X) #0 {
-entry:
- %X.addr = alloca i32, align 4
- %resp = alloca i32, align 4
- store i32 %X, ptr %X.addr, align 4
- %0 = load i32, ptr %X.addr, align 4
- %cmp = icmp sgt i32 %0, 0
- br i1 %cmp, label %if.then, label %if.else, !hlsl.controlflow.hint !4
-
-if.then: ; preds = %entry
- %1 = load i32, ptr %X.addr, align 4
- %sub = sub nsw i32 0, %1
- store i32 %sub, ptr %resp, align 4
- br label %if.end
-
-if.else: ; preds = %entry
- %2 = load i32, ptr %X.addr, align 4
- %mul = mul nsw i32 %2, 2
- store i32 %mul, ptr %resp, align 4
- br label %if.end
-
-if.end: ; preds = %if.else, %if.then
- %3 = load i32, ptr %resp, align 4
- ret i32 %3
-}
-
-; Function Attrs: alwaysinline convergent mustprogress norecurse nounwind
-define noundef i32 @_Z7no_attri(i32 noundef %X) #0 {
-entry:
- %X.addr = alloca i32, align 4
- %resp = alloca i32, align 4
- store i32 %X, ptr %X.addr, align 4
- %0 = load i32, ptr %X.addr, align 4
- %cmp = icmp sgt i32 %0, 0
- br i1 %cmp, label %if.then, label %if.else
-
-if.then: ; preds = %entry
- %1 = load i32, ptr %X.addr, align 4
- %sub = sub nsw i32 0, %1
- store i32 %sub, ptr %resp, align 4
- br label %if.end
-
-if.else: ; preds = %entry
- %2 = load i32, ptr %X.addr, align 4
- %mul = mul nsw i32 %2, 2
- store i32 %mul, ptr %resp, align 4
- br label %if.end
-
-if.end: ; preds = %if.else, %if.then
- %3 = load i32, ptr %resp, align 4
- ret i32 %3
-}
-
-; Function Attrs: alwaysinline convergent mustprogress norecurse nounwind
-define noundef i32 @_Z14flatten_switchi(i32 noundef %X) #0 {
-entry:
- %X.addr = alloca i32, align 4
- %resp = alloca i32, align 4
- store i32 %X, ptr %X.addr, align 4
- %0 = load i32, ptr %X.addr, align 4
- switch i32 %0, label %sw.epilog [
- i32 0, label %sw.bb
- i32 1, label %sw.bb1
- i32 2, label %sw.bb2
- ], !hlsl.controlflow.hint !4
-
-sw.bb: ; preds = %entry
- %1 = load i32, ptr %X.addr, align 4
- %sub = sub nsw i32 0, %1
- store i32 %sub, ptr %resp, align 4
- br label %sw.epilog
-
-sw.bb1: ; preds = %entry
- %2 = load i32, ptr %X.addr, align 4
- %3 = load i32, ptr %X.addr, align 4
- %add = add nsw i32 %2, %3
- store i32 %add, ptr %resp, align 4
- br label %sw.epilog
-
-sw.bb2: ; preds = %entry
- %4 = load i32, ptr %X.addr, align 4
- %5 = load i32, ptr %X.addr, align 4
- %mul = mul nsw i32 %4, %5
- store i32 %mul, ptr %resp, align 4
- br label %sw.epilog
-
-sw.epilog: ; preds = %entry, %sw.bb2, %sw.bb1, %sw.bb
- %6 = load i32, ptr %resp, align 4
- ret i32 %6
-}
-
-; Function Attrs: alwaysinline convergent mustprogress norecurse nounwind
-define noundef i32 @_Z13branch_switchi(i32 noundef %X) #0 {
-entry:
- %X.addr = alloca i32, align 4
- %resp = alloca i32, align 4
- store i32 %X, ptr %X.addr, align 4
- %0 = load i32, ptr %X.addr, align 4
- switch i32 %0, label %sw.epilog [
- i32 0, label %sw.bb
- i32 1, label %sw.bb1
- i32 2, label %sw.bb2
- ], !hlsl.controlflow.hint !3
-
-sw.bb: ; preds = %entry
- %1 = load i32, ptr %X.addr, align 4
- %sub = sub nsw i32 0, %1
- store i32 %sub, ptr %resp, align 4
- br label %sw.epilog
-
-sw.bb1: ; preds = %entry
- %2 = load i32, ptr %X.addr, align 4
- %3 = load i32, ptr %X.addr, align 4
- %add = add nsw i32 %2, %3
- store i32 %add, ptr %resp, align 4
- br label %sw.epilog
-
-sw.bb2: ; preds = %entry
- %4 = load i32, ptr %X.addr, align 4
- %5 = load i32, ptr %X.addr, align 4
- %mul = mul nsw i32 %4, %5
- store i32 %mul, ptr %resp, align 4
- br label %sw.epilog
-
-sw.epilog: ; preds = %entry, %sw.bb2, %sw.bb1, %sw.bb
- %6 = load i32, ptr %resp, align 4
- ret i32 %6
-}
-
-; Function Attrs: alwaysinline convergent mustprogress norecurse nounwind
-define noundef i32 @_Z14no_attr_switchi(i32 noundef %X) #0 {
-entry:
- %X.addr = alloca i32, align 4
- %resp = alloca i32, align 4
- store i32 %X, ptr %X.addr, align 4
- %0 = load i32, ptr %X.addr, align 4
- switch i32 %0, label %sw.epilog [
- i32 0, label %sw.bb
- i32 1, label %sw.bb1
- i32 2, label %sw.bb2
- ]
-
-sw.bb: ; preds = %entry
- %1 = load i32, ptr %X.addr, align 4
- %sub = sub nsw i32 0, %1
- store i32 %sub, ptr %resp, align 4
- br label %sw.epilog
-
-sw.bb1: ; preds = %entry
- %2 = load i32, ptr %X.addr, align 4
- %3 = load i32, ptr %X.addr, align 4
- %add = add nsw i32 %2, %3
- store i32 %add, ptr %resp, align 4
- br label %sw.epilog
-
-sw.bb2: ; preds = %entry
- %4 = load i32, ptr %X.addr, align 4
- %5 = load i32, ptr %X.addr, align 4
- %mul = mul nsw i32 %4, %5
- store i32 %mul, ptr %resp, align 4
- br label %sw.epilog
-
-sw.epilog: ; preds = %entry, %sw.bb2, %sw.bb1, %sw.bb
- %6 = load i32, ptr %resp, align 4
- ret i32 %6
-}
-
-attributes #0 = { alwaysinline convergent mustprogress norecurse nounwind "approx-func-fp-math"="true" "hlsl.export" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
-
-!llvm.module.flags = !{!0}
-!dx.valver = !{!1}
-!llvm.ident = !{!2}
-
-!0 = !{i32 1, !"wchar_size", i32 4}
-!1 = !{i32 1, i32 8}
-!2 = !{!"clang version 21.0.0git (https://github.com/joaosaffran/llvm-project.git fe0db909f0b0d61dbc0d2f7a3313138808c20194)"}
-!3 = !{!"hlsl.controlflow.hint", i32 1}
-!4 = !{!"hlsl.controlflow.hint", i32 2}
>From e8fbd9675a033592a315c8d1f097edf701bbdb4c Mon Sep 17 00:00:00 2001
From: joaosaffran <joao.saffran at microsoft.com>
Date: Tue, 18 Mar 2025 06:35:08 +0000
Subject: [PATCH 3/3] fix format
---
.../SPIRV/structurizer/HLSLControlFlowHint.ll | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/llvm/test/CodeGen/SPIRV/structurizer/HLSLControlFlowHint.ll b/llvm/test/CodeGen/SPIRV/structurizer/HLSLControlFlowHint.ll
index 300b1c9672c8d..9c6f977dc9b34 100644
--- a/llvm/test/CodeGen/SPIRV/structurizer/HLSLControlFlowHint.ll
+++ b/llvm/test/CodeGen/SPIRV/structurizer/HLSLControlFlowHint.ll
@@ -5,7 +5,7 @@
define spir_func noundef i32 @test_branch(i32 noundef %X) {
entry:
; CHECK-LABEL: ; -- Begin function test_branch
- ; CHECK: OpSelectionMerge %[[#]] DontFlatten
+; CHECK: OpSelectionMerge %[[#]] DontFlatten
%X.addr = alloca i32, align 4
%resp = alloca i32, align 4
store i32 %X, ptr %X.addr, align 4
@@ -34,7 +34,7 @@ if.end: ; preds = %if.else, %if.then
define spir_func noundef i32 @test_flatten(i32 noundef %X) {
entry:
; CHECK-LABEL: ; -- Begin function test_flatten
- ; CHECK: OpSelectionMerge %[[#]] Flatten
+; CHECK: OpSelectionMerge %[[#]] Flatten
%X.addr = alloca i32, align 4
%resp = alloca i32, align 4
store i32 %X, ptr %X.addr, align 4
@@ -62,7 +62,7 @@ if.end: ; preds = %if.else, %if.then
define spir_func noundef i32 @test_no_attr(i32 noundef %X) {
entry:
; CHECK-LABEL: ; -- Begin function test_no_attr
- ; CHECK: OpSelectionMerge %[[#]] None
+; CHECK: OpSelectionMerge %[[#]] None
%X.addr = alloca i32, align 4
%resp = alloca i32, align 4
store i32 %X, ptr %X.addr, align 4
@@ -90,7 +90,7 @@ if.end: ; preds = %if.else, %if.then
define spir_func noundef i32 @flatten_switch(i32 noundef %X) {
entry:
; CHECK-LABEL: ; -- Begin function flatten_switch
- ; CHECK: OpSelectionMerge %[[#]] Flatten
+; CHECK: OpSelectionMerge %[[#]] Flatten
%X.addr = alloca i32, align 4
%resp = alloca i32, align 4
store i32 %X, ptr %X.addr, align 4
@@ -130,7 +130,7 @@ sw.epilog: ; preds = %entry, %sw.bb2, %sw
define spir_func noundef i32 @branch_switch(i32 noundef %X) {
entry:
; CHECK-LABEL: ; -- Begin function branch_switch
- ; CHECK: OpSelectionMerge %[[#]] DontFlatten
+ ; CHECK: OpSelectionMerge %[[#]] DontFlatten
%X.addr = alloca i32, align 4
%resp = alloca i32, align 4
store i32 %X, ptr %X.addr, align 4
@@ -169,7 +169,7 @@ sw.epilog: ; preds = %entry, %sw.bb2, %sw
define spir_func noundef i32 @no_attr_switch(i32 noundef %X) {
; CHECK-LABEL: ; -- Begin function no_attr_switch
- ; CHECK: OpSelectionMerge %[[#]] None
+; CHECK: OpSelectionMerge %[[#]] None
entry:
%X.addr = alloca i32, align 4
%resp = alloca i32, align 4
More information about the llvm-commits
mailing list