[PATCH] D135463: [FuncSpec] Do not generate multiple copies for identical specializations.

Momchil Velikov via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 10 03:47:31 PDT 2022


chill added inline comments.


================
Comment at: llvm/lib/Transforms/IPO/FunctionSpecialization.cpp:526
+      // Create a copy of the function if it doesn't already exist.
+      hash_code Key = hash_value((ArrayRef<ArgInfo>)Info.Args);
+      auto Pair = Clones.insert({Key, nullptr});
----------------
Avoid C-style casts. It should work as `hash_value(ArrayRef<ArgInfo>(Info.Args));`


================
Comment at: llvm/lib/Transforms/IPO/FunctionSpecialization.cpp:528
+      auto Pair = Clones.insert({Key, nullptr});
+      Function *&Clone = Pair.first->second;
+      if (Pair.second) {
----------------
This is not correct, if the hash values clash two different specialisation will be regarded as the same and one will be discarded.


================
Comment at: llvm/lib/Transforms/IPO/FunctionSpecialization.cpp:529
+      Function *&Clone = Pair.first->second;
+      if (Pair.second) {
+        ValueToValueMapTy Mappings;
----------------
Discarding duplicates should happen before we decide which of the possible specialisations to perform. For example, in `calculateGains` the `MaxClonedThreshold` limit is applied on a list, which potentially contains duplicates.



================
Comment at: llvm/lib/Transforms/IPO/FunctionSpecialization.cpp:534
+        // formal arguments of the specialization.
+        for (User *U : F->users())
+          if (auto CS = dyn_cast<CallBase>(U))
----------------
This looks like a big redundancy, we traverse all the call sites of `F` for each specialisation while all we need is traverse all the call sites of `F` once and redirect the call site to the correct specialisation.


================
Comment at: llvm/lib/Transforms/IPO/FunctionSpecialization.cpp:539
+                    unsigned ArgNo = Arg.Formal->getArgNo();
+                    return CS->getArgOperand(ArgNo) == Mappings[Arg.Formal];
+                }))
----------------
So the idea here is, when specializing on the second parameter only, to turn
```
void g(int x, int y) {
...
  g(x, y);
...
}
...
g(1, 2);
```
into

```
void g.1(int x, /* unused */ int y) {
...
  g.1(x, 2);
...
}
...
g.1(1, 2);
```
But the same ought to happen for:
```
void g(int x, int y) {
...
  g(x, 2);
...
}
...
g(1, 2);
```
and it looks to me the test will miss it because it will compare `2` (from the call argument) to `y` in the cloned function.

(Similar issue in the original code as well).


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D135463



More information about the llvm-commits mailing list