[PATCH] D99347: [AMDGPU] Set implicit arg attributes for indirect calls

Jon Chesterfield via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 25 10:48:26 PDT 2021


JonChesterfield added inline comments.


================
Comment at: llvm/lib/Target/AMDGPU/AMDGPUAnnotateKernelFeatures.cpp:275
+
+  // If this function hasAddressTaken() = true
+  // then add all attributes corresponding to the implicit args.
----------------
madhur13490 wrote:
> JonChesterfield wrote:
> > Is the reasoning here that an indirect call site to an unknown callee will have set up all the implicit state, so for consistency a function which is ever called indirectly must always have all the state set up?
> > 
> > I would have hoped the granularity is such that functions can be annotated with only what they need, so that indirect call sites pass (and require) everything but direct call sites don't need to. With consistent register location for implicit values, I would hope that will work out of the box.
> > Is the reasoning here that an indirect call site to an unknown callee will have set up all the implicit state, so for consistency a function which is ever called indirectly must always have all the state set up?
> 
> We are not setting up implicit attributes per call site. This pass works at function granularity and it does not take into account the call site. Implicit attributes are not a property of call site but  the functions themselves. If function's hasAddressTaken() is true, we set all attributes corresponding to the implicits.
> 
> 
> > I would have hoped the granularity is such that functions can be annotated with only what they need, so that indirect call sites pass (and require) everything but direct call sites don't need to. With consistent register location for implicit values, I would hope that will work out of the box.
> 
> That won't work out. You can't ask call site to pass all implicits when you setup only a subset of them. The arguments setup must be at superset of what is passed. We use attributes on the function (not call site) to setup implicits and thus pass this pass sets them up before we begin codegen so that codegen works out-of-the-box. So your comment - " that functions can be annotated with only what they need" is invalid.
> 
> 
> 
> 
Argument passing is per call site, derived from on the attributes of the function being called (or a pessimistic superset when the callee is uncertain). What you're doing here makes every call to a function slower, as opposed to only the indirect calls.

The attributes on a function should be derived from the attributes on the functions it calls, and whether any of those call sites is indirect, not based on whether the function itself is called indirectly.


================
Comment at: llvm/lib/Target/AMDGPU/AMDGPUAnnotateKernelFeatures.cpp:298
+          if (!CB->isInlineAsm()) {
+            HasIndirectCall = true;
             HaveCall = true;
----------------
madhur13490 wrote:
> JonChesterfield wrote:
> > As discussed, presence of inline asm does not need to be taken to imply presence of an indirect call within said asm. If someone wants to make an indirect branch from asm, it's on them to get it right. If someone wants to use asm without indirect branches, they won't want the extra overhead from conservatively setting up all the state.
> The code is setting the flag when there is *noinlineasm()*. If you set the flag even when there is inlineAsm() then all exisiting apps which are using inlieAsm() would be requesting more implicits than current ones. This is what we discussed and aligned internally.
I missed the `!`.


================
Comment at: llvm/lib/Target/AMDGPU/AMDGPUAnnotateKernelFeatures.cpp:382
+  //    essential for correctness).
+  if (CallingConvSupportsAllImplicits && HasIndirectCall) {
+    for (StringRef AttrName : ImplicitAttrNames) {
----------------
madhur13490 wrote:
> JonChesterfield wrote:
> > This doesn't make sense to me. 
> > 
> > An indirect call site implies all implicit args are needed, so the caller of that function will acquire those attributes. Then a direct call to said function will have those attributes, and so on.
> > 
> > hasAddressTaken on the kernel itself makes no difference here - is the comment out of date?
> I don't understand this comment. 
> 
> > This doesn't make sense to me. 
> > 
> > An indirect call site implies all implicit args are needed, so the caller of that function will acquire those attributes. Then a direct call to said function will have those attributes, and so on.
> 
> which function?
> 
> > 
> > hasAddressTaken on the kernel itself makes no difference here - is the comment out of date?
> 
> hasAddressTaken() on kernels makes difference because hasAddressTaken() for kernels is naturally false. How would set implicits then? This snippet is explicitly for functions which makes an indirect call and not for the address taken functions (that is handled at the beginning).
> 
> The comment is not out of date. Look at the test cases - simple-indirect-call.ll and direct-indirect-call.ll.
> 
> 
The function that was making an indirect call, and is itself being called directly.

The code makes approximate sense here but I can't relate it to the comment.

Approximate in that it should probably be:
```
if (hasIndirectCall) {
  for (auto AttrName : ImplicitAttrNames) {
    if (callingconv.supports(AttrName) {
      F.addFnAttr(AttrName);
      Changed = true;
    } else {
      // sometimes an error
    }
  }  
}
```

Could the comment be:
// An indirect call may use any implicit arguments. Conservatively ensure all are available.


================
Comment at: llvm/test/CodeGen/AMDGPU/simple-indirect-call.ll:4
+; GCN-LABEL: define internal void @indirect() #0 {
+define internal void @indirect() {
+    ret void
----------------
This doesn't seem right. The function 'indirect' uses no implicit arguments, it should have none of those attributes appended.


================
Comment at: llvm/test/CodeGen/AMDGPU/simple-indirect-call.ll:11
+    %fptr = alloca void()*
+    store void()* @indirect, void()** %fptr
+    %fp = load void()*, void()** %fptr
----------------
This (kernel) function should however be annotated with all the implicit arguments, as it contains an indirect call (that has not been devirtualized in this test)


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D99347/new/

https://reviews.llvm.org/D99347



More information about the llvm-commits mailing list