Issue 102791
Summary IPSCCP causes redundant recalculation of function return value
Labels llvm:optimizations
Assignees
Reporter smeenai
    https://godbolt.org/z/7M1d9675c is a full demonstration. Consider this code:

```
struct S {
 S();
    int getI();
};

S &getS() {
    static S s;
 return s;
}

int getI() {
    return getS().getI();
}
```

The code generated for `getI` at `-Os` (for AArch64, but other architectures also reproduce this) is:

```
getI():
        stp     x29, x30, [sp, #-16]!
 mov     x29, sp
        bl      getS()
        adrp    x0, _ZZ4getSvE1s
        add     x0, x0, :lo12:_ZZ4getSvE1s
        ldp x29, x30, [sp], #16
        b       S::getI()
```

The `adrp` and `add` are completely redundant, because we're just recomputing the return value of `getS`, which was already in `x0` as well. We actually generate better code at `-O0`:

```
getI():
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      getS()
        bl S::getI()
        ldp     x29, x30, [sp], #16
 ret
```

The optimization pipeline viewers shows IPSCCP to be the culprit; it's replacing the use of `getS()`'s return value with what it knows that value will be:

```
  define dso_local noundef i32 @getI()() {
  entry:
    %call = call noundef nonnull align 1 dereferenceable(1) ptr @getS()()
-   %call1 = call noundef i32 @S::getI()(ptr noundef nonnull align 1 dereferenceable(1) %call)
+   %call1 = call noundef i32 @S::getI()(ptr noundef nonnull align 1 dereferenceable(1) @getS()::s)
 ret i32 %call1
  }
```

I can see this being profitable in some cases since it saves you from needing to preserve the return value, but in this case it's just adding two extra instructions for no gain. What's the best way to remedy this?
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to