[llvm] [AMDGPU][Attributor] Infer `inreg` attribute in `AMDGPUAttributor` (PR #101609)

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 24 06:12:01 PDT 2025


================
@@ -1363,6 +1490,59 @@ static bool updateWavesPerEU(Module &M, TargetMachine &TM) {
   return Changed;
 }
 
+/// Emit the readfirstlane intrinsic for all inreg uniform function arguments at
+/// each call site. The inreg uniform attribute combination is set by
+/// AAAMDGPUUniform. This function provides a workaround for a downstream issue
+/// where failing to emit a waterfall loop for 'inreg' arguments may result in
+/// an invalid VGPR-to-SGPR copy. However, we intentionally avoid a waterfall
+/// loop for inreg uniform arguments here, because the 'inreg' attribute set by
+/// AAAMDGPUUniform guarantees uniformity, making the readfirstlane intrinsic
+/// appropriate.
+static bool emitReadFirstLaneForInregUniformArgs(Module &M) {
+  std::vector<std::pair<CallBase *, unsigned>> WorkList;
+
+  for (Function &F : M) {
+    if (F.isDeclaration())
+      continue;
+    for (Argument &Arg : F.args()) {
+      if (!Arg.hasAttribute(Attribute::InReg) || !Arg.hasAttribute("uniform"))
+        continue;
+      unsigned ArgNo = Arg.getArgNo();
+      for (Use &U : F.uses()) {
+        auto *CB = dyn_cast<CallBase>(U.getUser());
+        if (!CB)
+          continue;
+        // We will skip the call site argument when itself is an inreg argument.
+        // In this case, it will already be in SGPR.
+        if (auto *CSArg = dyn_cast<Argument>(CB->getArgOperand(ArgNo))) {
+          if (CSArg->hasAttribute(Attribute::InReg))
+            continue;
+        }
+        WorkList.emplace_back(CB, ArgNo);
+      }
+      // We don't count this as changed since it just stays within this pass.
+      Arg.removeAttr("uniform");
+    }
+  }
+
+  if (WorkList.empty())
+    return false;
+
+  for (auto &[CB, ArgNo] : WorkList) {
+    Value *V = CB->getArgOperand(ArgNo);
+    IRBuilder<> Builder(CB);
+    Value *NewV = Builder.CreateIntrinsic(V->getType(),
+                                          Intrinsic::amdgcn_readfirstlane, {V});
+    CB->setArgOperand(ArgNo, NewV);
----------------
arsenm wrote:

Can you directly do this in the manifest of the attribute? Ideally this would only do this for cases where this pass introduced the inreg argument and leave existing cases alone 

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


More information about the llvm-commits mailing list