[clang] [llvm] [HLSL] Adding Flatten and Branch if attributes (PR #116331)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Nov 15 11:38:02 PST 2024
https://github.com/joaosaffran updated https://github.com/llvm/llvm-project/pull/116331
>From 3c792216f88e87b69b3ea7415c2fd74b7f5d7469 Mon Sep 17 00:00:00 2001
From: Joao Saffran <jderezende at microsoft.com>
Date: Fri, 25 Oct 2024 17:48:41 +0000
Subject: [PATCH 1/7] adding comments
---
clang/include/clang/Basic/Attr.td | 10 ++++++++++
clang/lib/CodeGen/CGStmt.cpp | 2 ++
clang/lib/CodeGen/CodeGenFunction.cpp | 2 ++
clang/lib/Sema/SemaStmtAttr.cpp | 8 ++++++++
4 files changed, 22 insertions(+)
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index b3c357ec906a23..6d3e07ce83100b 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4302,6 +4302,16 @@ def HLSLLoopHint: StmtAttr {
let Documentation = [HLSLLoopHintDocs, HLSLUnrollHintDocs];
}
+def HLSLBranchHint: StmtAttr {
+ /// [branch]
+ /// [flatten]
+ let Spellings = [Microsoft<"branch">, Microsoft<"flatten">];
+ let Subjects = SubjectList<[IfStmt],
+ ErrorDiag, "'if' statements">;
+ let LangOpts = [HLSL];
+ let Documentation = [InternalOnly];
+}
+
def CapturedRecord : InheritableAttr {
// This attribute has no spellings as it is only ever created implicitly.
let Spellings = [];
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index 698baf853507f4..7b01dc84b55365 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -761,6 +761,7 @@ void CodeGenFunction::EmitAttributedStmt(const AttributedStmt &S) {
Builder.CreateAssumption(AssumptionVal);
}
} break;
+ // [jderezende] TODO: Add HLSLBranchHint, to mark if flatten/branch is present.
}
}
SaveAndRestore save_nomerge(InNoMergeAttributedStmt, nomerge);
@@ -768,6 +769,7 @@ void CodeGenFunction::EmitAttributedStmt(const AttributedStmt &S) {
SaveAndRestore save_alwaysinline(InAlwaysInlineAttributedStmt, alwaysinline);
SaveAndRestore save_noconvergent(InNoConvergentAttributedStmt, noconvergent);
SaveAndRestore save_musttail(MustTailCall, musttail);
+ // [jderezende] TODO: Save HLSLBranchHint information
EmitStmt(S.getSubStmt(), S.getAttrs());
}
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 6ead45793742d6..fc4fde81984d64 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -43,6 +43,7 @@
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/MDBuilder.h"
+#include "llvm/IR/Metadata.h"
#include "llvm/IR/Operator.h"
#include "llvm/Support/CRC.h"
#include "llvm/Support/xxhash.h"
@@ -2076,6 +2077,7 @@ void CodeGenFunction::EmitBranchOnBoolExpr(
Weights = createProfileWeights(TrueCount, CurrentCount - TrueCount);
}
+ // [jderezende] TODO: Emit branch metadata marking it as flatten/branch, if exists.
Builder.CreateCondBr(CondV, TrueBlock, FalseBlock, Weights, Unpredictable);
}
diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index f801455596fe6f..68323092cb564d 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -623,6 +623,12 @@ static Attr *handleHLSLLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A,
return ::new (S.Context) HLSLLoopHintAttr(S.Context, A, UnrollFactor);
}
+static Attr *handleHLSLBranchHint(Sema &S, Stmt *St, const ParsedAttr &A,
+ SourceRange Range) {
+
+ return ::new (S.Context) HLSLBranchHintAttr(S.Context, A);
+}
+
static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A,
SourceRange Range) {
if (A.isInvalid() || A.getKind() == ParsedAttr::IgnoredAttribute)
@@ -659,6 +665,8 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A,
return handleLoopHintAttr(S, St, A, Range);
case ParsedAttr::AT_HLSLLoopHint:
return handleHLSLLoopHintAttr(S, St, A, Range);
+ case ParsedAttr::AT_HLSLBranchHint:
+ return handleHLSLBranchHint(S, St, A, Range);
case ParsedAttr::AT_OpenCLUnrollHint:
return handleOpenCLUnrollHint(S, St, A, Range);
case ParsedAttr::AT_Suppress:
>From f48e382b7ff396fbf1b2ce7dcea9529a06fa9b12 Mon Sep 17 00:00:00 2001
From: Joao Saffran <jderezende at microsoft.com>
Date: Mon, 28 Oct 2024 23:58:10 +0000
Subject: [PATCH 2/7] continue exploration
---
llvm/include/llvm/IR/FixedMetadataKinds.def | 3 +++
llvm/lib/Target/SPIRV/SPIRVStructurizer.cpp | 1 +
2 files changed, 4 insertions(+)
diff --git a/llvm/include/llvm/IR/FixedMetadataKinds.def b/llvm/include/llvm/IR/FixedMetadataKinds.def
index df572e8791e13b..02a986d42f1933 100644
--- a/llvm/include/llvm/IR/FixedMetadataKinds.def
+++ b/llvm/include/llvm/IR/FixedMetadataKinds.def
@@ -53,3 +53,6 @@ LLVM_FIXED_MD_KIND(MD_DIAssignID, "DIAssignID", 38)
LLVM_FIXED_MD_KIND(MD_coro_outside_frame, "coro.outside.frame", 39)
LLVM_FIXED_MD_KIND(MD_mmra, "mmra", 40)
LLVM_FIXED_MD_KIND(MD_noalias_addrspace, "noalias.addrspace", 41)
+// [jderezende] TODO: this will likelly be placed somewhere else,
+// so we don't mix dxil/hlsl/spirv and clang metadata
+LLVM_FIXED_MD_KIND(MD_dxil_controlflow_hints, "dx.controlflow.hints", 42)
diff --git a/llvm/lib/Target/SPIRV/SPIRVStructurizer.cpp b/llvm/lib/Target/SPIRV/SPIRVStructurizer.cpp
index 13e05b67927518..bff8cc1cfc5821 100644
--- a/llvm/lib/Target/SPIRV/SPIRVStructurizer.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVStructurizer.cpp
@@ -645,6 +645,7 @@ class SPIRVStructurizer : public FunctionPass {
auto MergeAddress = BlockAddress::get(BB.getParent(), &BB);
SmallVector<Value *, 1> Args = {MergeAddress};
+ // [jderezende] TODO: Pass metadata from Header->getTerminator() to modify the intrinsic
Builder.CreateIntrinsic(Intrinsic::spv_selection_merge, {}, {Args});
Modified = true;
>From feb9d2dfc020e27a69637774f896d16f74e20625 Mon Sep 17 00:00:00 2001
From: Joao Saffran <jderezende at microsoft.com>
Date: Thu, 14 Nov 2024 02:13:12 +0000
Subject: [PATCH 3/7] adding attribute lowering
---
clang/lib/CodeGen/CGStmt.cpp | 10 ++++--
clang/lib/CodeGen/CodeGenFunction.cpp | 15 +++++++-
clang/lib/CodeGen/CodeGenFunction.h | 7 ++++
clang/lib/CodeGen/CodeGenPGO.cpp | 17 ++++++++++
llvm/include/llvm/IR/IRBuilder.h | 11 ++++--
llvm/include/llvm/IR/IntrinsicsSPIRV.td | 2 +-
llvm/include/llvm/IR/ProfDataUtils.h | 7 ++++
llvm/lib/IR/ProfDataUtils.cpp | 7 ++++
.../Target/SPIRV/SPIRVInstructionSelector.cpp | 34 +++++++++++++++----
llvm/lib/Target/SPIRV/SPIRVMetadata.cpp | 2 +-
llvm/lib/Target/SPIRV/SPIRVStructurizer.cpp | 14 ++++++--
11 files changed, 109 insertions(+), 17 deletions(-)
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index 7b01dc84b55365..2f95ceb297f7d8 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -16,6 +16,7 @@
#include "CodeGenModule.h"
#include "TargetInfo.h"
#include "clang/AST/Attr.h"
+#include "clang/AST/Attrs.inc"
#include "clang/AST/Expr.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/StmtVisitor.h"
@@ -730,6 +731,8 @@ void CodeGenFunction::EmitAttributedStmt(const AttributedStmt &S) {
bool noinline = false;
bool alwaysinline = false;
bool noconvergent = false;
+ HLSLBranchHintAttr::Spelling flattenOrBranch =
+ HLSLBranchHintAttr::SpellingNotCalculated;
const CallExpr *musttail = nullptr;
for (const auto *A : S.getAttrs()) {
@@ -761,7 +764,9 @@ void CodeGenFunction::EmitAttributedStmt(const AttributedStmt &S) {
Builder.CreateAssumption(AssumptionVal);
}
} break;
- // [jderezende] TODO: Add HLSLBranchHint, to mark if flatten/branch is present.
+ case attr::HLSLBranchHint: {
+ flattenOrBranch = cast<HLSLBranchHintAttr>(A)->getSemanticSpelling();
+ } break;
}
}
SaveAndRestore save_nomerge(InNoMergeAttributedStmt, nomerge);
@@ -769,7 +774,8 @@ void CodeGenFunction::EmitAttributedStmt(const AttributedStmt &S) {
SaveAndRestore save_alwaysinline(InAlwaysInlineAttributedStmt, alwaysinline);
SaveAndRestore save_noconvergent(InNoConvergentAttributedStmt, noconvergent);
SaveAndRestore save_musttail(MustTailCall, musttail);
- // [jderezende] TODO: Save HLSLBranchHint information
+ SaveAndRestore save_flattenOrBranch(HLSLBranchHintAttributedSpelling,
+ flattenOrBranch);
EmitStmt(S.getSubStmt(), S.getAttrs());
}
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index fc4fde81984d64..a799e017f46c5e 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -24,6 +24,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTLambda.h"
#include "clang/AST/Attr.h"
+#include "clang/AST/Attrs.inc"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
@@ -2053,6 +2054,7 @@ void CodeGenFunction::EmitBranchOnBoolExpr(
llvm::MDNode *Weights = nullptr;
llvm::MDNode *Unpredictable = nullptr;
+ llvm::MDNode *ControlFlowHint = nullptr;
// If the branch has a condition wrapped by __builtin_unpredictable,
// create metadata that specifies that the branch is unpredictable.
@@ -2077,8 +2079,19 @@ void CodeGenFunction::EmitBranchOnBoolExpr(
Weights = createProfileWeights(TrueCount, CurrentCount - TrueCount);
}
+ switch (HLSLBranchHintAttributedSpelling) {
+
+ case HLSLBranchHintAttr::Microsoft_branch:
+ case HLSLBranchHintAttr::Microsoft_flatten:
+ ControlFlowHint = createControlFlowHint(HLSLBranchHintAttributedSpelling);
+ break;
+ case HLSLBranchHintAttr::SpellingNotCalculated:
+ break;
+ }
+
// [jderezende] TODO: Emit branch metadata marking it as flatten/branch, if exists.
- Builder.CreateCondBr(CondV, TrueBlock, FalseBlock, Weights, Unpredictable);
+ Builder.CreateCondBr(CondV, TrueBlock, FalseBlock, Weights, Unpredictable,
+ ControlFlowHint);
}
/// ErrorUnsupported - Print out an error that codegen doesn't support the
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index fcc1013d7361ec..f1001dc21e5e5d 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -21,6 +21,7 @@
#include "CodeGenPGO.h"
#include "EHScopeStack.h"
#include "VarBypassDetector.h"
+#include "clang/AST/Attrs.inc"
#include "clang/AST/CharUnits.h"
#include "clang/AST/CurrentSourceLocExprScope.h"
#include "clang/AST/ExprCXX.h"
@@ -615,6 +616,10 @@ class CodeGenFunction : public CodeGenTypeCache {
/// True if the current statement has noconvergent attribute.
bool InNoConvergentAttributedStmt = false;
+ /// HLSL Branch attribute.
+ HLSLBranchHintAttr::Spelling HLSLBranchHintAttributedSpelling =
+ HLSLBranchHintAttr::SpellingNotCalculated;
+
// The CallExpr within the current statement that the musttail attribute
// applies to. nullptr if there is no 'musttail' on the current statement.
const CallExpr *MustTailCall = nullptr;
@@ -1612,6 +1617,8 @@ class CodeGenFunction : public CodeGenTypeCache {
/// Bitmap used by MC/DC to track condition outcomes of a boolean expression.
Address MCDCCondBitmapAddr = Address::invalid();
+ llvm::MDNode *createControlFlowHint(HLSLBranchHintAttr::Spelling S) const;
+
/// Calculate branch weights appropriate for PGO data
llvm::MDNode *createProfileWeights(uint64_t TrueCount,
uint64_t FalseCount) const;
diff --git a/clang/lib/CodeGen/CodeGenPGO.cpp b/clang/lib/CodeGen/CodeGenPGO.cpp
index 820bb521ccf850..d8d72f91f28708 100644
--- a/clang/lib/CodeGen/CodeGenPGO.cpp
+++ b/clang/lib/CodeGen/CodeGenPGO.cpp
@@ -13,10 +13,14 @@
#include "CodeGenPGO.h"
#include "CodeGenFunction.h"
#include "CoverageMappingGen.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Attrs.inc"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/StmtVisitor.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/MDBuilder.h"
+#include "llvm/IR/Metadata.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/FileSystem.h"
@@ -1451,6 +1455,19 @@ static uint32_t scaleBranchWeight(uint64_t Weight, uint64_t Scale) {
return Scaled;
}
+llvm::MDNode *
+CodeGenFunction::createControlFlowHint(HLSLBranchHintAttr::Spelling S) const {
+ llvm::MDBuilder MDHelper(CGM.getLLVMContext());
+
+ SmallVector<llvm::Metadata *, 2> Vals(llvm::ArrayRef<llvm::Metadata *>{
+ MDHelper.createString("dx.controlflow.hints"),
+ S == HLSLBranchHintAttr::Spelling::Microsoft_branch
+ ? MDHelper.createConstant(llvm::ConstantInt::get(Int32Ty, 1))
+ : MDHelper.createConstant(llvm::ConstantInt::get(Int32Ty, 2))});
+
+ return llvm::MDNode::get(CGM.getLLVMContext(), Vals);
+}
+
llvm::MDNode *CodeGenFunction::createProfileWeights(uint64_t TrueCount,
uint64_t FalseCount) const {
// Check for empty weights.
diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h
index 23fd8350a29b3d..215d3362bd4f6c 100644
--- a/llvm/include/llvm/IR/IRBuilder.h
+++ b/llvm/include/llvm/IR/IRBuilder.h
@@ -1101,11 +1101,14 @@ class IRBuilderBase {
/// instruction.
/// \returns The annotated instruction.
template <typename InstTy>
- InstTy *addBranchMetadata(InstTy *I, MDNode *Weights, MDNode *Unpredictable) {
+ InstTy *addBranchMetadata(InstTy *I, MDNode *Weights, MDNode *Unpredictable,
+ MDNode *ControlFlowHint = nullptr) {
if (Weights)
I->setMetadata(LLVMContext::MD_prof, Weights);
if (Unpredictable)
I->setMetadata(LLVMContext::MD_unpredictable, Unpredictable);
+ if (ControlFlowHint)
+ I->setMetadata(LLVMContext::MD_dxil_controlflow_hints, ControlFlowHint);
return I;
}
@@ -1143,9 +1146,11 @@ class IRBuilderBase {
/// instruction.
BranchInst *CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False,
MDNode *BranchWeights = nullptr,
- MDNode *Unpredictable = nullptr) {
+ MDNode *Unpredictable = nullptr,
+ MDNode *ControlFlowHint = nullptr) {
return Insert(addBranchMetadata(BranchInst::Create(True, False, Cond),
- BranchWeights, Unpredictable));
+ BranchWeights, Unpredictable,
+ ControlFlowHint));
}
/// Create a conditional 'br Cond, TrueDest, FalseDest'
diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
index f29eb7ee22b2d2..4a5f744c74d9be 100644
--- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td
+++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
@@ -33,7 +33,7 @@ let TargetPrefix = "spv" in {
def int_spv_ptrcast : Intrinsic<[llvm_any_ty], [llvm_any_ty, llvm_metadata_ty, llvm_i32_ty], [ImmArg<ArgIndex<2>>]>;
def int_spv_switch : Intrinsic<[], [llvm_any_ty, llvm_vararg_ty]>;
def int_spv_loop_merge : Intrinsic<[], [llvm_vararg_ty]>;
- def int_spv_selection_merge : Intrinsic<[], [llvm_vararg_ty]>;
+ def int_spv_selection_merge : Intrinsic<[], [llvm_metadata_ty, llvm_vararg_ty]>;
def int_spv_cmpxchg : Intrinsic<[llvm_i32_ty], [llvm_any_ty, llvm_vararg_ty]>;
def int_spv_unreachable : Intrinsic<[], []>;
def int_spv_alloca : Intrinsic<[llvm_any_ty], []>;
diff --git a/llvm/include/llvm/IR/ProfDataUtils.h b/llvm/include/llvm/IR/ProfDataUtils.h
index 0bea517df832e3..49f7da480f928d 100644
--- a/llvm/include/llvm/IR/ProfDataUtils.h
+++ b/llvm/include/llvm/IR/ProfDataUtils.h
@@ -48,6 +48,13 @@ bool hasValidBranchWeightMD(const Instruction &I);
/// Nullptr otherwise.
MDNode *getBranchWeightMDNode(const Instruction &I);
+/// Get the branching metadata information
+///
+/// \param I The Instruction to get the weights from.
+/// \returns A pointer to I's branch weights metadata node, if it exists.
+/// Nullptr otherwise.
+MDNode *getDxBranchHint(const Instruction &I);
+
/// Get the valid branch weights metadata node
///
/// \param I The Instruction to get the weights from.
diff --git a/llvm/lib/IR/ProfDataUtils.cpp b/llvm/lib/IR/ProfDataUtils.cpp
index 5441228b3291ee..47a5059017a48f 100644
--- a/llvm/lib/IR/ProfDataUtils.cpp
+++ b/llvm/lib/IR/ProfDataUtils.cpp
@@ -150,6 +150,13 @@ MDNode *getBranchWeightMDNode(const Instruction &I) {
return ProfileData;
}
+MDNode *getDxBranchHint(const Instruction &I) {
+ MDNode *Node = I.getMetadata(LLVMContext::MD_dxil_controlflow_hints);
+ if (!isTargetMD(Node, "dx.controlflow.hints", 2))
+ return nullptr;
+ return Node;
+}
+
MDNode *getValidBranchWeightMDNode(const Instruction &I) {
auto *ProfileData = getBranchWeightMDNode(I);
if (ProfileData && getNumBranchWeights(*ProfileData) == I.getNumSuccessors())
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index 8a8835e0269200..f3f78fb4f2bdbb 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -32,6 +32,7 @@
#include "llvm/CodeGen/Register.h"
#include "llvm/CodeGen/TargetOpcodes.h"
#include "llvm/IR/IntrinsicsSPIRV.h"
+#include "llvm/IR/Metadata.h"
#include "llvm/Support/Debug.h"
#define DEBUG_TYPE "spirv-isel"
@@ -2694,12 +2695,8 @@ 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());
@@ -2707,6 +2704,31 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
MIB.addImm(SPIRV::SelectionControl::None);
return MIB.constrainAllUses(TII, TRI, RBI);
}
+ case Intrinsic::spv_selection_merge: {
+
+ auto SelectionControl = SPIRV::SelectionControl::None;
+ const MDNode *MDOp = I.getOperand(1).getMetadata();
+ if (MDOp->getNumOperands() > 0) {
+ ConstantInt *BranchHint =
+ mdconst::extract<ConstantInt>(MDOp->getOperand(1));
+
+ if (BranchHint->equalsInt(2))
+ SelectionControl = SPIRV::SelectionControl::Flatten;
+ else if (BranchHint->equalsInt(1))
+ SelectionControl = SPIRV::SelectionControl::DontFlatten;
+ else
+ llvm_unreachable("Invalid value for SelectionControl");
+ }
+
+ auto MIB =
+ BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpSelectionMerge));
+ for (unsigned i = 2; i < I.getNumExplicitOperands(); ++i) {
+ assert(I.getOperand(i).isMBB());
+ MIB.addMBB(I.getOperand(i).getMBB());
+ }
+ MIB.addImm(SelectionControl);
+ return MIB.constrainAllUses(TII, TRI, RBI);
+ }
case Intrinsic::spv_cmpxchg:
return selectAtomicCmpXchg(ResVReg, ResType, I);
case Intrinsic::spv_unreachable:
diff --git a/llvm/lib/Target/SPIRV/SPIRVMetadata.cpp b/llvm/lib/Target/SPIRV/SPIRVMetadata.cpp
index 3800aac70df327..7d5617919df87c 100644
--- a/llvm/lib/Target/SPIRV/SPIRVMetadata.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVMetadata.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "SPIRVMetadata.h"
+#include "llvm/IR/Metadata.h"
using namespace llvm;
@@ -81,5 +82,4 @@ MDString *getOCLKernelArgTypeQual(const Function &F, unsigned ArgIdx) {
"Kernel attributes are attached/belong only to OpenCL kernel functions");
return getOCLKernelArgAttribute(F, ArgIdx, "kernel_arg_type_qual");
}
-
} // namespace llvm
diff --git a/llvm/lib/Target/SPIRV/SPIRVStructurizer.cpp b/llvm/lib/Target/SPIRV/SPIRVStructurizer.cpp
index bff8cc1cfc5821..6fed0b81bf61e7 100644
--- a/llvm/lib/Target/SPIRV/SPIRVStructurizer.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVStructurizer.cpp
@@ -13,6 +13,7 @@
#include "SPIRVSubtarget.h"
#include "SPIRVTargetMachine.h"
#include "SPIRVUtils.h"
+#include "llvm-c/Core.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Analysis/LoopInfo.h"
@@ -23,6 +24,8 @@
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/IntrinsicsSPIRV.h"
+#include "llvm/IR/Metadata.h"
+#include "llvm/IR/ProfDataUtils.h"
#include "llvm/InitializePasses.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/LoopSimplify.h"
@@ -95,7 +98,7 @@ BasicBlock *getDesignatedMergeBlock(Instruction *I) {
II->getIntrinsicID() != Intrinsic::spv_selection_merge)
return nullptr;
- BlockAddress *BA = cast<BlockAddress>(II->getOperand(0));
+ BlockAddress *BA = cast<BlockAddress>(II->getOperand(1));
return BA->getBasicBlock();
}
@@ -644,8 +647,13 @@ class SPIRVStructurizer : public FunctionPass {
Builder.SetInsertPoint(Header->getTerminator());
auto MergeAddress = BlockAddress::get(BB.getParent(), &BB);
- SmallVector<Value *, 1> Args = {MergeAddress};
- // [jderezende] TODO: Pass metadata from Header->getTerminator() to modify the intrinsic
+
+ MDNode *BranchMdNode = getDxBranchHint(*Header->getTerminator());
+ Value *MDNodeValue =
+ MetadataAsValue::get(Builder.getContext(), BranchMdNode);
+
+ SmallVector<Value *, 2> Args = {MDNodeValue, MergeAddress};
+
Builder.CreateIntrinsic(Intrinsic::spv_selection_merge, {}, {Args});
Modified = true;
>From 9beb5f17bfefcea148c1954b1b7bd458c4372389 Mon Sep 17 00:00:00 2001
From: Joao Saffran <jderezende at microsoft.com>
Date: Fri, 15 Nov 2024 00:08:26 +0000
Subject: [PATCH 4/7] adding tests
---
clang/lib/CodeGen/CGStmt.cpp | 1 -
clang/lib/CodeGen/CodeGenFunction.cpp | 3 -
clang/lib/CodeGen/CodeGenFunction.h | 1 -
clang/lib/CodeGen/CodeGenPGO.cpp | 4 -
clang/test/AST/HLSL/HLSLBranchHint.hlsl | 43 +++++++++
clang/test/CodeGenHLSL/HLSLBranchHint.hlsl | 48 ++++++++++
llvm/include/llvm/IR/FixedMetadataKinds.def | 2 +-
.../Target/SPIRV/SPIRVInstructionSelector.cpp | 1 -
llvm/lib/Target/SPIRV/SPIRVMetadata.cpp | 2 +-
llvm/test/CodeGen/DirectX/HLSLBranchHint.ll | 95 +++++++++++++++++++
llvm/test/CodeGen/SPIRV/HLSLBranchHint.ll | 91 ++++++++++++++++++
11 files changed, 279 insertions(+), 12 deletions(-)
create mode 100644 clang/test/AST/HLSL/HLSLBranchHint.hlsl
create mode 100644 clang/test/CodeGenHLSL/HLSLBranchHint.hlsl
create mode 100644 llvm/test/CodeGen/DirectX/HLSLBranchHint.ll
create mode 100644 llvm/test/CodeGen/SPIRV/HLSLBranchHint.ll
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index 2f95ceb297f7d8..bf82e50c8b59e0 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -16,7 +16,6 @@
#include "CodeGenModule.h"
#include "TargetInfo.h"
#include "clang/AST/Attr.h"
-#include "clang/AST/Attrs.inc"
#include "clang/AST/Expr.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/StmtVisitor.h"
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index a799e017f46c5e..a790d1fde0e104 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -24,7 +24,6 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTLambda.h"
#include "clang/AST/Attr.h"
-#include "clang/AST/Attrs.inc"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
@@ -44,7 +43,6 @@
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/MDBuilder.h"
-#include "llvm/IR/Metadata.h"
#include "llvm/IR/Operator.h"
#include "llvm/Support/CRC.h"
#include "llvm/Support/xxhash.h"
@@ -2089,7 +2087,6 @@ void CodeGenFunction::EmitBranchOnBoolExpr(
break;
}
- // [jderezende] TODO: Emit branch metadata marking it as flatten/branch, if exists.
Builder.CreateCondBr(CondV, TrueBlock, FalseBlock, Weights, Unpredictable,
ControlFlowHint);
}
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index f1001dc21e5e5d..d3f1af6f5a5ce9 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -21,7 +21,6 @@
#include "CodeGenPGO.h"
#include "EHScopeStack.h"
#include "VarBypassDetector.h"
-#include "clang/AST/Attrs.inc"
#include "clang/AST/CharUnits.h"
#include "clang/AST/CurrentSourceLocExprScope.h"
#include "clang/AST/ExprCXX.h"
diff --git a/clang/lib/CodeGen/CodeGenPGO.cpp b/clang/lib/CodeGen/CodeGenPGO.cpp
index d8d72f91f28708..ff3826ca6da854 100644
--- a/clang/lib/CodeGen/CodeGenPGO.cpp
+++ b/clang/lib/CodeGen/CodeGenPGO.cpp
@@ -13,14 +13,10 @@
#include "CodeGenPGO.h"
#include "CodeGenFunction.h"
#include "CoverageMappingGen.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Attrs.inc"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/StmtVisitor.h"
-#include "llvm/ADT/ArrayRef.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/MDBuilder.h"
-#include "llvm/IR/Metadata.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/FileSystem.h"
diff --git a/clang/test/AST/HLSL/HLSLBranchHint.hlsl b/clang/test/AST/HLSL/HLSLBranchHint.hlsl
new file mode 100644
index 00000000000000..907d6c5ff580c0
--- /dev/null
+++ b/clang/test/AST/HLSL/HLSLBranchHint.hlsl
@@ -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: HLSLBranchHintAttr 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: HLSLBranchHintAttr 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: HLSLBranchHintAttr
+export int no_attr(int X){
+ int resp;
+ if (X > 0) {
+ resp = -X;
+ } else {
+ resp = X * 2;
+ }
+
+ return resp;
+}
diff --git a/clang/test/CodeGenHLSL/HLSLBranchHint.hlsl b/clang/test/CodeGenHLSL/HLSLBranchHint.hlsl
new file mode 100644
index 00000000000000..11b14b1ec43175
--- /dev/null
+++ b/clang/test/CodeGenHLSL/HLSLBranchHint.hlsl
@@ -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, !dx.controlflow.hints [[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, !dx.controlflow.hints [[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: !dx.controlflow.hints
+export int test_no_attr(int X){
+ int resp;
+ if (X > 0) {
+ resp = -X;
+ } else {
+ resp = X * 2;
+ }
+
+ return resp;
+}
+
+//CHECK: [[HINT_BRANCH]] = !{!"dx.controlflow.hints", i32 1}
+//CHECK: [[HINT_FLATTEN]] = !{!"dx.controlflow.hints", i32 2}
diff --git a/llvm/include/llvm/IR/FixedMetadataKinds.def b/llvm/include/llvm/IR/FixedMetadataKinds.def
index 02a986d42f1933..a239a076d131f7 100644
--- a/llvm/include/llvm/IR/FixedMetadataKinds.def
+++ b/llvm/include/llvm/IR/FixedMetadataKinds.def
@@ -53,6 +53,6 @@ LLVM_FIXED_MD_KIND(MD_DIAssignID, "DIAssignID", 38)
LLVM_FIXED_MD_KIND(MD_coro_outside_frame, "coro.outside.frame", 39)
LLVM_FIXED_MD_KIND(MD_mmra, "mmra", 40)
LLVM_FIXED_MD_KIND(MD_noalias_addrspace, "noalias.addrspace", 41)
-// [jderezende] TODO: this will likelly be placed somewhere else,
+// TODO: this will likelly be placed somewhere else,
// so we don't mix dxil/hlsl/spirv and clang metadata
LLVM_FIXED_MD_KIND(MD_dxil_controlflow_hints, "dx.controlflow.hints", 42)
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index f3f78fb4f2bdbb..4903185309328e 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -32,7 +32,6 @@
#include "llvm/CodeGen/Register.h"
#include "llvm/CodeGen/TargetOpcodes.h"
#include "llvm/IR/IntrinsicsSPIRV.h"
-#include "llvm/IR/Metadata.h"
#include "llvm/Support/Debug.h"
#define DEBUG_TYPE "spirv-isel"
diff --git a/llvm/lib/Target/SPIRV/SPIRVMetadata.cpp b/llvm/lib/Target/SPIRV/SPIRVMetadata.cpp
index 7d5617919df87c..3800aac70df327 100644
--- a/llvm/lib/Target/SPIRV/SPIRVMetadata.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVMetadata.cpp
@@ -12,7 +12,6 @@
//===----------------------------------------------------------------------===//
#include "SPIRVMetadata.h"
-#include "llvm/IR/Metadata.h"
using namespace llvm;
@@ -82,4 +81,5 @@ MDString *getOCLKernelArgTypeQual(const Function &F, unsigned ArgIdx) {
"Kernel attributes are attached/belong only to OpenCL kernel functions");
return getOCLKernelArgAttribute(F, ArgIdx, "kernel_arg_type_qual");
}
+
} // namespace llvm
diff --git a/llvm/test/CodeGen/DirectX/HLSLBranchHint.ll b/llvm/test/CodeGen/DirectX/HLSLBranchHint.ll
new file mode 100644
index 00000000000000..e7128d19283e80
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/HLSLBranchHint.ll
@@ -0,0 +1,95 @@
+; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
+
+; This test make sure LLVM metadata is propagating to DXIL.
+
+
+; CHECK: define i32 @test_branch(i32 %X)
+; CHECK: br i1 %cmp, label %if.then, label %if.else, !dx.controlflow.hints [[HINT_BRANCH:![0-9]+]]
+define i32 @test_branch(i32 %X) {
+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, !dx.controlflow.hints !0
+
+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
+}
+
+
+; CHECK: define i32 @test_flatten(i32 %X)
+; CHECK: br i1 %cmp, label %if.then, label %if.else, !dx.controlflow.hints [[HINT_FLATTEN:![0-9]+]]
+define i32 @test_flatten(i32 %X) {
+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, !dx.controlflow.hints !1
+
+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
+}
+
+
+; CHECK: define i32 @test_no_attr(i32 %X)
+; CHECK-NO: !dx.controlflow.hints
+define i32 @test_no_attr(i32 %X) {
+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
+}
+
+; CHECK: [[HINT_BRANCH]] = !{!"dx.controlflow.hints", i32 1}
+; CHECK: [[HINT_FLATTEN]] = !{!"dx.controlflow.hints", i32 2}
+!0 = !{!"dx.controlflow.hints", i32 1}
+!1 = !{!"dx.controlflow.hints", i32 2}
diff --git a/llvm/test/CodeGen/SPIRV/HLSLBranchHint.ll b/llvm/test/CodeGen/SPIRV/HLSLBranchHint.ll
new file mode 100644
index 00000000000000..771f5603cf526f
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/HLSLBranchHint.ll
@@ -0,0 +1,91 @@
+; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+
+define spir_func noundef i32 @test_branch(i32 noundef %X) {
+entry:
+; CHECK-LABEL: ; -- Begin function test_branch
+; 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
+ %cmp = icmp sgt i32 %0, 0
+ br i1 %cmp, label %if.then, label %if.else, !dx.controlflow.hints !0
+
+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
+}
+
+
+define spir_func noundef i32 @test_flatten(i32 noundef %X) {
+entry:
+; CHECK-LABEL: ; -- Begin function test_flatten
+; 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
+ %cmp = icmp sgt i32 %0, 0
+ br i1 %cmp, label %if.then, label %if.else, !dx.controlflow.hints !1
+
+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
+}
+
+define spir_func noundef i32 @test_no_attr(i32 noundef %X) {
+entry:
+; CHECK-LABEL: ; -- Begin function test_no_attr
+; OpSelectionMerge %[[#]] None
+ %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
+}
+
+!0 = !{!"dx.controlflow.hints", i32 1}
+!1 = !{!"dx.controlflow.hints", i32 2}
>From 4c33ffb6a243a278583e79eb0694a5cd8a016e6a Mon Sep 17 00:00:00 2001
From: Joao Saffran <jderezende at microsoft.com>
Date: Fri, 15 Nov 2024 18:48:14 +0000
Subject: [PATCH 5/7] fixing spirv failures
---
llvm/include/llvm/IR/IntrinsicsSPIRV.td | 2 +-
.../Target/SPIRV/SPIRVInstructionSelector.cpp | 5 +--
llvm/lib/Target/SPIRV/SPIRVStructurizer.cpp | 35 ++++++++++---------
.../{ => structurizer}/HLSLBranchHint.ll | 0
4 files changed, 22 insertions(+), 20 deletions(-)
rename llvm/test/CodeGen/SPIRV/{ => structurizer}/HLSLBranchHint.ll (100%)
diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
index 4a5f744c74d9be..f29eb7ee22b2d2 100644
--- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td
+++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
@@ -33,7 +33,7 @@ let TargetPrefix = "spv" in {
def int_spv_ptrcast : Intrinsic<[llvm_any_ty], [llvm_any_ty, llvm_metadata_ty, llvm_i32_ty], [ImmArg<ArgIndex<2>>]>;
def int_spv_switch : Intrinsic<[], [llvm_any_ty, llvm_vararg_ty]>;
def int_spv_loop_merge : Intrinsic<[], [llvm_vararg_ty]>;
- def int_spv_selection_merge : Intrinsic<[], [llvm_metadata_ty, llvm_vararg_ty]>;
+ def int_spv_selection_merge : Intrinsic<[], [llvm_vararg_ty]>;
def int_spv_cmpxchg : Intrinsic<[llvm_i32_ty], [llvm_any_ty, llvm_vararg_ty]>;
def int_spv_unreachable : Intrinsic<[], []>;
def int_spv_alloca : Intrinsic<[llvm_any_ty], []>;
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index 4903185309328e..5576f46cf89f9a 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -2706,7 +2706,8 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
case Intrinsic::spv_selection_merge: {
auto SelectionControl = SPIRV::SelectionControl::None;
- const MDNode *MDOp = I.getOperand(1).getMetadata();
+ const MDNode *MDOp =
+ I.getOperand(I.getNumExplicitOperands() - 1).getMetadata();
if (MDOp->getNumOperands() > 0) {
ConstantInt *BranchHint =
mdconst::extract<ConstantInt>(MDOp->getOperand(1));
@@ -2721,7 +2722,7 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
auto MIB =
BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpSelectionMerge));
- for (unsigned i = 2; i < I.getNumExplicitOperands(); ++i) {
+ for (unsigned i = 1; i < I.getNumExplicitOperands() - 1; ++i) {
assert(I.getOperand(i).isMBB());
MIB.addMBB(I.getOperand(i).getMBB());
}
diff --git a/llvm/lib/Target/SPIRV/SPIRVStructurizer.cpp b/llvm/lib/Target/SPIRV/SPIRVStructurizer.cpp
index 6fed0b81bf61e7..1d837296ddc647 100644
--- a/llvm/lib/Target/SPIRV/SPIRVStructurizer.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVStructurizer.cpp
@@ -13,18 +13,17 @@
#include "SPIRVSubtarget.h"
#include "SPIRVTargetMachine.h"
#include "SPIRVUtils.h"
-#include "llvm-c/Core.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/CodeGen/IntrinsicLowering.h"
+#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/IntrinsicsSPIRV.h"
-#include "llvm/IR/Metadata.h"
#include "llvm/IR/ProfDataUtils.h"
#include "llvm/InitializePasses.h"
#include "llvm/Transforms/Utils/Cloning.h"
@@ -98,7 +97,7 @@ BasicBlock *getDesignatedMergeBlock(Instruction *I) {
II->getIntrinsicID() != Intrinsic::spv_selection_merge)
return nullptr;
- BlockAddress *BA = cast<BlockAddress>(II->getOperand(1));
+ BlockAddress *BA = cast<BlockAddress>(II->getOperand(0));
return BA->getBasicBlock();
}
@@ -647,14 +646,7 @@ class SPIRVStructurizer : public FunctionPass {
Builder.SetInsertPoint(Header->getTerminator());
auto MergeAddress = BlockAddress::get(BB.getParent(), &BB);
-
- MDNode *BranchMdNode = getDxBranchHint(*Header->getTerminator());
- Value *MDNodeValue =
- MetadataAsValue::get(Builder.getContext(), BranchMdNode);
-
- SmallVector<Value *, 2> Args = {MDNodeValue, MergeAddress};
-
- Builder.CreateIntrinsic(Intrinsic::spv_selection_merge, {}, {Args});
+ createOpSelectMerge(&Builder, MergeAddress);
Modified = true;
}
@@ -776,10 +768,9 @@ class SPIRVStructurizer : public FunctionPass {
BasicBlock *Merge = Candidates[0];
auto MergeAddress = BlockAddress::get(Merge->getParent(), Merge);
- SmallVector<Value *, 1> Args = {MergeAddress};
IRBuilder<> Builder(&BB);
Builder.SetInsertPoint(BB.getTerminator());
- Builder.CreateIntrinsic(Intrinsic::spv_selection_merge, {}, {Args});
+ createOpSelectMerge(&Builder, MergeAddress);
}
return Modified;
@@ -1112,8 +1103,7 @@ class SPIRVStructurizer : public FunctionPass {
Builder.SetInsertPoint(Header->getTerminator());
auto MergeAddress = BlockAddress::get(Merge->getParent(), Merge);
- SmallVector<Value *, 1> Args = {MergeAddress};
- Builder.CreateIntrinsic(Intrinsic::spv_selection_merge, {}, {Args});
+ createOpSelectMerge(&Builder, MergeAddress);
continue;
}
@@ -1127,8 +1117,7 @@ class SPIRVStructurizer : public FunctionPass {
Builder.SetInsertPoint(Header->getTerminator());
auto MergeAddress = BlockAddress::get(NewMerge->getParent(), NewMerge);
- SmallVector<Value *, 1> Args = {MergeAddress};
- Builder.CreateIntrinsic(Intrinsic::spv_selection_merge, {}, {Args});
+ createOpSelectMerge(&Builder, MergeAddress);
}
return Modified;
@@ -1215,6 +1204,18 @@ class SPIRVStructurizer : public FunctionPass {
AU.addPreserved<SPIRVConvergenceRegionAnalysisWrapperPass>();
FunctionPass::getAnalysisUsage(AU);
}
+
+ void createOpSelectMerge(IRBuilder<> *Builder, BlockAddress *MergeAddress) {
+ Instruction *BBTerminatoInst = Builder->GetInsertBlock()->getTerminator();
+
+ MDNode *BranchMdNode = getDxBranchHint(*BBTerminatoInst);
+ Value *MDNodeValue =
+ MetadataAsValue::get(Builder->getContext(), BranchMdNode);
+
+ llvm::SmallVector<llvm::Value *, 2> Args = {MergeAddress, MDNodeValue};
+
+ Builder->CreateIntrinsic(Intrinsic::spv_selection_merge, {}, {Args});
+ }
};
} // namespace llvm
diff --git a/llvm/test/CodeGen/SPIRV/HLSLBranchHint.ll b/llvm/test/CodeGen/SPIRV/structurizer/HLSLBranchHint.ll
similarity index 100%
rename from llvm/test/CodeGen/SPIRV/HLSLBranchHint.ll
rename to llvm/test/CodeGen/SPIRV/structurizer/HLSLBranchHint.ll
>From 6d01f396b71282b3be72633d25caa8dda10dc353 Mon Sep 17 00:00:00 2001
From: Joao Saffran <jderezende at microsoft.com>
Date: Fri, 15 Nov 2024 19:29:29 +0000
Subject: [PATCH 6/7] removing headers
---
llvm/lib/Target/SPIRV/SPIRVStructurizer.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/llvm/lib/Target/SPIRV/SPIRVStructurizer.cpp b/llvm/lib/Target/SPIRV/SPIRVStructurizer.cpp
index 1d837296ddc647..57285869b2e338 100644
--- a/llvm/lib/Target/SPIRV/SPIRVStructurizer.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVStructurizer.cpp
@@ -17,7 +17,6 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/CodeGen/IntrinsicLowering.h"
-#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/IRBuilder.h"
>From a0d11883d2f506a89323a5804bc44bf3fc130bb5 Mon Sep 17 00:00:00 2001
From: Joao Saffran <jderezende at microsoft.com>
Date: Fri, 15 Nov 2024 19:37:47 +0000
Subject: [PATCH 7/7] fixing format
---
clang/lib/Sema/SemaStmtAttr.cpp | 2 +-
llvm/test/CodeGen/SPIRV/HLSLBranchHint.ll | 91 +++++++++++++++++++++++
2 files changed, 92 insertions(+), 1 deletion(-)
create mode 100644 llvm/test/CodeGen/SPIRV/HLSLBranchHint.ll
diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index 68323092cb564d..827a674ece4bc0 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -624,7 +624,7 @@ static Attr *handleHLSLLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A,
}
static Attr *handleHLSLBranchHint(Sema &S, Stmt *St, const ParsedAttr &A,
- SourceRange Range) {
+ SourceRange Range) {
return ::new (S.Context) HLSLBranchHintAttr(S.Context, A);
}
diff --git a/llvm/test/CodeGen/SPIRV/HLSLBranchHint.ll b/llvm/test/CodeGen/SPIRV/HLSLBranchHint.ll
new file mode 100644
index 00000000000000..771f5603cf526f
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/HLSLBranchHint.ll
@@ -0,0 +1,91 @@
+; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+
+define spir_func noundef i32 @test_branch(i32 noundef %X) {
+entry:
+; CHECK-LABEL: ; -- Begin function test_branch
+; 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
+ %cmp = icmp sgt i32 %0, 0
+ br i1 %cmp, label %if.then, label %if.else, !dx.controlflow.hints !0
+
+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
+}
+
+
+define spir_func noundef i32 @test_flatten(i32 noundef %X) {
+entry:
+; CHECK-LABEL: ; -- Begin function test_flatten
+; 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
+ %cmp = icmp sgt i32 %0, 0
+ br i1 %cmp, label %if.then, label %if.else, !dx.controlflow.hints !1
+
+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
+}
+
+define spir_func noundef i32 @test_no_attr(i32 noundef %X) {
+entry:
+; CHECK-LABEL: ; -- Begin function test_no_attr
+; OpSelectionMerge %[[#]] None
+ %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
+}
+
+!0 = !{!"dx.controlflow.hints", i32 1}
+!1 = !{!"dx.controlflow.hints", i32 2}
More information about the cfe-commits
mailing list