[llvm] [AMDGPU] Model structured control-flow lane masks as i1 (PR #209158)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 13 05:17:53 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-ir

@llvm/pr-subscribers-llvm-globalisel

Author: Pankaj Dwivedi (PankajDwivedi-25)

<details>
<summary>Changes</summary>

Ref: #<!-- -->206435.

The lane mask from the structured CF intrinsics (`if`, `else`, `if.break`, `loop`, `end.cf`) is a per-lane value, but it was typed as an overloaded `i32`/`i64`. 

This patch attempts to retype these intrinsics to `i1`, the natural type for a wave-width lane mask.

---

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


72 Files Affected:

- (modified) llvm/include/llvm/IR/IntrinsicsAMDGPU.td (+7-7) 
- (modified) llvm/lib/Target/AMDGPU/AMDGPUGlobalISelDivergenceLowering.cpp (+1-1) 
- (modified) llvm/lib/Target/AMDGPU/AMDGPUGlobalISelUtils.cpp (+5-5) 
- (modified) llvm/lib/Target/AMDGPU/AMDGPUGlobalISelUtils.h (+6-8) 
- (modified) llvm/lib/Target/AMDGPU/AMDGPURegBankLegalizeRules.cpp (+7-8) 
- (modified) llvm/lib/Target/AMDGPU/AMDGPURegBankSelect.cpp (+6-1) 
- (modified) llvm/lib/Target/AMDGPU/AMDGPUSearchableTables.td (+4-1) 
- (modified) llvm/lib/Target/AMDGPU/SIAnnotateControlFlow.cpp (+8-15) 
- (modified) llvm/lib/Target/AMDGPU/SIISelLowering.cpp (+2-2) 
- (modified) llvm/test/Analysis/UniformityAnalysis/AMDGPU/control-flow-intrinsics.ll (+40-40) 
- (modified) llvm/test/CodeGen/AMDGPU/GlobalISel/atomicrmw_fmax.ll (+286-80) 
- (modified) llvm/test/CodeGen/AMDGPU/GlobalISel/atomicrmw_fmin.ll (+286-80) 
- (modified) llvm/test/CodeGen/AMDGPU/GlobalISel/divergence-divergent-i1-phis-no-lane-mask-merging.ll (+41-28) 
- (modified) llvm/test/CodeGen/AMDGPU/GlobalISel/divergence-divergent-i1-used-outside-loop.ll (+131-96) 
- (modified) llvm/test/CodeGen/AMDGPU/GlobalISel/divergence-structurizer.ll (+92-60) 
- (modified) llvm/test/CodeGen/AMDGPU/GlobalISel/divergence-temporal-divergent-i1.ll (+115-74) 
- (modified) llvm/test/CodeGen/AMDGPU/GlobalISel/divergence-temporal-divergent-reg.ll (+24-16) 
- (modified) llvm/test/CodeGen/AMDGPU/GlobalISel/divergent-control-flow.ll (+18-12) 
- (modified) llvm/test/CodeGen/AMDGPU/GlobalISel/global-atomic-fadd.f64.ll (+36-18) 
- (modified) llvm/test/CodeGen/AMDGPU/GlobalISel/irtranslator-atomicrmw.ll (+20-20) 
- (modified) llvm/test/CodeGen/AMDGPU/GlobalISel/irtranslator-function-args.ll (+2-2) 
- (modified) llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.end.cf.i32.ll (+7-3) 
- (modified) llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.end.cf.i64.ll (+6-6) 
- (modified) llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.if.break.i32.ll (+14-7) 
- (modified) llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.if.break.i64.ll (+17-12) 
- (modified) llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.wqm.demote.ll (+64-46) 
- (modified) llvm/test/CodeGen/AMDGPU/GlobalISel/regbankselect-mui-regbanklegalize.mir (+214-155) 
- (modified) llvm/test/CodeGen/AMDGPU/GlobalISel/regbankselect-mui.mir (+322-223) 
- (modified) llvm/test/CodeGen/AMDGPU/asyncmark-pregfx12.ll (+37-29) 
- (modified) llvm/test/CodeGen/AMDGPU/atomicrmw_usub_cond.ll (+95-35) 
- (modified) llvm/test/CodeGen/AMDGPU/atomicrmw_usub_sat.ll (+830-286) 
- (modified) llvm/test/CodeGen/AMDGPU/buffer-fat-pointer-atomicrmw-fadd.ll (+122-113) 
- (modified) llvm/test/CodeGen/AMDGPU/buffer-fat-pointer-atomicrmw-fmax.ll (+112-103) 
- (modified) llvm/test/CodeGen/AMDGPU/buffer-fat-pointer-atomicrmw-fmin.ll (+112-103) 
- (modified) llvm/test/CodeGen/AMDGPU/codegen-prepare-addrspacecast-non-null.ll (+67-28) 
- (modified) llvm/test/CodeGen/AMDGPU/div_i128.ll (+36-32) 
- (modified) llvm/test/CodeGen/AMDGPU/div_v2i128.ll (+188-188) 
- (modified) llvm/test/CodeGen/AMDGPU/diverge-switch-default.ll (+3-3) 
- (modified) llvm/test/CodeGen/AMDGPU/divergent-branch-uniform-condition.ll (+4-4) 
- (added) llvm/test/CodeGen/AMDGPU/divergent-loop-i1-lane-mask.ll (+118) 
- (modified) llvm/test/CodeGen/AMDGPU/flat-saddr-atomics.ll (+945-395) 
- (modified) llvm/test/CodeGen/AMDGPU/irtranslator-whole-wave-functions.ll (+2-2) 
- (modified) llvm/test/CodeGen/AMDGPU/literal64.ll (+57-24) 
- (modified) llvm/test/CodeGen/AMDGPU/llvm.amdgcn.init.whole.wave-w32.ll (+23-12) 
- (modified) llvm/test/CodeGen/AMDGPU/llvm.amdgcn.raw.atomic.buffer.load.ll (+2092-689) 
- (modified) llvm/test/CodeGen/AMDGPU/llvm.amdgcn.raw.ptr.atomic.buffer.load.ll (+2092-689) 
- (modified) llvm/test/CodeGen/AMDGPU/llvm.amdgcn.struct.atomic.buffer.load.ll (+2350-610) 
- (modified) llvm/test/CodeGen/AMDGPU/llvm.amdgcn.struct.ptr.atomic.buffer.load.ll (+2350-610) 
- (modified) llvm/test/CodeGen/AMDGPU/loop-on-function-argument.ll (+4-4) 
- (modified) llvm/test/CodeGen/AMDGPU/loop_break.ll (+24-24) 
- (modified) llvm/test/CodeGen/AMDGPU/machine-sink-temporal-divergence-swdev407790.ll (+1-1) 
- (modified) llvm/test/CodeGen/AMDGPU/memory-legalizer-atomic-insert-end.mir (+6-6) 
- (modified) llvm/test/CodeGen/AMDGPU/memory-legalizer-multiple-mem-operands-nontemporal-1.mir (+5-5) 
- (modified) llvm/test/CodeGen/AMDGPU/memset-param-combinations.ll (+306-153) 
- (modified) llvm/test/CodeGen/AMDGPU/memset-pattern.ll (+715-299) 
- (modified) llvm/test/CodeGen/AMDGPU/multi-divergent-exit-region.ll (+45-45) 
- (modified) llvm/test/CodeGen/AMDGPU/multilevel-break.ll (+16-16) 
- (modified) llvm/test/CodeGen/AMDGPU/nested-loop-conditions.ll (+28-30) 
- (modified) llvm/test/CodeGen/AMDGPU/rem_i128.ll (+18-16) 
- (modified) llvm/test/CodeGen/AMDGPU/sdiv64.ll (+5-5) 
- (modified) llvm/test/CodeGen/AMDGPU/si-annotate-cf-unreachable.ll (+1-1) 
- (modified) llvm/test/CodeGen/AMDGPU/si-annotate-dbg-info.ll (+15-15) 
- (added) llvm/test/CodeGen/AMDGPU/si-annotate-loop-i1-lane-mask.ll (+43) 
- (modified) llvm/test/CodeGen/AMDGPU/si-annotatecfg-multiple-backedges.ll (+9-9) 
- (modified) llvm/test/CodeGen/AMDGPU/si-unify-exit-return-unreachable.ll (+23-23) 
- (modified) llvm/test/CodeGen/AMDGPU/srem64.ll (+5-5) 
- (modified) llvm/test/CodeGen/AMDGPU/udiv64.ll (+5-5) 
- (modified) llvm/test/CodeGen/AMDGPU/unstructured-cfg-def-use-issue.ll (+21-21) 
- (modified) llvm/test/CodeGen/AMDGPU/urem64.ll (+4-4) 
- (modified) llvm/test/CodeGen/AMDGPU/valu-i1.ll (+11-11) 
- (modified) llvm/test/CodeGen/AMDGPU/wave32.ll (+5-5) 
- (modified) llvm/test/CodeGen/MIR/AMDGPU/syncscopes.mir (+5-5) 


``````````diff
diff --git a/llvm/include/llvm/IR/IntrinsicsAMDGPU.td b/llvm/include/llvm/IR/IntrinsicsAMDGPU.td
index 21882e247c027..12c96d354760b 100644
--- a/llvm/include/llvm/IR/IntrinsicsAMDGPU.td
+++ b/llvm/include/llvm/IR/IntrinsicsAMDGPU.td
@@ -3903,24 +3903,24 @@ def int_amdgcn_cooperative_atomic_store_8x16B : AMDGPUCooperativeAtomicStore<llv
 // convergence control tokens. The corresponding MIR pseudos are marked as
 // having side effects, which is sufficient to prevent optimizations without
 // having to mark them as convergent.
-def int_amdgcn_if : Intrinsic<[llvm_i1_ty, llvm_anyint_ty],
+def int_amdgcn_if : Intrinsic<[llvm_i1_ty, llvm_i1_ty],
   [llvm_i1_ty], [IntrWillReturn, IntrNoCallback, IntrNoFree]
 >;
 
-def int_amdgcn_else : Intrinsic<[llvm_i1_ty, llvm_anyint_ty],
-  [llvm_anyint_ty], [IntrWillReturn, IntrNoCallback, IntrNoFree]
+def int_amdgcn_else : Intrinsic<[llvm_i1_ty, llvm_i1_ty],
+  [llvm_i1_ty], [IntrWillReturn, IntrNoCallback, IntrNoFree]
 >;
 
-def int_amdgcn_if_break : Intrinsic<[llvm_anyint_ty],
-  [llvm_i1_ty, LLVMMatchType<0>],
+def int_amdgcn_if_break : Intrinsic<[llvm_i1_ty],
+  [llvm_i1_ty, llvm_i1_ty],
   [IntrNoMem, IntrWillReturn, IntrNoCallback, IntrNoFree]
 >;
 
 def int_amdgcn_loop : Intrinsic<[llvm_i1_ty],
-  [llvm_anyint_ty], [IntrWillReturn, IntrNoCallback, IntrNoFree]
+  [llvm_i1_ty], [IntrWillReturn, IntrNoCallback, IntrNoFree]
 >;
 
-def int_amdgcn_end_cf : Intrinsic<[], [llvm_anyint_ty],
+def int_amdgcn_end_cf : Intrinsic<[], [llvm_i1_ty],
   [IntrWillReturn, IntrNoCallback, IntrNoFree]>;
 
 // Represent unreachable in a divergent region.
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUGlobalISelDivergenceLowering.cpp b/llvm/lib/Target/AMDGPU/AMDGPUGlobalISelDivergenceLowering.cpp
index cbb4269e17260..2ae63025d2fd7 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUGlobalISelDivergenceLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUGlobalISelDivergenceLowering.cpp
@@ -208,7 +208,7 @@ bool DivergenceLoweringHelper::lowerTemporalDivergence() {
 
   for (auto [Reg, UseInst, _] : MUI->getTemporalDivergenceList()) {
     if (MRI->getType(Reg) == LLT::scalar(1) || MUI->isDivergentAtDef(Reg) ||
-        ILMA.isS32S64LaneMask(Reg))
+        ILMA.isLaneMask(Reg))
       continue;
 
     Register CachedTDCopy = TDCache.lookup(Reg);
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUGlobalISelUtils.cpp b/llvm/lib/Target/AMDGPU/AMDGPUGlobalISelUtils.cpp
index f36935d8c0e8f..0b7b2fe8cb13b 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUGlobalISelUtils.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUGlobalISelUtils.cpp
@@ -83,8 +83,8 @@ IntrinsicLaneMaskAnalyzer::IntrinsicLaneMaskAnalyzer(MachineFunction &MF)
   initLaneMaskIntrinsics(MF);
 }
 
-bool IntrinsicLaneMaskAnalyzer::isS32S64LaneMask(Register Reg) const {
-  return S32S64LaneMask.contains(Reg);
+bool IntrinsicLaneMaskAnalyzer::isLaneMask(Register Reg) const {
+  return LaneMask.contains(Reg);
 }
 
 void IntrinsicLaneMaskAnalyzer::initLaneMaskIntrinsics(MachineFunction &MF) {
@@ -92,13 +92,13 @@ void IntrinsicLaneMaskAnalyzer::initLaneMaskIntrinsics(MachineFunction &MF) {
     for (auto &MI : MBB) {
       GIntrinsic *GI = dyn_cast<GIntrinsic>(&MI);
       if (GI && GI->is(Intrinsic::amdgcn_if_break)) {
-        S32S64LaneMask.insert(MI.getOperand(3).getReg());
-        S32S64LaneMask.insert(MI.getOperand(0).getReg());
+        LaneMask.insert(MI.getOperand(3).getReg());
+        LaneMask.insert(MI.getOperand(0).getReg());
       }
 
       if (MI.getOpcode() == AMDGPU::SI_IF ||
           MI.getOpcode() == AMDGPU::SI_ELSE) {
-        S32S64LaneMask.insert(MI.getOperand(0).getReg());
+        LaneMask.insert(MI.getOperand(0).getReg());
       }
     }
   }
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUGlobalISelUtils.h b/llvm/lib/Target/AMDGPU/AMDGPUGlobalISelUtils.h
index 5e1000ee0ab26..40e7be7f7bbd7 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUGlobalISelUtils.h
+++ b/llvm/lib/Target/AMDGPU/AMDGPUGlobalISelUtils.h
@@ -31,19 +31,17 @@ getBaseWithConstantOffset(MachineRegisterInfo &MRI, Register Reg,
                           GISelValueTracking *ValueTracking = nullptr,
                           bool CheckNUW = false);
 
-// Currently finds S32/S64 lane masks that can be declared as divergent by
-// uniformity analysis (all are phis at the moment).
-// These are defined as i32/i64 in some IR intrinsics (not as i1).
-// Tablegen forces(via telling that lane mask IR intrinsics are uniform) most of
-// S32/S64 lane masks to be uniform, as this results in them ending up with sgpr
-// reg class after instruction-select, don't search for all of them.
+// Finds lane masks produced/consumed by the control flow intrinsics. These are
+// i1 values that live in wave-width lane mask registers (SReg_1). They are used
+// to assign such values to the Vcc (lane mask) register bank so that they
+// select to a wave mask register class.
 class IntrinsicLaneMaskAnalyzer {
-  SmallDenseSet<Register, 8> S32S64LaneMask;
+  SmallDenseSet<Register, 8> LaneMask;
   MachineRegisterInfo &MRI;
 
 public:
   IntrinsicLaneMaskAnalyzer(MachineFunction &MF);
-  bool isS32S64LaneMask(Register Reg) const;
+  bool isLaneMask(Register Reg) const;
 
 private:
   void initLaneMaskIntrinsics(MachineFunction &MF);
diff --git a/llvm/lib/Target/AMDGPU/AMDGPURegBankLegalizeRules.cpp b/llvm/lib/Target/AMDGPU/AMDGPURegBankLegalizeRules.cpp
index 7f7225ad6d311..acc71206e8cd3 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPURegBankLegalizeRules.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPURegBankLegalizeRules.cpp
@@ -1875,14 +1875,13 @@ RegBankLegalizeRules::RegBankLegalizeRules(const GCNSubtarget &_ST,
       .Any({{UniS1, _, S64}, {{UniInVcc}, {IntrId, Vgpr64, Vgpr32}}})
       .Any({{DivS1, _, S64}, {{Vcc}, {IntrId, Vgpr64, Vgpr32}}});
 
-  // This is "intrinsic lane mask" it was set to i32/i64 in llvm-ir.
-  addRulesForIOpcs({amdgcn_end_cf})
-      .Any({{_, UniS32}, {{}, {IntrId, Sgpr32}}})
-      .Any({{_, UniS64}, {{}, {IntrId, Sgpr64}}});
-
-  addRulesForIOpcs({amdgcn_if_break}, Standard)
-      .Uni(S64, {{Sgpr64}, {IntrId, Vcc, Sgpr64}})
-      .Uni(S32, {{Sgpr32}, {IntrId, Vcc, Sgpr32}});
+  // The "intrinsic lane mask" is a divergent i1 value living in a wave-width
+  // lane mask register (the Vcc bank / SReg_1). Modeling it as a divergent i1
+  // lets the existing divergent-i1-phi lowering thread the "phi.broken" mask
+  // through loops as a lane mask.
+  addRulesForIOpcs({amdgcn_end_cf}).Any({{_, S1}, {{}, {IntrId, Vcc}}});
+
+  addRulesForIOpcs({amdgcn_if_break}).Any({{S1}, {{Vcc}, {IntrId, Vcc, Vcc}}});
 
   addRulesForIOpcs({amdgcn_exp})
       .Any({{_, _, _, S32, S32, S32, S32},
diff --git a/llvm/lib/Target/AMDGPU/AMDGPURegBankSelect.cpp b/llvm/lib/Target/AMDGPU/AMDGPURegBankSelect.cpp
index 247522a0dd43b..dc6bfa9e83bda 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPURegBankSelect.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPURegBankSelect.cpp
@@ -110,8 +110,13 @@ class RegBankSelectHelper {
   }
 
   const RegisterBank *getRegBankToAssign(Register Reg) {
+    // An "intrinsic lane mask" is an s1 value that lives in a wave-width lane
+    // mask register. Assign it to the Vcc (lane mask) bank rather than a scalar
+    // sgpr boolean so that it selects to a wave mask register class.
+    if (ILMA.isLaneMask(Reg) && MRI.getType(Reg) == LLT::scalar(1))
+      return VccRB;
     if (!isTemporalDivergenceCopy(Reg) &&
-        (MUI.isUniformAtDef(Reg) || ILMA.isS32S64LaneMask(Reg)))
+        (MUI.isUniformAtDef(Reg) || ILMA.isLaneMask(Reg)))
       return SgprRB;
     if (MRI.getType(Reg) == LLT::scalar(1))
       return VccRB;
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUSearchableTables.td b/llvm/lib/Target/AMDGPU/AMDGPUSearchableTables.td
index 2f7f72bd58f0e..df8a56ef51ead 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUSearchableTables.td
+++ b/llvm/lib/Target/AMDGPU/AMDGPUSearchableTables.td
@@ -376,6 +376,10 @@ def : SourceOfDivergence<int_amdgcn_ds_read_tr16_b64>;
 def : SourceOfDivergence<int_amdgcn_if>;
 def : SourceOfDivergence<int_amdgcn_else>;
 def : SourceOfDivergence<int_amdgcn_loop>;
+// The "intrinsic lane mask" result is an i1 value that lives in a wave-width
+// lane mask register (SReg_1), i.e. a divergent i1 from the analysis's point of
+// view. This lets the forwarding phis be treated as lane masks.
+def : SourceOfDivergence<int_amdgcn_if_break>;
 def : SourceOfDivergence<int_amdgcn_inverse_ballot>;
 
 foreach intr = AMDGPUImageDimAtomicIntrinsics in
@@ -401,7 +405,6 @@ def : AlwaysUniform<int_amdgcn_readlane>;
 def : AlwaysUniform<int_amdgcn_icmp>;
 def : AlwaysUniform<int_amdgcn_fcmp>;
 def : AlwaysUniform<int_amdgcn_ballot>;
-def : AlwaysUniform<int_amdgcn_if_break>;
 def : AlwaysUniform<int_amdgcn_cluster_workgroup_id_x>;
 def : AlwaysUniform<int_amdgcn_cluster_workgroup_id_y>;
 def : AlwaysUniform<int_amdgcn_cluster_workgroup_id_z>;
diff --git a/llvm/lib/Target/AMDGPU/SIAnnotateControlFlow.cpp b/llvm/lib/Target/AMDGPU/SIAnnotateControlFlow.cpp
index a7f98e79ce61d..09578918def17 100644
--- a/llvm/lib/Target/AMDGPU/SIAnnotateControlFlow.cpp
+++ b/llvm/lib/Target/AMDGPU/SIAnnotateControlFlow.cpp
@@ -45,13 +45,10 @@ class SIAnnotateControlFlow {
 
   Type *Boolean;
   Type *Void;
-  Type *IntMask;
-  Type *ReturnStruct;
 
   ConstantInt *BoolTrue;
   ConstantInt *BoolFalse;
   PoisonValue *BoolPoison;
-  Constant *IntMaskZero;
 
   Function *If = nullptr;
   Function *Else = nullptr;
@@ -115,14 +112,10 @@ void SIAnnotateControlFlow::initialize(const GCNSubtarget &ST) {
 
   Void = Type::getVoidTy(Context);
   Boolean = Type::getInt1Ty(Context);
-  IntMask = ST.isWave32() ? Type::getInt32Ty(Context)
-                           : Type::getInt64Ty(Context);
-  ReturnStruct = StructType::get(Boolean, IntMask);
 
   BoolTrue = ConstantInt::getTrue(Context);
   BoolFalse = ConstantInt::getFalse(Context);
   BoolPoison = PoisonValue::get(Boolean);
-  IntMaskZero = ConstantInt::get(IntMask, 0);
 }
 
 /// Is the branch condition uniform or did the StructurizeCFG pass
@@ -188,7 +181,7 @@ bool SIAnnotateControlFlow::openIf(CondBrInst *Term) {
     return false;
 
   IRBuilder<> IRB(Term);
-  Value *IfCall = IRB.CreateCall(getDecl(If, Intrinsic::amdgcn_if, IntMask),
+  Value *IfCall = IRB.CreateCall(getDecl(If, Intrinsic::amdgcn_if, {}),
                                  {Term->getCondition()});
   Value *Cond = IRB.CreateExtractValue(IfCall, {0});
   Value *Mask = IRB.CreateExtractValue(IfCall, {1});
@@ -204,8 +197,8 @@ bool SIAnnotateControlFlow::insertElse(CondBrInst *Term) {
   }
 
   IRBuilder<> IRB(Term);
-  Value *ElseCall = IRB.CreateCall(
-      getDecl(Else, Intrinsic::amdgcn_else, {IntMask, IntMask}), {popSaved()});
+  Value *ElseCall =
+      IRB.CreateCall(getDecl(Else, Intrinsic::amdgcn_else, {}), {popSaved()});
   Value *Cond = IRB.CreateExtractValue(ElseCall, {0});
   Value *Mask = IRB.CreateExtractValue(ElseCall, {1});
   Term->setCondition(Cond);
@@ -220,7 +213,7 @@ Value *SIAnnotateControlFlow::handleLoopCondition(Value *Cond, PHINode *Broken,
 
   auto CreateBreak = [this, Cond, Broken](Instruction *I) -> CallInst * {
     return IRBuilder<>(I).CreateCall(
-        getDecl(IfBreak, Intrinsic::amdgcn_if_break, IntMask), {Cond, Broken});
+        getDecl(IfBreak, Intrinsic::amdgcn_if_break, {}), {Cond, Broken});
   };
 
   if (Instruction *Inst = dyn_cast<Instruction>(Cond)) {
@@ -267,7 +260,7 @@ bool SIAnnotateControlFlow::handleLoop(CondBrInst *Term) {
     return false;
 
   BasicBlock *Target = Term->getSuccessor(1);
-  PHINode *Broken = PHINode::Create(IntMask, 0, "phi.broken");
+  PHINode *Broken = PHINode::Create(Boolean, 0, "phi.broken");
   Broken->insertBefore(Target->begin());
 
   Value *Cond = Term->getCondition();
@@ -275,7 +268,7 @@ bool SIAnnotateControlFlow::handleLoop(CondBrInst *Term) {
   Value *Arg = handleLoopCondition(Cond, Broken, L, Term);
 
   for (BasicBlock *Pred : predecessors(Target)) {
-    Value *PHIValue = IntMaskZero;
+    Value *PHIValue = BoolFalse;
     if (Pred == BB) // Remember the value of the previous iteration.
       PHIValue = Arg;
     // If the backedge from Pred to Target could be executed before the exit
@@ -287,7 +280,7 @@ bool SIAnnotateControlFlow::handleLoop(CondBrInst *Term) {
   }
 
   CallInst *LoopCall = IRBuilder<>(Term).CreateCall(
-      getDecl(Loop, Intrinsic::amdgcn_loop, IntMask), {Arg});
+      getDecl(Loop, Intrinsic::amdgcn_loop, {}), {Arg});
   Term->setCondition(LoopCall);
 
   push(Term->getSuccessor(0), Arg);
@@ -332,7 +325,7 @@ bool SIAnnotateControlFlow::closeControlFlow(BasicBlock *BB) {
     // condition, for now just avoid copying these DebugLocs so that stepping
     // out of the then/else block in a debugger doesn't step to the condition.
     IRB.SetCurrentDebugLocation(DebugLoc());
-    IRB.CreateCall(getDecl(EndCf, Intrinsic::amdgcn_end_cf, IntMask), {Exec});
+    IRB.CreateCall(getDecl(EndCf, Intrinsic::amdgcn_end_cf, {}), {Exec});
   }
 
   return true;
diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
index 9cf33b4ccbb87..e11d321bd83b3 100644
--- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
@@ -20648,8 +20648,8 @@ static bool hasCFUser(const Value *V, SmallPtrSet<const Value *, 16> &Visited,
   // FIXME: We assume we never cast the mask results of a control flow
   // intrinsic.
   // Early exit if the type won't be consistent as a compile time hack.
-  IntegerType *IT = dyn_cast<IntegerType>(V->getType());
-  if (!IT || IT->getBitWidth() != WaveSize)
+  // The mask results of the control flow intrinsics are i1 lane masks.
+  if (!V->getType()->isIntegerTy(1))
     return false;
 
   if (!isa<Instruction>(V))
diff --git a/llvm/test/Analysis/UniformityAnalysis/AMDGPU/control-flow-intrinsics.ll b/llvm/test/Analysis/UniformityAnalysis/AMDGPU/control-flow-intrinsics.ll
index b92daa64040e4..a3c3b5f544ad6 100644
--- a/llvm/test/Analysis/UniformityAnalysis/AMDGPU/control-flow-intrinsics.ll
+++ b/llvm/test/Analysis/UniformityAnalysis/AMDGPU/control-flow-intrinsics.ll
@@ -1,102 +1,102 @@
 ; RUN: opt -mtriple amdgcn-mesa-mesa3d -passes='print<uniformity>' -disable-output %s 2>&1 | FileCheck %s
 
-; Tests control flow intrinsics that should be treated as uniform
+; Tests uniformity of the AMDGPU control flow intrinsics. Their lane-mask
+; operands and results are i1 values that are divergent (per-lane).
 
 ; CHECK: for function 'test_if_break':
 ; CHECK: DIVERGENT: %cond = icmp eq i32 %arg0, 0
-; CHECK-NOT: DIVERGENT
-; CHECK: ret void
-define amdgpu_ps void @test_if_break(i32 %arg0, i64 inreg %saved) {
+; CHECK: DIVERGENT: %break = call i1 @llvm.amdgcn.if.break(i1 %cond, i1 %saved)
+define amdgpu_ps void @test_if_break(i32 %arg0, i1 inreg %saved) {
 entry:
   %cond = icmp eq i32 %arg0, 0
-  %break = call i64 @llvm.amdgcn.if.break.i64.i64(i1 %cond, i64 %saved)
-  store volatile i64 %break, ptr addrspace(1) undef
+  %break = call i1 @llvm.amdgcn.if.break(i1 %cond, i1 %saved)
+  store volatile i1 %break, ptr addrspace(1) undef
   ret void
 }
 
 ; CHECK: for function 'test_if':
 ; CHECK: DIVERGENT: %cond = icmp eq i32 %arg0, 0
-; CHECK-NEXT: DIVERGENT: %if = call { i1, i64 } @llvm.amdgcn.if.i64(i1 %cond)
-; CHECK-NEXT: DIVERGENT: %if.bool = extractvalue { i1, i64 } %if, 0
+; CHECK-NEXT: DIVERGENT: %if = call { i1, i1 } @llvm.amdgcn.if(i1 %cond)
+; CHECK-NEXT: DIVERGENT: %if.bool = extractvalue { i1, i1 } %if, 0
 ; CHECK-NOT: DIVERGENT
 ; CHECK: DIVERGENT: %if.bool.ext = zext i1 %if.bool to i32
 define void @test_if(i32 %arg0) {
 entry:
   %cond = icmp eq i32 %arg0, 0
-  %if = call { i1, i64 } @llvm.amdgcn.if.i64(i1 %cond)
-  %if.bool = extractvalue { i1, i64 } %if, 0
-  %if.mask = extractvalue { i1, i64 } %if, 1
+  %if = call { i1, i1 } @llvm.amdgcn.if(i1 %cond)
+  %if.bool = extractvalue { i1, i1 } %if, 0
+  %if.mask = extractvalue { i1, i1 } %if, 1
   %if.bool.ext = zext i1 %if.bool to i32
   store volatile i32 %if.bool.ext, ptr addrspace(1) undef
-  store volatile i64 %if.mask, ptr addrspace(1) undef
+  store volatile i1 %if.mask, ptr addrspace(1) undef
   ret void
 }
 
 ; The result should still be treated as divergent, even with a uniform source.
 ; CHECK: for function 'test_if_uniform':
 ; CHECK-NOT: DIVERGENT
-; CHECK: DIVERGENT: %if = call { i1, i64 } @llvm.amdgcn.if.i64(i1 %cond)
-; CHECK-NEXT: DIVERGENT: %if.bool = extractvalue { i1, i64 } %if, 0
+; CHECK: DIVERGENT: %if = call { i1, i1 } @llvm.amdgcn.if(i1 %cond)
+; CHECK-NEXT: DIVERGENT: %if.bool = extractvalue { i1, i1 } %if, 0
 ; CHECK-NOT: DIVERGENT
 ; CHECK: DIVERGENT: %if.bool.ext = zext i1 %if.bool to i32
 define amdgpu_ps void @test_if_uniform(i32 inreg %arg0) {
 entry:
   %cond = icmp eq i32 %arg0, 0
-  %if = call { i1, i64 } @llvm.amdgcn.if.i64(i1 %cond)
-  %if.bool = extractvalue { i1, i64 } %if, 0
-  %if.mask = extractvalue { i1, i64 } %if, 1
+  %if = call { i1, i1 } @llvm.amdgcn.if(i1 %cond)
+  %if.bool = extractvalue { i1, i1 } %if, 0
+  %if.mask = extractvalue { i1, i1 } %if, 1
   %if.bool.ext = zext i1 %if.bool to i32
   store volatile i32 %if.bool.ext, ptr addrspace(1) undef
-  store volatile i64 %if.mask, ptr addrspace(1) undef
+  store volatile i1 %if.mask, ptr addrspace(1) undef
   ret void
 }
 
 ; CHECK: for function 'test_loop_uniform':
-; CHECK: DIVERGENT: %loop = call i1 @llvm.amdgcn.loop.i64(i64 %mask)
-define amdgpu_ps void @test_loop_uniform(i64 inreg %mask) {
+; CHECK: DIVERGENT: %loop = call i1 @llvm.amdgcn.loop(i1 %mask)
+define amdgpu_ps void @test_loop_uniform(i1 inreg %mask) {
 entry:
-  %loop = call i1 @llvm.amdgcn.loop.i64(i64 %mask)
+  %loop = call i1 @llvm.amdgcn.loop(i1 %mask)
   %loop.ext = zext i1 %loop to i32
   store volatile i32 %loop.ext, ptr addrspace(1) undef
   ret void
 }
 
 ; CHECK: for function 'test_else':
-; CHECK: DIVERGENT: %else = call { i1, i64 } @llvm.amdgcn.else.i64.i64(i64 %mask)
-; CHECK: DIVERGENT:       %else.bool = extractvalue { i1, i64 } %else, 0
-; CHECK: {{^[ \t]+}}%else.mask = extractvalue { i1, i64 } %else, 1
-define amdgpu_ps void @test_else(i64 inreg %mask) {
+; CHECK: DIVERGENT: %else = call { i1, i1 } @llvm.amdgcn.else(i1 %mask)
+; CHECK: DIVERGENT:       %else.bool = extractvalue { i1, i1 } %else, 0
+; CHECK: {{^[ \t]+}}%else.mask = extractvalue { i1, i1 } %else, 1
+define amdgpu_ps void @test_else(i1 inreg %mask) {
 entry:
-  %else = call { i1, i64 } @llvm.amdgcn.else.i64.i64(i64 %mask)
-  %else.bool = extractvalue { i1, i64 } %else, 0
-  %else.mask = extractvalue { i1, i64 } %else, 1
+  %else = call { i1, i1 } @llvm.amdgcn.else(i1 %mask)
+  %else.bool = extractvalue { i1, i1 } %else, 0
+  %else.mask = extractvalue { i1, i1 } %else, 1
   %else.bool.ext = zext i1 %else.bool to i32
   store volatile i32 %else.bool.ext, ptr addrspace(1) undef
-  store volatile i64 %else.mask, ptr addrspace(1) undef
+  store volatile i1 %else.mask, ptr addrspace(1) undef
   ret void
 }
 
 ; This case is probably always broken
 ; CHECK: for function 'test_else_divergent_mask':
-; CHECK: DIVERGENT: %if = call { i1, i64 } @llvm.amdgcn.else.i64.i64(i64 %mask)
-; CHECK-NEXT: DIVERGENT: %if.bool = extractvalue { i1, i64 } %if, 0
+; CHECK: DIVERGENT: %if = call { i1, i1 } @llvm.amdgcn.else(i1 %mask)
+; CHECK-NEXT: DIVERGENT: %if.bool = extractvalue { i1, i1 } %if, 0
 ; CHECK-NOT: DIVERGENT
 ; CHECK: DIVERGENT: %if.bool.ext = zext i1 %if.bool to i32
-define void @test_else_divergent_mask(i64 %mask) {
+define void @test_else_divergent_mask(i1 %mask) {
 entry:
-  %if = call { i1, i64 } @llvm.amdgcn.else.i64.i64(i64 %mask)
-  %if.bool = extractvalue { i1, i64 } %if, 0
-  %if.mask = extractvalue { i1, i64 } %if, 1
+  %if = call { i1, i1 } @llvm.amdgcn.else(i1 %mask)
+  %if.bool = extractvalue { i1, i1 } %if, 0
+  %if.mask = extractvalue { i1, i1 } %if, 1
   %if.bool.ext = zext i1 %if.bool to i32
   store volatile i32 %if.bool.ext, ptr addrspace(1) undef
-  store volatile i64 %if.mask, ptr addrspace(1) undef
+  store volatile i1 %if.mask, ptr addrspace(1) undef
   ret void
 }
 
-declare { i1, i64 } @llvm.amdgcn.if.i64(i1) #0
-declare { i1, i64 } @llvm.amdgcn.else.i64.i64(i64) #0
-declare i64 @llvm.amdgcn.if.break.i64.i64(i1, i64) #1
-declare i1 @llvm.amdgcn.loop.i64(i64) #1
+declare { i1, i1 } @llvm.amdgcn.if(i1) #0
+declare { i1, i1 } @llvm.amdgcn.else(i1) #0
+declare i1 @llvm.amdgcn.if.break(i1, i1) #1
+declare i1 @llvm.amdgcn.loop(i1) #1
 
 attributes #0 = { convergent nounwind }
 attributes #1 = { convergent nounwind readnone }
diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/atomicrmw_fmax.ll b/llvm/test/CodeGen...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/209158


More information about the llvm-commits mailing list