Skip to content

[NFC][SPIRV] Move SPIRVStripConvergenceIntrinsics to Utils#188537

Merged
inbelic merged 8 commits into
llvm:mainfrom
inbelic:inbelic/rmv-conv-tokens
Apr 16, 2026
Merged

[NFC][SPIRV] Move SPIRVStripConvergenceIntrinsics to Utils#188537
inbelic merged 8 commits into
llvm:mainfrom
inbelic:inbelic/rmv-conv-tokens

Conversation

@inbelic

@inbelic inbelic commented Mar 25, 2026

Copy link
Copy Markdown
Contributor

The SPIRVStripConvergenceIntrinsic pass was written as a spirv pass as it is the currently the only target that emits convergence tokens during codegen. There is nothing target specific to the pass, and, we plan to emit convergence tokens when targeting DirectX (and all targets in general), so move the pass to a common place.

The previous pass used temporary Undefs, as part of moving the pass we can simply reverse the traverse order to remove the use of Undef as it is deprecated.

Enables the pass for targeting DirectX and is a pre-req for: #188792.

Assisted by: Github Copilot

@github-actions

github-actions Bot commented Mar 25, 2026

Copy link
Copy Markdown

✅ With the latest revision this PR passed the C/C++ code formatter.

@github-actions

github-actions Bot commented Mar 25, 2026

Copy link
Copy Markdown

✅ With the latest revision this PR passed the undef deprecator.

inbelic added 2 commits March 26, 2026 16:17
The `SPIRVStripConvergenceIntrinsic` pass was written as a spirv pass as
it is the currently the only target that emits convergence tokens during
codegen. There is nothing target specific to the pass, and, we plan to
emit convergence tokens when targeting DirectX and we can move the pass
to a common place.

Enables the pass for targeting DirectX and is a pre-req for: TODO.
by going in reverse order we remove the need to create a temporary undef
value
@inbelic inbelic force-pushed the inbelic/rmv-conv-tokens branch from b30f58c to ad43112 Compare March 26, 2026 16:31
@inbelic inbelic marked this pull request as ready for review March 26, 2026 17:39
@llvmbot

llvmbot commented Mar 26, 2026

Copy link
Copy Markdown
Member

@llvm/pr-subscribers-llvm-transforms
@llvm/pr-subscribers-backend-spir-v

@llvm/pr-subscribers-backend-directx

Author: Finn Plummer (inbelic)

Changes

The SPIRVStripConvergenceIntrinsic pass was written as a spirv pass as it is the currently the only target that emits convergence tokens during codegen. There is nothing target specific to the pass, and, we plan to emit convergence tokens when targeting DirectX (and all targets in general), so move the pass to a common place.

The previous pass used temporary Undefs, as part of moving the pass we can simply reverse the traverse order to remove the use of Undef as it is deprecated.

Enables the pass for targeting DirectX and is a pre-req for: #188792.

Assisted by: Github Copilot


Patch is 20.42 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/188537.diff

16 Files Affected:

  • (modified) llvm/include/llvm/InitializePasses.h (+2)
  • (modified) llvm/include/llvm/Transforms/Utils.h (+7)
  • (added) llvm/include/llvm/Transforms/Utils/StripConvergenceIntrinsics.h (+29)
  • (modified) llvm/lib/Passes/PassBuilder.cpp (+1)
  • (modified) llvm/lib/Passes/PassRegistry.def (+1)
  • (modified) llvm/lib/Target/DirectX/DirectXTargetMachine.cpp (+3)
  • (modified) llvm/lib/Target/SPIRV/CMakeLists.txt (-1)
  • (modified) llvm/lib/Target/SPIRV/SPIRV.h (-2)
  • (removed) llvm/lib/Target/SPIRV/SPIRVStripConvergentIntrinsics.cpp (-86)
  • (modified) llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp (+1-2)
  • (modified) llvm/lib/Transforms/Utils/CMakeLists.txt (+1)
  • (added) llvm/lib/Transforms/Utils/StripConvergenceIntrinsics.cpp (+89)
  • (modified) llvm/test/CodeGen/DirectX/llc-pipeline.ll (+3)
  • (added) llvm/test/CodeGen/DirectX/strip-convergence-intrinsics.ll (+38)
  • (modified) llvm/test/CodeGen/SPIRV/llc-pipeline.ll (+2-2)
  • (added) llvm/test/Transforms/StripConvergenceIntrinsics/basic.ll (+58)
diff --git a/llvm/include/llvm/InitializePasses.h b/llvm/include/llvm/InitializePasses.h
index 48e4ecd8ee2af..4a566eed16e32 100644
--- a/llvm/include/llvm/InitializePasses.h
+++ b/llvm/include/llvm/InitializePasses.h
@@ -324,6 +324,8 @@ LLVM_ABI void initializeStackSafetyInfoWrapperPassPass(PassRegistry &);
 LLVM_ABI void initializeStackSlotColoringLegacyPass(PassRegistry &);
 LLVM_ABI void
 initializeStraightLineStrengthReduceLegacyPassPass(PassRegistry &);
+LLVM_ABI void
+initializeStripConvergenceIntrinsicsLegacyPassPass(PassRegistry &);
 LLVM_ABI void initializeStripDebugMachineModulePass(PassRegistry &);
 LLVM_ABI void initializeStructurizeCFGLegacyPassPass(PassRegistry &);
 LLVM_ABI void initializeTailCallElimPass(PassRegistry &);
diff --git a/llvm/include/llvm/Transforms/Utils.h b/llvm/include/llvm/Transforms/Utils.h
index 840e085379a1d..c4e4dffc80c66 100644
--- a/llvm/include/llvm/Transforms/Utils.h
+++ b/llvm/include/llvm/Transforms/Utils.h
@@ -129,6 +129,13 @@ LLVM_ABI Pass *createCanonicalizeFreezeInLoopsPass();
 // functions that are registered in @llvm.global_ctors and which contain a call
 // to `__cxa_atexit` to register their destructor functions.
 LLVM_ABI ModulePass *createLowerGlobalDtorsLegacyPass();
+
+//===----------------------------------------------------------------------===//
+//
+// createStripConvergenceIntrinsicsPass - Strip convergence intrinsics and
+// convergencectrl operand bundles.
+//
+LLVM_ABI FunctionPass *createStripConvergenceIntrinsicsPass();
 } // namespace llvm
 
 #endif
diff --git a/llvm/include/llvm/Transforms/Utils/StripConvergenceIntrinsics.h b/llvm/include/llvm/Transforms/Utils/StripConvergenceIntrinsics.h
new file mode 100644
index 0000000000000..96a24641e34d2
--- /dev/null
+++ b/llvm/include/llvm/Transforms/Utils/StripConvergenceIntrinsics.h
@@ -0,0 +1,29 @@
+//===- StripConvergenceIntrinsics.h -----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This pass strips convergence intrinsics and operand bundles as those are
+/// only useful when modifying the CFG during IR passes.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_UTILS_STRIPCONVERGENCEINTRINSICS_H
+#define LLVM_TRANSFORMS_UTILS_STRIPCONVERGENCEINTRINSICS_H
+
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+class StripConvergenceIntrinsicsPass
+    : public PassInfoMixin<StripConvergenceIntrinsicsPass> {
+public:
+  PreservedAnalyses run(Function &F, FunctionAnalysisManager &);
+};
+
+} // namespace llvm
+
+#endif // LLVM_TRANSFORMS_UTILS_STRIPCONVERGENCEINTRINSICS_H
diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index a23d64b491a79..379aea8e07c8b 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -374,6 +374,7 @@
 #include "llvm/Transforms/Utils/PredicateInfo.h"
 #include "llvm/Transforms/Utils/ProfileVerify.h"
 #include "llvm/Transforms/Utils/RelLookupTableConverter.h"
+#include "llvm/Transforms/Utils/StripConvergenceIntrinsics.h"
 #include "llvm/Transforms/Utils/StripGCRelocates.h"
 #include "llvm/Transforms/Utils/StripNonLineTableDebugInfo.h"
 #include "llvm/Transforms/Utils/SymbolRewriter.h"
diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def
index c92d93d7ae396..82f73faefb624 100644
--- a/llvm/lib/Passes/PassRegistry.def
+++ b/llvm/lib/Passes/PassRegistry.def
@@ -543,6 +543,7 @@ FUNCTION_PASS("sjlj-eh-prepare", SjLjEHPreparePass(TM))
 FUNCTION_PASS("slp-vectorizer", SLPVectorizerPass())
 FUNCTION_PASS("slsr", StraightLineStrengthReducePass())
 FUNCTION_PASS("stack-protector", StackProtectorPass(*TM))
+FUNCTION_PASS("strip-convergence-intrinsics", StripConvergenceIntrinsicsPass())
 FUNCTION_PASS("strip-gc-relocates", StripGCRelocates())
 FUNCTION_PASS("tailcallelim", TailCallElimPass())
 FUNCTION_PASS("transform-warning", WarnMissedTransformationsPass())
diff --git a/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp b/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp
index c0a92f92e1fba..23bd820883b92 100644
--- a/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp
+++ b/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp
@@ -50,6 +50,7 @@
 #include "llvm/Transforms/IPO/GlobalDCE.h"
 #include "llvm/Transforms/Scalar.h"
 #include "llvm/Transforms/Scalar/Scalarizer.h"
+#include "llvm/Transforms/Utils.h"
 #include <optional>
 
 using namespace llvm;
@@ -81,6 +82,7 @@ LLVMInitializeDirectXTarget() {
   initializeDXILForwardHandleAccessesLegacyPass(*PR);
   initializeDSELegacyPassPass(*PR);
   initializeDXILCBufferAccessLegacyPass(*PR);
+  initializeStripConvergenceIntrinsicsLegacyPassPass(*PR);
 }
 
 class DXILTargetObjectFile : public TargetLoweringObjectFile {
@@ -125,6 +127,7 @@ class DirectXPassConfig : public TargetPassConfig {
     addPass(createDeadStoreEliminationPass());
     addPass(createDXILLegalizeLegacyPass());
     addPass(createDXILResourceImplicitBindingLegacyPass());
+    addPass(createStripConvergenceIntrinsicsPass());
     addPass(createDXILTranslateMetadataLegacyPass());
     addPass(createDXILPostOptimizationValidationLegacyPass());
     addPass(createDXILOpLoweringLegacyPass());
diff --git a/llvm/lib/Target/SPIRV/CMakeLists.txt b/llvm/lib/Target/SPIRV/CMakeLists.txt
index 0ce96c23603ff..6c79856c713e9 100644
--- a/llvm/lib/Target/SPIRV/CMakeLists.txt
+++ b/llvm/lib/Target/SPIRV/CMakeLists.txt
@@ -29,7 +29,6 @@ add_llvm_target(SPIRVCodeGen
   SPIRVInstructionSelector.cpp
   SPIRVLegalizeImplicitBinding.cpp
   SPIRVLegalizeZeroSizeArrays.cpp
-  SPIRVStripConvergentIntrinsics.cpp
   SPIRVLegalizePointerCast.cpp
   SPIRVMergeRegionExitTargets.cpp
   SPIRVISelLowering.cpp
diff --git a/llvm/lib/Target/SPIRV/SPIRV.h b/llvm/lib/Target/SPIRV/SPIRV.h
index 448a1f0ddaf96..231bbdcd5d304 100644
--- a/llvm/lib/Target/SPIRV/SPIRV.h
+++ b/llvm/lib/Target/SPIRV/SPIRV.h
@@ -24,7 +24,6 @@ FunctionPass *createSPIRVStructurizerPass();
 ModulePass *createSPIRVCBufferAccessLegacyPass();
 ModulePass *createSPIRVPushConstantAccessLegacyPass(SPIRVTargetMachine *TM);
 FunctionPass *createSPIRVMergeRegionExitTargetsPass();
-FunctionPass *createSPIRVStripConvergenceIntrinsicsPass();
 ModulePass *createSPIRVLegalizeImplicitBindingPass();
 ModulePass *createSPIRVLegalizeZeroSizeArraysPass(const SPIRVTargetMachine &TM);
 FunctionPass *createSPIRVLegalizePointerCastPass(SPIRVTargetMachine *TM);
@@ -57,7 +56,6 @@ void initializeSPIRVRegularizerPass(PassRegistry &);
 void initializeSPIRVMergeRegionExitTargetsPass(PassRegistry &);
 void initializeSPIRVPrepareFunctionsPass(PassRegistry &);
 void initializeSPIRVPrepareGlobalsPass(PassRegistry &);
-void initializeSPIRVStripConvergentIntrinsicsPass(PassRegistry &);
 void initializeSPIRVLegalizeImplicitBindingPass(PassRegistry &);
 void initializeSPIRVLegalizeZeroSizeArraysLegacyPass(PassRegistry &);
 void initializeSPIRVCtorDtorLoweringLegacyPass(PassRegistry &);
diff --git a/llvm/lib/Target/SPIRV/SPIRVStripConvergentIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVStripConvergentIntrinsics.cpp
deleted file mode 100644
index b1a8d1ab8a297..0000000000000
--- a/llvm/lib/Target/SPIRV/SPIRVStripConvergentIntrinsics.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-//===-- SPIRVStripConvergentIntrinsics.cpp ----------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This pass trims convergence intrinsics as those were only useful when
-// modifying the CFG during IR passes.
-//
-//===----------------------------------------------------------------------===//
-
-#include "SPIRV.h"
-#include "SPIRVSubtarget.h"
-#include "SPIRVUtils.h"
-#include "llvm/IR/IntrinsicInst.h"
-#include "llvm/IR/Intrinsics.h"
-#include "llvm/Transforms/Utils/Cloning.h"
-#include "llvm/Transforms/Utils/LowerMemIntrinsics.h"
-
-using namespace llvm;
-
-namespace {
-class SPIRVStripConvergentIntrinsics : public FunctionPass {
-public:
-  static char ID;
-
-  SPIRVStripConvergentIntrinsics() : FunctionPass(ID) {}
-
-  bool runOnFunction(Function &F) override {
-    DenseSet<Instruction *> ToRemove;
-
-    // Is the instruction is a convergent intrinsic, add it to kill-list and
-    // returns true. Returns false otherwise.
-    auto CleanupIntrinsic = [&](IntrinsicInst *II) {
-      if (II->getIntrinsicID() != Intrinsic::experimental_convergence_entry &&
-          II->getIntrinsicID() != Intrinsic::experimental_convergence_loop &&
-          II->getIntrinsicID() != Intrinsic::experimental_convergence_anchor)
-        return false;
-
-      II->replaceAllUsesWith(UndefValue::get(II->getType()));
-      ToRemove.insert(II);
-      return true;
-    };
-
-    // Replace the given CallInst by a similar CallInst with no convergencectrl
-    // attribute.
-    auto CleanupCall = [&](CallInst *CI) {
-      auto OB = CI->getOperandBundle(LLVMContext::OB_convergencectrl);
-      if (!OB.has_value())
-        return;
-
-      auto *NewCall = CallBase::removeOperandBundle(
-          CI, LLVMContext::OB_convergencectrl, CI->getIterator());
-      NewCall->copyMetadata(*CI);
-      CI->replaceAllUsesWith(NewCall);
-      ToRemove.insert(CI);
-    };
-
-    for (BasicBlock &BB : F) {
-      for (Instruction &I : BB) {
-        if (auto *II = dyn_cast<IntrinsicInst>(&I))
-          if (CleanupIntrinsic(II))
-            continue;
-        if (auto *CI = dyn_cast<CallInst>(&I))
-          CleanupCall(CI);
-      }
-    }
-
-    // All usages must be removed before their definition is removed.
-    for (Instruction *I : ToRemove)
-      I->eraseFromParent();
-
-    return ToRemove.size() != 0;
-  }
-};
-} // namespace
-
-char SPIRVStripConvergentIntrinsics::ID = 0;
-INITIALIZE_PASS(SPIRVStripConvergentIntrinsics, "strip-convergent-intrinsics",
-                "SPIRV strip convergent intrinsics", false, false)
-
-FunctionPass *llvm::createSPIRVStripConvergenceIntrinsicsPass() {
-  return new SPIRVStripConvergentIntrinsics();
-}
diff --git a/llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp b/llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp
index 061bfc21bc447..cb3e46a0b5ce0 100644
--- a/llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp
@@ -66,7 +66,6 @@ extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSPIRVTarget() {
   initializeSPIRVEmitNonSemanticDIPass(PR);
   initializeSPIRVPrepareFunctionsPass(PR);
   initializeSPIRVPrepareGlobalsPass(PR);
-  initializeSPIRVStripConvergentIntrinsicsPass(PR);
   initializeSPIRVCtorDtorLoweringLegacyPass(PR);
 }
 
@@ -225,7 +224,7 @@ void SPIRVPassConfig::addISelPrepare() {
     addPass(createPromoteMemoryToRegisterPass());
   }
   SPIRVTargetMachine &TM = getTM<SPIRVTargetMachine>();
-  addPass(createSPIRVStripConvergenceIntrinsicsPass());
+  addPass(createStripConvergenceIntrinsicsPass());
   addPass(createSPIRVLegalizeImplicitBindingPass());
   addPass(createSPIRVLegalizeZeroSizeArraysPass(TM));
   addPass(createSPIRVCBufferAccessLegacyPass());
diff --git a/llvm/lib/Transforms/Utils/CMakeLists.txt b/llvm/lib/Transforms/Utils/CMakeLists.txt
index 2b5f5cf344e60..82e9edf674866 100644
--- a/llvm/lib/Transforms/Utils/CMakeLists.txt
+++ b/llvm/lib/Transforms/Utils/CMakeLists.txt
@@ -74,6 +74,7 @@ add_llvm_component_library(LLVMTransformUtils
   RelLookupTableConverter.cpp
   ScalarEvolutionExpander.cpp
   SCCPSolver.cpp
+  StripConvergenceIntrinsics.cpp
   StripGCRelocates.cpp
   SSAUpdater.cpp
   SSAUpdaterBulk.cpp
diff --git a/llvm/lib/Transforms/Utils/StripConvergenceIntrinsics.cpp b/llvm/lib/Transforms/Utils/StripConvergenceIntrinsics.cpp
new file mode 100644
index 0000000000000..84ef3e6f48a5d
--- /dev/null
+++ b/llvm/lib/Transforms/Utils/StripConvergenceIntrinsics.cpp
@@ -0,0 +1,89 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass strips convergence intrinsics and convergencectrl operand bundles,
+// as those are only useful when modifying the CFG during IR passes.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Transforms/Utils/StripConvergenceIntrinsics.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Intrinsics.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/Transforms/Utils.h"
+
+using namespace llvm;
+
+static bool stripConvergenceIntrinsics(Function &F) {
+  bool Changed = false;
+
+  // Iterate in reverse order so that uses of convergence tokens are removed
+  // before the convergence intrinsics that define them.
+  for (BasicBlock &BB : reverse(F)) {
+    for (Instruction &I : make_early_inc_range(reverse(BB))) {
+      if (auto *II = dyn_cast<IntrinsicInst>(&I)) {
+        if (II->getIntrinsicID() == Intrinsic::experimental_convergence_entry ||
+            II->getIntrinsicID() == Intrinsic::experimental_convergence_loop ||
+            II->getIntrinsicID() ==
+                Intrinsic::experimental_convergence_anchor) {
+          II->eraseFromParent();
+          Changed = true;
+          continue;
+        }
+      }
+      if (auto *CI = dyn_cast<CallInst>(&I)) {
+        auto OB = CI->getOperandBundle(LLVMContext::OB_convergencectrl);
+        if (!OB.has_value())
+          continue;
+        auto *NewCall = CallBase::removeOperandBundle(
+            CI, LLVMContext::OB_convergencectrl, CI->getIterator());
+        NewCall->copyMetadata(*CI);
+        CI->replaceAllUsesWith(NewCall);
+        CI->eraseFromParent();
+        Changed = true;
+      }
+    }
+  }
+
+  return Changed;
+}
+
+PreservedAnalyses
+StripConvergenceIntrinsicsPass::run(Function &F, FunctionAnalysisManager &) {
+  if (!stripConvergenceIntrinsics(F))
+    return PreservedAnalyses::all();
+  return PreservedAnalyses::none();
+}
+
+namespace {
+class StripConvergenceIntrinsicsLegacyPass : public FunctionPass {
+public:
+  static char ID;
+
+  StripConvergenceIntrinsicsLegacyPass() : FunctionPass(ID) {
+    initializeStripConvergenceIntrinsicsLegacyPassPass(
+        *PassRegistry::getPassRegistry());
+  }
+
+  bool runOnFunction(Function &F) override {
+    return stripConvergenceIntrinsics(F);
+  }
+};
+} // namespace
+
+char StripConvergenceIntrinsicsLegacyPass::ID = 0;
+INITIALIZE_PASS(StripConvergenceIntrinsicsLegacyPass,
+                "strip-convergence-intrinsics",
+                "Strip convergence intrinsics and operand bundles", false,
+                false)
+
+FunctionPass *llvm::createStripConvergenceIntrinsicsPass() {
+  return new StripConvergenceIntrinsicsLegacyPass();
+}
diff --git a/llvm/test/CodeGen/DirectX/llc-pipeline.ll b/llvm/test/CodeGen/DirectX/llc-pipeline.ll
index 586567ceb18ec..04e0194690e73 100644
--- a/llvm/test/CodeGen/DirectX/llc-pipeline.ll
+++ b/llvm/test/CodeGen/DirectX/llc-pipeline.ll
@@ -39,11 +39,14 @@
 ; CHECK-NEXT:     DXIL Legalizer
 ; CHECK-NEXT:   DXIL Resource Binding Analysis
 ; CHECK-NEXT:   DXIL Resource Implicit Binding
+; CHECK-NEXT:   FunctionPass Manager
+; CHECK-NEXT:     Strip convergence intrinsics and operand bundles
 ; CHECK-NEXT:   DXIL Resources Analysis
 ; CHECK-NEXT:   DXIL Module Metadata analysis
 ; CHECK-NEXT:   DXIL Shader Flag Analysis
 ; CHECK-NEXT:   DXIL Root Signature Analysis
 ; CHECK-NEXT:   DXIL Translate Metadata
+; CHECK-NEXT:   DXIL Resource Binding Analysis
 ; CHECK-NEXT:   DXIL Post Optimization Validation
 ; CHECK-NEXT:   DXIL Op Lowering
 ; CHECK-NEXT:   DXIL Prepare Module
diff --git a/llvm/test/CodeGen/DirectX/strip-convergence-intrinsics.ll b/llvm/test/CodeGen/DirectX/strip-convergence-intrinsics.ll
new file mode 100644
index 0000000000000..afd858ad4eec3
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/strip-convergence-intrinsics.ll
@@ -0,0 +1,38 @@
+; RUN: llc %s -mtriple=dxil-pc-shadermodel6.3-library -o - | FileCheck %s
+
+; Verify that convergence intrinsics and operand bundles are stripped
+; during DXIL lowering pipeline.
+
+; CHECK-LABEL: define float @test(
+; CHECK-NOT: convergence
+; CHECK: ret float
+
+; CHECK-LABEL: define void @test_loop(
+; CHECK-NOT: convergence
+; CHECK: ret void
+
+define float @test(float %a) convergent {
+entry:
+  %0 = call token @llvm.experimental.convergence.entry()
+  %1 = call float @llvm.dx.dot(float %a) [ "convergencectrl"(token %0) ]
+  ret float %1
+}
+
+define void @test_loop(float %a) convergent {
+entry:
+  %0 = call token @llvm.experimental.convergence.entry()
+  br label %loop
+
+loop:
+  %1 = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %0) ]
+  call void @convergent_callee() [ "convergencectrl"(token %1) ]
+  br i1 true, label %exit, label %loop
+
+exit:
+  ret void
+}
+
+declare void @convergent_callee() convergent
+declare float @llvm.dx.dot(float)
+declare token @llvm.experimental.convergence.entry()
+declare token @llvm.experimental.convergence.loop()
diff --git a/llvm/test/CodeGen/SPIRV/llc-pipeline.ll b/llvm/test/CodeGen/SPIRV/llc-pipeline.ll
index 3b256f1a3a2dc..81b12caeddec1 100644
--- a/llvm/test/CodeGen/SPIRV/llc-pipeline.ll
+++ b/llvm/test/CodeGen/SPIRV/llc-pipeline.ll
@@ -40,7 +40,7 @@
 ; SPIRV-O0-NEXT:    FunctionPass Manager
 ; SPIRV-O0-NEXT:      Lower invoke and unwind, for unwindless code generators
 ; SPIRV-O0-NEXT:      Remove unreachable blocks from the CFG
-; SPIRV-O0-NEXT:      SPIRV strip convergent intrinsics
+; SPIRV-O0-NEXT:      Strip convergence intrinsics and operand bundles
 ; SPIRV-O0-NEXT:    SPIRV Legalize Implicit Binding
 ; SPIRV-O0-NEXT:    SPIRV Legalize Zero-Size Arrays
 ; SPIRV-O0-NEXT:    SPIRV CBuffer Access
@@ -154,7 +154,7 @@
 ; SPIRV-Opt-NEXT:      CodeGen Prepare
 ; SPIRV-Opt-NEXT:      Lower invoke and unwind, for unwindless code generators
 ; SPIRV-Opt-NEXT:      Remove unreachable blocks from the CFG
-; SPIRV-Opt-NEXT:      SPIRV strip convergent intrinsics
+; SPIRV-Opt-NEXT:      Strip convergence intrinsics and operand bundles
 ; SPIRV-Opt-NEXT:    SPIRV Legalize Implicit Binding
 ; SPIRV-Opt-NEXT:    SPIRV Legalize Zero-Size Arrays
 ; SPIRV-Opt-NEXT:    SPIRV CBuffer Access
diff --git a/llvm/test/Transforms/StripConvergenceIntrinsics/basic.ll b/llvm/test/Transforms/StripConvergenceIntrinsics/basic.ll
new file mode 100644
index 0000000000000..e233075fce2ed
--- /dev/null
+++ b/llvm/test/Transforms/StripConvergenceIntrinsics/basic.ll
@@ -0,0 +1,58 @@
+; RUN: opt -passes=strip-convergence-intrinsics -S < %s | FileCheck %s
+
+; Verify that convergence intrinsics and convergencectrl operand bundles are
+; stripped by the pass.
+
+define void @entry_and_call() convergent {
+; CHECK-LABEL: define void @entry_and_call()
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    call void @convergent_callee()
+; CHECK-NOT:     convergence
+; CHECK-NEXT:    ret void
+entry:
+  %0 = call token @llvm.experimental.convergence.entry()
+  call void @convergent_callee() [ "convergencectrl"(token %0) ]
+  ret void
+}
+
+define void @loop_with_token() convergent {
+; CHECK-LABEL: define void @loop_with_token()
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label %loop
+; CHECK:       loop:
+; CHECK-NEXT:    call void @convergent_callee()
+; CHECK-NOT:     convergence
+; CHECK-NEXT:    br i1
+entry:
+  %0 = call token @llvm.experimental.convergence.entry()
+  br label %loop
+
+loop:
+  %1 = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %0) ]
+  call void @convergent_callee() [ "convergencectrl"(token %1) ]
+  br i1 true, label %exit, label %loop
+
+exit:
+  ret void
+}
+
+define void @anchor_token() convergent {
+; CHECK-LABEL: define void @anchor_token()
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    call void @convergent_callee()
+; CHECK-NOT:     convergence
+; CHECK-NEXT:    ret void
+entry:
+  %0 = call token @llvm.experimental.convergenc...
[truncated]

@joaosaffran joaosaffran left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Left a question about the position of the convergence strip pass in the pipeline.

One thing I've been thinking about, though I don't think it needs to be addressed in this PR: do we have a sense of the impact this change has on compilation times and binary sizes for targets other than DirectX and SPIRV?

The goal of sharing this pass between the two targets makes total sense — but I wonder if Transforms/Utils is the right home for it, given that convergence intrinsics are a GPU/shader-specific concept. Would something like a dedicated Transforms/GPU/ (or similar) be worth exploring as a place to share passes that are meaningful to GPU targets like SPIRV and DirectX, without pulling them into every LLVM build?

Happy to discuss further in a follow-up issue if others think it's worth exploring. Not a blocker at all!

Comment thread llvm/test/CodeGen/DirectX/llc-pipeline.ll Outdated
Comment thread llvm/lib/Transforms/Utils/StripConvergenceIntrinsics.cpp Outdated
II->getIntrinsicID() == Intrinsic::experimental_convergence_loop ||
II->getIntrinsicID() ==
Intrinsic::experimental_convergence_anchor) {
II->eraseFromParent();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing that is logically different in this path compared to the spirv logic is that there is no:
II->replaceAllUsesWith(UndefValue::get(II->getType())); statement in the IntrinsicInst case.
Is this intentional?

@inbelic inbelic Apr 14, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, when copying over the use of undef I hit the following: #188537 (comment) (click the see edit panel). So I thought, if it is easy to do, we should remove the use of undef now that it is deprecated.

@inbelic

inbelic commented Apr 14, 2026

Copy link
Copy Markdown
Contributor Author

One thing I've been thinking about, though I don't think it needs to be addressed in this PR: do we have a sense of the impact this change has on compilation times and binary sizes for targets other than DirectX and SPIRV?

The goal of sharing this pass between the two targets makes total sense — but I wonder if Transforms/Utils is the right home for it, given that convergence intrinsics are a GPU/shader-specific concept. Would something like a dedicated Transforms/GPU/ (or similar) be worth exploring as a place to share passes that are meaningful to GPU targets like SPIRV and DirectX, without pulling them into every LLVM build?

The convergence control tokens are not necessarily bound to gpu use-cases, it could be used for modelling threads (or otherwise) so I think utils is fine

@Keenuts

Keenuts commented Apr 15, 2026

Copy link
Copy Markdown
Contributor

Would it be possible to to the file renaming between the SPIRVStripConvergence to StripConvergenceIntrinsics.cpp using git mv ? If so, we might be able to correctly identify what changed (since algo slighty changed) and keep track of history.
nevermind, file is completely changed.

Comment on lines +69 to +70
return PreservedAnalyses::all();
return PreservedAnalyses::none();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this pass preserves almost all analysis:

  • loop analysis is ok
  • CFG, domtree, etc

; Verify that convergence intrinsics and convergencectrl operand bundles are
; stripped by the pass.

define void @entry_and_call() convergent {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should add the test Deric mentioned: a block following a block it dominates in the CFG with intrinsincs to cleanup.

@inbelic inbelic merged commit ffde06f into llvm:main Apr 16, 2026
12 checks passed
@llvm-ci

llvm-ci commented Apr 16, 2026

Copy link
Copy Markdown

LLVM Buildbot has detected a new failure on builder clang-hip-vega20 running on hip-vega20-0 while building llvm at step 3 "annotate".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/123/builds/38709

Here is the relevant piece of the build log for the reference
Step 3 (annotate) failure: '../llvm-zorg/zorg/buildbot/builders/annotated/hip-build.sh --jobs=' (failure)
...
+ HERE=../llvm-zorg/zorg/buildbot/builders/annotated
+ . ../llvm-zorg/zorg/buildbot/builders/annotated/buildbot-helper.sh
+ set -eu
+ halt_on_failure
+ echo @@@HALT_ON_FAILURE@@@
@@@HALT_ON_FAILURE@@@
@@@BUILD_STEP Setting up the buildbot@@@
+ setup_env
+ build_step 'Setting up the buildbot'
+ echo '@@@BUILD_STEP Setting up the buildbot@@@'
+ BUILDBOT_ROOT=/home/botworker/bbot/clang-hip-vega20
++ whoami
+ BUILDBOT_SLAVENAME=botworker
+ AMDGPU_ARCHS='gfx908;gfx90a;gfx1030;gfx1100'
+ EXTERNAL_DIR=/opt/botworker/llvm/External
+ BUILD_DIR=/home/botworker/bbot/clang-hip-vega20/botworker/clang-hip-vega20
+ DESTDIR=/home/botworker/bbot/clang-hip-vega20/botworker/clang-hip-vega20/install
+ LLVM_ROOT=/home/botworker/bbot/clang-hip-vega20/llvm-project
+ LLVM_REVISION=ffde06f4c11927c60936802fb439a5195ac0742e
+ LLVM_BUILD_DIR=/home/botworker/bbot/clang-hip-vega20/botworker/clang-hip-vega20/llvm
+ TESTSUITE_ROOT=/home/botworker/bbot/clang-hip-vega20/llvm-test-suite
+ TEST_BUILD_DIR=/home/botworker/bbot/clang-hip-vega20/botworker/clang-hip-vega20/test-suite-build
+ NINJAOPT=
+ echo BUILDBOT_ROOT=/home/botworker/bbot/clang-hip-vega20
+ echo BUILDBOT_SLAVENAME=botworker
+ echo 'AMDGPU_ARCHS=gfx908;gfx90a;gfx1030;gfx1100'
+ echo LLVM_ROOT=/home/botworker/bbot/clang-hip-vega20/llvm-project
+ echo TESTSUITE_ROOT=/home/botworker/bbot/clang-hip-vega20/llvm-test-suite
+ echo EXTERNAL_DIR=/opt/botworker/llvm/External
+ echo BUILD_DIR=/home/botworker/bbot/clang-hip-vega20/botworker/clang-hip-vega20
+ echo DESTDIR=/home/botworker/bbot/clang-hip-vega20/botworker/clang-hip-vega20/install
+ echo LLVM_BUILD_DIR=/home/botworker/bbot/clang-hip-vega20/botworker/clang-hip-vega20/llvm
+ echo TEST_BUILD_DIR=/home/botworker/bbot/clang-hip-vega20/botworker/clang-hip-vega20/test-suite-build
+ update_llvm
+ '[' '!' -d /home/botworker/bbot/clang-hip-vega20/llvm-project ']'
BUILDBOT_ROOT=/home/botworker/bbot/clang-hip-vega20
BUILDBOT_SLAVENAME=botworker
AMDGPU_ARCHS=gfx908;gfx90a;gfx1030;gfx1100
LLVM_ROOT=/home/botworker/bbot/clang-hip-vega20/llvm-project
TESTSUITE_ROOT=/home/botworker/bbot/clang-hip-vega20/llvm-test-suite
EXTERNAL_DIR=/opt/botworker/llvm/External
BUILD_DIR=/home/botworker/bbot/clang-hip-vega20/botworker/clang-hip-vega20
DESTDIR=/home/botworker/bbot/clang-hip-vega20/botworker/clang-hip-vega20/install
LLVM_BUILD_DIR=/home/botworker/bbot/clang-hip-vega20/botworker/clang-hip-vega20/llvm
TEST_BUILD_DIR=/home/botworker/bbot/clang-hip-vega20/botworker/clang-hip-vega20/test-suite-build
@@@BUILD_STEP Updating llvm-project repo@@@
+ build_step 'Updating llvm-project repo'
+ echo '@@@BUILD_STEP Updating llvm-project repo@@@'
+ git -C /home/botworker/bbot/clang-hip-vega20/llvm-project fetch --prune origin
fatal: unable to access 'https://github.com/llvm/llvm-project.git/': The requested URL returned error: 504
Step 5 (Updating llvm-project repo) failure: Updating llvm-project repo (failure)
@@@BUILD_STEP Updating llvm-project repo@@@
+ build_step 'Updating llvm-project repo'
+ echo '@@@BUILD_STEP Updating llvm-project repo@@@'
+ git -C /home/botworker/bbot/clang-hip-vega20/llvm-project fetch --prune origin
fatal: unable to access 'https://github.com/llvm/llvm-project.git/': The requested URL returned error: 504
program finished with exit code 128
elapsedTime=600.214599

alexfh pushed a commit to alexfh/llvm-project that referenced this pull request Apr 18, 2026
…8537)

The `SPIRVStripConvergenceIntrinsic` pass was written as a spirv pass as
it is the currently the only target that emits convergence tokens during
codegen. There is nothing target specific to the pass, and, we plan to
emit convergence tokens when targeting DirectX (and all targets in
general), so move the pass to a common place.

The previous pass used temporary `Undef`s, as part of moving the pass we
can simply reverse the traverse order to remove the use of `Undef` as it
is deprecated.

Enables the pass for targeting DirectX and is a pre-req for:
llvm#188792.

Assisted by: Github Copilot
inbelic added a commit that referenced this pull request Apr 20, 2026
#188792)

This pr allows codegen to generate convergence control tokens. This
allows for a more accurate description of convergence behaviour to
prevent (or allow) invalid control flow graph transforms. As noted, the
use of convergence control tokens is the ideal norm and this follows
that by enabling it for `DirectX`.

This was done now under the precedent of preventing a convergent exit
condition of a loop from being illegally moved across control flow. Test
cases for this are explicitly added.

Please see the individual commits for logically similar chunks.
Unfortunately, it is tricky to stage this in smaller individual commits.

Resolves #180621.

#188537 is a pre-requisite of
this passing HLSL offload suite tests.

Assisted by: Github Copilot
llvm-sync Bot pushed a commit to arm/arm-toolchain that referenced this pull request Apr 20, 2026
…ting DirectX (#188792)

This pr allows codegen to generate convergence control tokens. This
allows for a more accurate description of convergence behaviour to
prevent (or allow) invalid control flow graph transforms. As noted, the
use of convergence control tokens is the ideal norm and this follows
that by enabling it for `DirectX`.

This was done now under the precedent of preventing a convergent exit
condition of a loop from being illegally moved across control flow. Test
cases for this are explicitly added.

Please see the individual commits for logically similar chunks.
Unfortunately, it is tricky to stage this in smaller individual commits.

Resolves llvm/llvm-project#180621.

llvm/llvm-project#188537 is a pre-requisite of
this passing HLSL offload suite tests.

Assisted by: Github Copilot
cpullvm-upstream-sync Bot pushed a commit to navaneethshan/cpullvm-toolchain-1 that referenced this pull request Apr 20, 2026
…ting DirectX (#188792)

This pr allows codegen to generate convergence control tokens. This
allows for a more accurate description of convergence behaviour to
prevent (or allow) invalid control flow graph transforms. As noted, the
use of convergence control tokens is the ideal norm and this follows
that by enabling it for `DirectX`.

This was done now under the precedent of preventing a convergent exit
condition of a loop from being illegally moved across control flow. Test
cases for this are explicitly added.

Please see the individual commits for logically similar chunks.
Unfortunately, it is tricky to stage this in smaller individual commits.

Resolves llvm/llvm-project#180621.

llvm/llvm-project#188537 is a pre-requisite of
this passing HLSL offload suite tests.

Assisted by: Github Copilot
@llvm-ci

llvm-ci commented Apr 20, 2026

Copy link
Copy Markdown

LLVM Buildbot has detected a new failure on builder clang-sparc64-linux running on debian-stadler-sparc64 while building llvm at step 14 "test-suite".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/114/builds/453

Here is the relevant piece of the build log for the reference
Step 14 (test-suite) failure: test (failure)
...
*** MICRO-TEST: benchVecWithRuntimeChecks4PointersDBeforeA/1000
    exec_time:  11940262.1379 
*** MICRO-TEST: benchVecWithRuntimeChecks4PointersDBeforeA/32
    exec_time:  430702.4855 
*** MICRO-TEST: benchVecWithRuntimeChecks4PointersDEqualsA/1000
    exec_time:  11326682.5574 
*** MICRO-TEST: benchVecWithRuntimeChecks4PointersDEqualsA/32
    exec_time:  397935.9768 
********************
NOEXE: test-suite :: SingleSource/UnitTests/Vectorizer/tf-any-of.test (524 of 616)
******************** TEST 'test-suite :: SingleSource/UnitTests/Vectorizer/tf-any-of.test' FAILED ********************
Executable '/var/lib/buildbot/workers/debian-stadler-sparc64/clang-sparc64-linux/test/sandbox/build/SingleSource/UnitTests/Vectorizer/tf-any-of' is missing
********************
NOEXE: test-suite :: SingleSource/UnitTests/Vectorizer/tf-argmin-argmax-fp.test (525 of 616)
******************** TEST 'test-suite :: SingleSource/UnitTests/Vectorizer/tf-argmin-argmax-fp.test' FAILED ********************
Executable '/var/lib/buildbot/workers/debian-stadler-sparc64/clang-sparc64-linux/test/sandbox/build/SingleSource/UnitTests/Vectorizer/tf-argmin-argmax-fp' is missing
********************
NOEXE: test-suite :: SingleSource/UnitTests/Vectorizer/tf-argmin-argmax-int.test (526 of 616)
******************** TEST 'test-suite :: SingleSource/UnitTests/Vectorizer/tf-argmin-argmax-int.test' FAILED ********************
Executable '/var/lib/buildbot/workers/debian-stadler-sparc64/clang-sparc64-linux/test/sandbox/build/SingleSource/UnitTests/Vectorizer/tf-argmin-argmax-int' is missing
********************
NOEXE: test-suite :: SingleSource/UnitTests/Vectorizer/tf-early-exit.test (527 of 616)
******************** TEST 'test-suite :: SingleSource/UnitTests/Vectorizer/tf-early-exit.test' FAILED ********************
Executable '/var/lib/buildbot/workers/debian-stadler-sparc64/clang-sparc64-linux/test/sandbox/build/SingleSource/UnitTests/Vectorizer/tf-early-exit' is missing
********************
NOEXE: test-suite :: SingleSource/UnitTests/Vectorizer/tf-find-last.test (528 of 616)
******************** TEST 'test-suite :: SingleSource/UnitTests/Vectorizer/tf-find-last.test' FAILED ********************
Executable '/var/lib/buildbot/workers/debian-stadler-sparc64/clang-sparc64-linux/test/sandbox/build/SingleSource/UnitTests/Vectorizer/tf-find-last' is missing
********************
NOEXE: test-suite :: SingleSource/UnitTests/Vectorizer/tf-fmax-reduction.test (529 of 616)
******************** TEST 'test-suite :: SingleSource/UnitTests/Vectorizer/tf-fmax-reduction.test' FAILED ********************
Executable '/var/lib/buildbot/workers/debian-stadler-sparc64/clang-sparc64-linux/test/sandbox/build/SingleSource/UnitTests/Vectorizer/tf-fmax-reduction' is missing
********************
NOEXE: test-suite :: SingleSource/UnitTests/Vectorizer/tf-ftic-any-of.test (530 of 616)
******************** TEST 'test-suite :: SingleSource/UnitTests/Vectorizer/tf-ftic-any-of.test' FAILED ********************
Executable '/var/lib/buildbot/workers/debian-stadler-sparc64/clang-sparc64-linux/test/sandbox/build/SingleSource/UnitTests/Vectorizer/tf-ftic-any-of' is missing
********************
NOEXE: test-suite :: SingleSource/UnitTests/Vectorizer/tf-ftic-argmin-argmax-fp.test (531 of 616)
******************** TEST 'test-suite :: SingleSource/UnitTests/Vectorizer/tf-ftic-argmin-argmax-fp.test' FAILED ********************
Executable '/var/lib/buildbot/workers/debian-stadler-sparc64/clang-sparc64-linux/test/sandbox/build/SingleSource/UnitTests/Vectorizer/tf-ftic-argmin-argmax-fp' is missing
********************
NOEXE: test-suite :: SingleSource/UnitTests/Vectorizer/tf-ftic-argmin-argmax-int.test (532 of 616)
******************** TEST 'test-suite :: SingleSource/UnitTests/Vectorizer/tf-ftic-argmin-argmax-int.test' FAILED ********************
Executable '/var/lib/buildbot/workers/debian-stadler-sparc64/clang-sparc64-linux/test/sandbox/build/SingleSource/UnitTests/Vectorizer/tf-ftic-argmin-argmax-int' is missing
********************
NOEXE: test-suite :: SingleSource/UnitTests/Vectorizer/tf-ftic-early-exit.test (533 of 616)
******************** TEST 'test-suite :: SingleSource/UnitTests/Vectorizer/tf-ftic-early-exit.test' FAILED ********************
Executable '/var/lib/buildbot/workers/debian-stadler-sparc64/clang-sparc64-linux/test/sandbox/build/SingleSource/UnitTests/Vectorizer/tf-ftic-early-exit' is missing
********************

s-perron pushed a commit to s-perron/llvm-project that referenced this pull request Apr 21, 2026
llvm#188792)

This pr allows codegen to generate convergence control tokens. This
allows for a more accurate description of convergence behaviour to
prevent (or allow) invalid control flow graph transforms. As noted, the
use of convergence control tokens is the ideal norm and this follows
that by enabling it for `DirectX`.

This was done now under the precedent of preventing a convergent exit
condition of a loop from being illegally moved across control flow. Test
cases for this are explicitly added.

Please see the individual commits for logically similar chunks.
Unfortunately, it is tricky to stage this in smaller individual commits.

Resolves llvm#180621.

llvm#188537 is a pre-requisite of
this passing HLSL offload suite tests.

Assisted by: Github Copilot
llvm-upstreamsync Bot pushed a commit to qualcomm/cpullvm-toolchain that referenced this pull request Apr 24, 2026
…ting DirectX (#188792)

This pr allows codegen to generate convergence control tokens. This
allows for a more accurate description of convergence behaviour to
prevent (or allow) invalid control flow graph transforms. As noted, the
use of convergence control tokens is the ideal norm and this follows
that by enabling it for `DirectX`.

This was done now under the precedent of preventing a convergent exit
condition of a loop from being illegally moved across control flow. Test
cases for this are explicitly added.

Please see the individual commits for logically similar chunks.
Unfortunately, it is tricky to stage this in smaller individual commits.

Resolves llvm/llvm-project#180621.

llvm/llvm-project#188537 is a pre-requisite of
this passing HLSL offload suite tests.

Assisted by: Github Copilot
KHicketts pushed a commit to KHicketts/llvm-project that referenced this pull request Apr 30, 2026
llvm#188792)

This pr allows codegen to generate convergence control tokens. This
allows for a more accurate description of convergence behaviour to
prevent (or allow) invalid control flow graph transforms. As noted, the
use of convergence control tokens is the ideal norm and this follows
that by enabling it for `DirectX`.

This was done now under the precedent of preventing a convergent exit
condition of a loop from being illegally moved across control flow. Test
cases for this are explicitly added.

Please see the individual commits for logically similar chunks.
Unfortunately, it is tricky to stage this in smaller individual commits.

Resolves llvm#180621.

llvm#188537 is a pre-requisite of
this passing HLSL offload suite tests.

Assisted by: Github Copilot
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[HLSL][DirectX] Loop is removed when exit condition is convergent

8 participants