Skip to content

Commit 567b0f8

Browse files
joaosaffranjoaosaffran
and
joaosaffran
authored
[HLSL] Add support to branch/flatten attributes to switch (#131739)
closes: [#125754](#125754) --------- Co-authored-by: joaosaffran <[email protected]>
1 parent 20fc2d5 commit 567b0f8

File tree

5 files changed

+327
-5
lines changed

5 files changed

+327
-5
lines changed

clang/include/clang/Basic/Attr.td

+2-2
Original file line numberDiff line numberDiff line change
@@ -4395,8 +4395,8 @@ def HLSLControlFlowHint: StmtAttr {
43954395
/// [branch]
43964396
/// [flatten]
43974397
let Spellings = [Microsoft<"branch">, Microsoft<"flatten">];
4398-
let Subjects = SubjectList<[IfStmt],
4399-
ErrorDiag, "'if' statements">;
4398+
let Subjects = SubjectList<[IfStmt, SwitchStmt],
4399+
ErrorDiag, "'if' and 'switch' statements">;
44004400
let LangOpts = [HLSL];
44014401
let Documentation = [InternalOnly];
44024402
}

clang/lib/CodeGen/CGStmt.cpp

+13
Original file line numberDiff line numberDiff line change
@@ -2276,6 +2276,19 @@ void CodeGenFunction::EmitSwitchStmt(const SwitchStmt &S) {
22762276
// failure.
22772277
llvm::BasicBlock *DefaultBlock = createBasicBlock("sw.default");
22782278
SwitchInsn = Builder.CreateSwitch(CondV, DefaultBlock);
2279+
if (HLSLControlFlowAttr != HLSLControlFlowHintAttr::SpellingNotCalculated) {
2280+
llvm::MDBuilder MDHelper(CGM.getLLVMContext());
2281+
llvm::ConstantInt *BranchHintConstant =
2282+
HLSLControlFlowAttr ==
2283+
HLSLControlFlowHintAttr::Spelling::Microsoft_branch
2284+
? llvm::ConstantInt::get(CGM.Int32Ty, 1)
2285+
: llvm::ConstantInt::get(CGM.Int32Ty, 2);
2286+
llvm::Metadata *Vals[] = {MDHelper.createString("hlsl.controlflow.hint"),
2287+
MDHelper.createConstant(BranchHintConstant)};
2288+
SwitchInsn->setMetadata("hlsl.controlflow.hint",
2289+
llvm::MDNode::get(CGM.getLLVMContext(), Vals));
2290+
}
2291+
22792292
if (PGO.haveRegionCounts()) {
22802293
// Walk the SwitchCase list to find how many there are.
22812294
uint64_t DefaultCount = 0;

clang/test/AST/HLSL/HLSLControlFlowHint.hlsl

+59
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,62 @@ export int no_attr(int X){
4141

4242
return resp;
4343
}
44+
45+
// CHECK: FunctionDecl {{.*}} used flatten_switch 'int (int)'
46+
// CHECK: AttributedStmt
47+
// CHECK-NEXT: HLSLControlFlowHintAttr {{.*}} flatten
48+
export int flatten_switch(int X){
49+
int resp;
50+
[flatten]
51+
switch (X) {
52+
case 0:
53+
resp = -X;
54+
break;
55+
case 1:
56+
resp = X+X;
57+
break;
58+
case 2:
59+
resp = X * X; break;
60+
}
61+
62+
return resp;
63+
}
64+
65+
// CHECK: FunctionDecl {{.*}} used branch_switch 'int (int)'
66+
// CHECK: AttributedStmt
67+
// CHECK-NEXT: HLSLControlFlowHintAttr {{.*}} branch
68+
export int branch_switch(int X){
69+
int resp;
70+
[branch]
71+
switch (X) {
72+
case 0:
73+
resp = -X;
74+
break;
75+
case 1:
76+
resp = X+X;
77+
break;
78+
case 2:
79+
resp = X * X; break;
80+
}
81+
82+
return resp;
83+
}
84+
85+
// CHECK: FunctionDecl {{.*}} used no_attr_switch 'int (int)'
86+
// CHECK-NOT: AttributedStmt
87+
// CHECK-NOT: HLSLControlFlowHintAttr
88+
export int no_attr_switch(int X){
89+
int resp;
90+
switch (X) {
91+
case 0:
92+
resp = -X;
93+
break;
94+
case 1:
95+
resp = X+X;
96+
break;
97+
case 2:
98+
resp = X * X; break;
99+
}
100+
101+
return resp;
102+
}

llvm/test/CodeGen/DirectX/HLSLControlFlowHint.ll

+131
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,137 @@ if.end: ; preds = %if.else, %if.then
9191
%3 = load i32, ptr %resp, align 4
9292
ret i32 %3
9393
}
94+
95+
; CHECK: define i32 @flatten_switch(i32 %X)
96+
; CHECK-NOT: hlsl.controlflow.hint
97+
; CHECK: switch i32 %0, label %sw.epilog [
98+
; CHECK-NEXT: i32 0, label %sw.bb
99+
; CHECK-NEXT: i32 1, label %sw.bb1
100+
; CHECK-NEXT: i32 2, label %sw.bb2
101+
; CHECK-NEXT: ], !dx.controlflow.hints [[HINT_FLATTEN]]
102+
define i32 @flatten_switch(i32 %X) #0 {
103+
entry:
104+
%X.addr = alloca i32, align 4
105+
%resp = alloca i32, align 4
106+
store i32 %X, ptr %X.addr, align 4
107+
%0 = load i32, ptr %X.addr, align 4
108+
switch i32 %0, label %sw.epilog [
109+
i32 0, label %sw.bb
110+
i32 1, label %sw.bb1
111+
i32 2, label %sw.bb2
112+
], !hlsl.controlflow.hint !1
113+
114+
sw.bb: ; preds = %entry
115+
%1 = load i32, ptr %X.addr, align 4
116+
%sub = sub nsw i32 0, %1
117+
store i32 %sub, ptr %resp, align 4
118+
br label %sw.epilog
119+
120+
sw.bb1: ; preds = %entry
121+
%2 = load i32, ptr %X.addr, align 4
122+
%3 = load i32, ptr %X.addr, align 4
123+
%add = add nsw i32 %2, %3
124+
store i32 %add, ptr %resp, align 4
125+
br label %sw.epilog
126+
127+
sw.bb2: ; preds = %entry
128+
%4 = load i32, ptr %X.addr, align 4
129+
%5 = load i32, ptr %X.addr, align 4
130+
%mul = mul nsw i32 %4, %5
131+
store i32 %mul, ptr %resp, align 4
132+
br label %sw.epilog
133+
134+
sw.epilog: ; preds = %entry, %sw.bb2, %sw.bb1, %sw.bb
135+
%6 = load i32, ptr %resp, align 4
136+
ret i32 %6
137+
}
138+
139+
140+
; CHECK: define i32 @branch_switch(i32 %X)
141+
; CHECK-NOT: hlsl.controlflow.hint
142+
; CHECK: switch i32 %0, label %sw.epilog [
143+
; CHECK-NEXT: i32 0, label %sw.bb
144+
; CHECK-NEXT: i32 1, label %sw.bb1
145+
; CHECK-NEXT: i32 2, label %sw.bb2
146+
; CHECK-NEXT: ], !dx.controlflow.hints [[HINT_BRANCH]]
147+
define i32 @branch_switch(i32 %X) #0 {
148+
entry:
149+
%X.addr = alloca i32, align 4
150+
%resp = alloca i32, align 4
151+
store i32 %X, ptr %X.addr, align 4
152+
%0 = load i32, ptr %X.addr, align 4
153+
switch i32 %0, label %sw.epilog [
154+
i32 0, label %sw.bb
155+
i32 1, label %sw.bb1
156+
i32 2, label %sw.bb2
157+
], !hlsl.controlflow.hint !0
158+
159+
sw.bb: ; preds = %entry
160+
%1 = load i32, ptr %X.addr, align 4
161+
%sub = sub nsw i32 0, %1
162+
store i32 %sub, ptr %resp, align 4
163+
br label %sw.epilog
164+
165+
sw.bb1: ; preds = %entry
166+
%2 = load i32, ptr %X.addr, align 4
167+
%3 = load i32, ptr %X.addr, align 4
168+
%add = add nsw i32 %2, %3
169+
store i32 %add, ptr %resp, align 4
170+
br label %sw.epilog
171+
172+
sw.bb2: ; preds = %entry
173+
%4 = load i32, ptr %X.addr, align 4
174+
%5 = load i32, ptr %X.addr, align 4
175+
%mul = mul nsw i32 %4, %5
176+
store i32 %mul, ptr %resp, align 4
177+
br label %sw.epilog
178+
179+
sw.epilog: ; preds = %entry, %sw.bb2, %sw.bb1, %sw.bb
180+
%6 = load i32, ptr %resp, align 4
181+
ret i32 %6
182+
}
183+
184+
185+
; CHECK: define i32 @no_attr_switch(i32 %X)
186+
; CHECK-NOT: hlsl.controlflow.hint
187+
; CHECK-NOT: !dx.controlflow.hints
188+
define i32 @no_attr_switch(i32 %X) #0 {
189+
entry:
190+
%X.addr = alloca i32, align 4
191+
%resp = alloca i32, align 4
192+
store i32 %X, ptr %X.addr, align 4
193+
%0 = load i32, ptr %X.addr, align 4
194+
switch i32 %0, label %sw.epilog [
195+
i32 0, label %sw.bb
196+
i32 1, label %sw.bb1
197+
i32 2, label %sw.bb2
198+
]
199+
200+
sw.bb: ; preds = %entry
201+
%1 = load i32, ptr %X.addr, align 4
202+
%sub = sub nsw i32 0, %1
203+
store i32 %sub, ptr %resp, align 4
204+
br label %sw.epilog
205+
206+
sw.bb1: ; preds = %entry
207+
%2 = load i32, ptr %X.addr, align 4
208+
%3 = load i32, ptr %X.addr, align 4
209+
%add = add nsw i32 %2, %3
210+
store i32 %add, ptr %resp, align 4
211+
br label %sw.epilog
212+
213+
sw.bb2: ; preds = %entry
214+
%4 = load i32, ptr %X.addr, align 4
215+
%5 = load i32, ptr %X.addr, align 4
216+
%mul = mul nsw i32 %4, %5
217+
store i32 %mul, ptr %resp, align 4
218+
br label %sw.epilog
219+
220+
sw.epilog: ; preds = %entry, %sw.bb2, %sw.bb1, %sw.bb
221+
%6 = load i32, ptr %resp, align 4
222+
ret i32 %6
223+
}
224+
94225
; CHECK-NOT: hlsl.controlflow.hint
95226
; CHECK: [[HINT_BRANCH]] = !{!"dx.controlflow.hints", i32 1}
96227
; CHECK: [[HINT_FLATTEN]] = !{!"dx.controlflow.hints", i32 2}

llvm/test/CodeGen/SPIRV/structurizer/HLSLControlFlowHint.ll

+122-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
define spir_func noundef i32 @test_branch(i32 noundef %X) {
66
entry:
77
; CHECK-LABEL: ; -- Begin function test_branch
8-
; OpSelectionMerge %[[#]] DontFlatten
8+
; CHECK: OpSelectionMerge %[[#]] DontFlatten
99
%X.addr = alloca i32, align 4
1010
%resp = alloca i32, align 4
1111
store i32 %X, ptr %X.addr, align 4
@@ -34,7 +34,7 @@ if.end: ; preds = %if.else, %if.then
3434
define spir_func noundef i32 @test_flatten(i32 noundef %X) {
3535
entry:
3636
; CHECK-LABEL: ; -- Begin function test_flatten
37-
; OpSelectionMerge %[[#]] Flatten
37+
; CHECK: OpSelectionMerge %[[#]] Flatten
3838
%X.addr = alloca i32, align 4
3939
%resp = alloca i32, align 4
4040
store i32 %X, ptr %X.addr, align 4
@@ -62,7 +62,7 @@ if.end: ; preds = %if.else, %if.then
6262
define spir_func noundef i32 @test_no_attr(i32 noundef %X) {
6363
entry:
6464
; CHECK-LABEL: ; -- Begin function test_no_attr
65-
; OpSelectionMerge %[[#]] None
65+
; CHECK: OpSelectionMerge %[[#]] None
6666
%X.addr = alloca i32, align 4
6767
%resp = alloca i32, align 4
6868
store i32 %X, ptr %X.addr, align 4
@@ -87,5 +87,124 @@ if.end: ; preds = %if.else, %if.then
8787
ret i32 %3
8888
}
8989

90+
define spir_func noundef i32 @flatten_switch(i32 noundef %X) {
91+
entry:
92+
; CHECK-LABEL: ; -- Begin function flatten_switch
93+
; CHECK: OpSelectionMerge %[[#]] Flatten
94+
%X.addr = alloca i32, align 4
95+
%resp = alloca i32, align 4
96+
store i32 %X, ptr %X.addr, align 4
97+
%0 = load i32, ptr %X.addr, align 4
98+
switch i32 %0, label %sw.epilog [
99+
i32 0, label %sw.bb
100+
i32 1, label %sw.bb1
101+
i32 2, label %sw.bb2
102+
], !hlsl.controlflow.hint !1
103+
104+
sw.bb: ; preds = %entry
105+
%1 = load i32, ptr %X.addr, align 4
106+
%sub = sub nsw i32 0, %1
107+
store i32 %sub, ptr %resp, align 4
108+
br label %sw.epilog
109+
110+
sw.bb1: ; preds = %entry
111+
%2 = load i32, ptr %X.addr, align 4
112+
%3 = load i32, ptr %X.addr, align 4
113+
%add = add nsw i32 %2, %3
114+
store i32 %add, ptr %resp, align 4
115+
br label %sw.epilog
116+
117+
sw.bb2: ; preds = %entry
118+
%4 = load i32, ptr %X.addr, align 4
119+
%5 = load i32, ptr %X.addr, align 4
120+
%mul = mul nsw i32 %4, %5
121+
store i32 %mul, ptr %resp, align 4
122+
br label %sw.epilog
123+
124+
sw.epilog: ; preds = %entry, %sw.bb2, %sw.bb1, %sw.bb
125+
%6 = load i32, ptr %resp, align 4
126+
ret i32 %6
127+
}
128+
129+
130+
define spir_func noundef i32 @branch_switch(i32 noundef %X) {
131+
entry:
132+
; CHECK-LABEL: ; -- Begin function branch_switch
133+
; CHECK: OpSelectionMerge %[[#]] DontFlatten
134+
%X.addr = alloca i32, align 4
135+
%resp = alloca i32, align 4
136+
store i32 %X, ptr %X.addr, align 4
137+
%0 = load i32, ptr %X.addr, align 4
138+
switch i32 %0, label %sw.epilog [
139+
i32 0, label %sw.bb
140+
i32 1, label %sw.bb1
141+
i32 2, label %sw.bb2
142+
], !hlsl.controlflow.hint !0
143+
144+
sw.bb: ; preds = %entry
145+
%1 = load i32, ptr %X.addr, align 4
146+
%sub = sub nsw i32 0, %1
147+
store i32 %sub, ptr %resp, align 4
148+
br label %sw.epilog
149+
150+
sw.bb1: ; preds = %entry
151+
%2 = load i32, ptr %X.addr, align 4
152+
%3 = load i32, ptr %X.addr, align 4
153+
%add = add nsw i32 %2, %3
154+
store i32 %add, ptr %resp, align 4
155+
br label %sw.epilog
156+
157+
sw.bb2: ; preds = %entry
158+
%4 = load i32, ptr %X.addr, align 4
159+
%5 = load i32, ptr %X.addr, align 4
160+
%mul = mul nsw i32 %4, %5
161+
store i32 %mul, ptr %resp, align 4
162+
br label %sw.epilog
163+
164+
sw.epilog: ; preds = %entry, %sw.bb2, %sw.bb1, %sw.bb
165+
%6 = load i32, ptr %resp, align 4
166+
ret i32 %6
167+
}
168+
169+
170+
define spir_func noundef i32 @no_attr_switch(i32 noundef %X) {
171+
; CHECK-LABEL: ; -- Begin function no_attr_switch
172+
; CHECK: OpSelectionMerge %[[#]] None
173+
entry:
174+
%X.addr = alloca i32, align 4
175+
%resp = alloca i32, align 4
176+
store i32 %X, ptr %X.addr, align 4
177+
%0 = load i32, ptr %X.addr, align 4
178+
switch i32 %0, label %sw.epilog [
179+
i32 0, label %sw.bb
180+
i32 1, label %sw.bb1
181+
i32 2, label %sw.bb2
182+
]
183+
184+
sw.bb: ; preds = %entry
185+
%1 = load i32, ptr %X.addr, align 4
186+
%sub = sub nsw i32 0, %1
187+
store i32 %sub, ptr %resp, align 4
188+
br label %sw.epilog
189+
190+
sw.bb1: ; preds = %entry
191+
%2 = load i32, ptr %X.addr, align 4
192+
%3 = load i32, ptr %X.addr, align 4
193+
%add = add nsw i32 %2, %3
194+
store i32 %add, ptr %resp, align 4
195+
br label %sw.epilog
196+
197+
sw.bb2: ; preds = %entry
198+
%4 = load i32, ptr %X.addr, align 4
199+
%5 = load i32, ptr %X.addr, align 4
200+
%mul = mul nsw i32 %4, %5
201+
store i32 %mul, ptr %resp, align 4
202+
br label %sw.epilog
203+
204+
sw.epilog: ; preds = %entry, %sw.bb2, %sw.bb1, %sw.bb
205+
%6 = load i32, ptr %resp, align 4
206+
ret i32 %6
207+
}
208+
90209
!0 = !{!"hlsl.controlflow.hint", i32 1}
91210
!1 = !{!"hlsl.controlflow.hint", i32 2}

0 commit comments

Comments
 (0)