-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[HLSL] Adding Flatten and Branch if attributes #116331
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 17 commits
ae71910
cf51a3e
ba1877f
9f9ae58
52370b9
ac487e5
905f80e
4bbb06f
c34a84b
dcf837d
1687f99
083e7ff
af1228a
dbecb17
97a0825
ea16e0e
d1764e1
ac44b3b
8ac48fe
b9d0e31
5e3c99d
fa34c25
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2081,7 +2081,28 @@ void CodeGenFunction::EmitBranchOnBoolExpr( | |
| Weights = createProfileWeights(TrueCount, CurrentCount - TrueCount); | ||
| } | ||
|
|
||
| Builder.CreateCondBr(CondV, TrueBlock, FalseBlock, Weights, Unpredictable); | ||
| auto *BrInst = Builder.CreateCondBr(CondV, TrueBlock, FalseBlock, Weights, | ||
| Unpredictable); | ||
| 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)}); | ||
| BrInst->setMetadata("hlsl.controlflow.hint", | ||
| llvm::MDNode::get(CGM.getLLVMContext(), Vals)); | ||
| } break; | ||
| case HLSLControlFlowHintAttr::SpellingNotCalculated: | ||
|
||
| break; | ||
| } | ||
| } | ||
|
|
||
| /// ErrorUnsupported - Print out an error that codegen doesn't support the | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,43 @@ | ||||||||||
| // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-compute -ast-dump %s | FileCheck %s | ||||||||||
|
|
||||||||||
| // CHECK: FunctionDecl 0x{{[0-9A-Fa-f]+}} <{{.*}}> {{.*}} used branch 'int (int)' | ||||||||||
| // CHECK: AttributedStmt 0x{{[0-9A-Fa-f]+}} <<invalid sloc> | ||||||||||
| // CHECK-NEXT: -HLSLControlFlowHintAttr 0x{{[0-9A-Fa-f]+}} <{{.*}}> branch | ||||||||||
| export int branch(int X){ | ||||||||||
| int resp; | ||||||||||
| [branch] if (X > 0) { | ||||||||||
| resp = -X; | ||||||||||
| } else { | ||||||||||
| resp = X * 2; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| return resp; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| // CHECK: FunctionDecl 0x{{[0-9A-Fa-f]+}} <{{.*}}> {{.*}} used flatten 'int (int)' | ||||||||||
| // CHECK: AttributedStmt 0x{{[0-9A-Fa-f]+}} <<invalid sloc> | ||||||||||
| // CHECK-NEXT: -HLSLControlFlowHintAttr 0x{{[0-9A-Fa-f]+}} <{{.*}}> flatten | ||||||||||
| export int flatten(int X){ | ||||||||||
| int resp; | ||||||||||
| [flatten] if (X > 0) { | ||||||||||
| resp = -X; | ||||||||||
| } else { | ||||||||||
| resp = X * 2; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| return resp; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| // CHECK: FunctionDecl 0x{{[0-9A-Fa-f]+}} <{{.*}}> {{.*}} used no_attr 'int (int)' | ||||||||||
| // CHECK-NO: AttributedStmt 0x{{[0-9A-Fa-f]+}} <<invalid sloc> | ||||||||||
| // CHECK-NO: -HLSLControlFlowHintAttr | ||||||||||
|
||||||||||
| // CHECK-NO: AttributedStmt 0x{{[0-9A-Fa-f]+}} <<invalid sloc> | |
| // CHECK-NO: -HLSLControlFlowHintAttr | |
| // CHECK-NOT: AttributedStmt 0x{{[0-9A-Fa-f]+}} <<invalid sloc> | |
| // CHECK-NOT: -HLSLControlFlowHintAttr |
This test isn't testing what you think it is... 😄
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,48 @@ | ||||||
| // RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s -fnative-half-type -emit-llvm -o - | FileCheck %s | ||||||
| // RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-vulkan-library %s -fnative-half-type -emit-llvm -o - | FileCheck %s | ||||||
|
|
||||||
| // CHECK: define {{.*}} i32 {{.*}}test_branch{{.*}}(i32 {{.*}} [[VALD:%.*]]) | ||||||
| // CHECK: [[PARAM:%.*]] = load i32, ptr [[VALD]].addr, align 4 | ||||||
| // CHECK: [[CMP:%.*]] = icmp sgt i32 [[PARAM]], 0 | ||||||
| // CHECK: br i1 [[CMP]], label %if.then, label %if.else, !hlsl.controlflow.hint [[HINT_BRANCH:![0-9]+]] | ||||||
| export int test_branch(int X){ | ||||||
| int resp; | ||||||
| [branch] if (X > 0) { | ||||||
| resp = -X; | ||||||
| } else { | ||||||
| resp = X * 2; | ||||||
| } | ||||||
|
|
||||||
| return resp; | ||||||
| } | ||||||
|
|
||||||
| // CHECK: define {{.*}} i32 {{.*}}test_flatten{{.*}}(i32 {{.*}} [[VALD:%.*]]) | ||||||
| // CHECK: [[PARAM:%.*]] = load i32, ptr [[VALD]].addr, align 4 | ||||||
| // CHECK: [[CMP:%.*]] = icmp sgt i32 [[PARAM]], 0 | ||||||
| // CHECK: br i1 [[CMP]], label %if.then, label %if.else, !hlsl.controlflow.hint [[HINT_FLATTEN:![0-9]+]] | ||||||
| export int test_flatten(int X){ | ||||||
| int resp; | ||||||
| [flatten] if (X > 0) { | ||||||
| resp = -X; | ||||||
| } else { | ||||||
| resp = X * 2; | ||||||
| } | ||||||
|
|
||||||
| return resp; | ||||||
| } | ||||||
|
|
||||||
| // CHECK: define {{.*}} i32 {{.*}}test_no_attr{{.*}}(i32 {{.*}} [[VALD:%.*]]) | ||||||
| // CHECK-NO: !hlsl.controlflow.hint | ||||||
|
||||||
| // CHECK-NO: !hlsl.controlflow.hint | |
| // CHECK-NOT: !hlsl.controlflow.hint |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -21,6 +21,7 @@ | |||||||||||||||||||||||||
| #include "llvm/IR/Function.h" | ||||||||||||||||||||||||||
| #include "llvm/IR/IRBuilder.h" | ||||||||||||||||||||||||||
| #include "llvm/IR/LLVMContext.h" | ||||||||||||||||||||||||||
| #include "llvm/IR/MDBuilder.h" | ||||||||||||||||||||||||||
| #include "llvm/IR/Metadata.h" | ||||||||||||||||||||||||||
| #include "llvm/IR/Module.h" | ||||||||||||||||||||||||||
| #include "llvm/InitializePasses.h" | ||||||||||||||||||||||||||
|
|
@@ -295,6 +296,39 @@ static MDTuple *emitTopLevelLibraryNode(Module &M, MDNode *RMD, | |||||||||||||||||||||||||
| return constructEntryMetadata(nullptr, nullptr, RMD, Properties, Ctx); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| // TODO: We might need to refactor this to be more generic, | ||||||||||||||||||||||||||
| // in case we need more metadata to be replaced. | ||||||||||||||||||||||||||
| static void translateBranchMetadata(Module &M) { | ||||||||||||||||||||||||||
| for (auto &F : M) { | ||||||||||||||||||||||||||
| for (auto &BB : F) { | ||||||||||||||||||||||||||
| auto *BBTerminatorInst = BB.getTerminator(); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| auto *HlslControlFlowMD = | ||||||||||||||||||||||||||
| BBTerminatorInst->getMetadata("hlsl.controlflow.hint"); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
| for (auto &F : M) { | |
| for (auto &BB : F) { | |
| auto *BBTerminatorInst = BB.getTerminator(); | |
| auto *HlslControlFlowMD = | |
| BBTerminatorInst->getMetadata("hlsl.controlflow.hint"); | |
| for (Function &F : M) { | |
| for (BasicBlock &BB : F) { | |
| Inst *BBTerminatorInst = BB.getTerminator(); | |
| MDNode *HlslControlFlowMD = | |
| BBTerminatorInst->getMetadata("hlsl.controlflow.hint"); |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2776,19 +2776,35 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return MIB.constrainAllUses(TII, TRI, RBI); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case Intrinsic::spv_loop_merge: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case Intrinsic::spv_selection_merge: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const auto Opcode = IID == Intrinsic::spv_selection_merge | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ? SPIRV::OpSelectionMerge | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| : SPIRV::OpLoopMerge; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(Opcode)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case Intrinsic::spv_loop_merge: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpLoopMerge)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for (unsigned i = 1; i < I.getNumExplicitOperands(); ++i) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert(I.getOperand(i).isMBB()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MIB.addMBB(I.getOperand(i).getMBB()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MIB.addImm(SPIRV::SelectionControl::None); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return MIB.constrainAllUses(TII, TRI, RBI); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case Intrinsic::spv_selection_merge: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| int64_t SelectionControl = SPIRV::SelectionControl::None; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| auto LastOp = I.getOperand(I.getNumOperands() - 1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| auto BranchHint = LastOp.getImm(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (BranchHint == 2) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SelectionControl = SPIRV::SelectionControl::Flatten; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else if (BranchHint == 1) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SelectionControl = SPIRV::SelectionControl::DontFlatten; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| auto MIB = | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpSelectionMerge)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for (unsigned i = 1; i < I.getNumExplicitOperands() - 1; ++i) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert(I.getOperand(i).isMBB()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MIB.addMBB(I.getOperand(i).getMBB()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MIB.addImm(SelectionControl); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return MIB.constrainAllUses(TII, TRI, RBI); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do you need to loop through the operands given the instruction is not variadic?
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case Intrinsic::spv_cmpxchg: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return selectAtomicCmpXchg(ResVReg, ResType, I); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case Intrinsic::spv_unreachable: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: https://llvm.org/docs/CodingStandards.html#use-auto-type-deduction-to-make-code-more-readable