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