[all-commits] [llvm/llvm-project] 6b9952: [SimplifyCFG] Simplify switch instruction that has...
Michael Maitland via All-commits
all-commits at lists.llvm.org
Fri Nov 15 06:38:55 PST 2024
Branch: refs/heads/main
Home: https://github.com/llvm/llvm-project
Commit: 6b9952759f66c8bc62ef4c6700f586053f009296
https://github.com/llvm/llvm-project/commit/6b9952759f66c8bc62ef4c6700f586053f009296
Author: Michael Maitland <michaeltmaitland at gmail.com>
Date: 2024-11-15 (Fri, 15 Nov 2024)
Changed paths:
M llvm/lib/Transforms/Utils/SimplifyCFG.cpp
M llvm/test/Transforms/PhaseOrdering/switch-sext.ll
M llvm/test/Transforms/SimplifyCFG/ForwardSwitchConditionToPHI.ll
M llvm/test/Transforms/SimplifyCFG/HoistCode.ll
A llvm/test/Transforms/SimplifyCFG/switch-dup-bbs.ll
M llvm/test/Transforms/SimplifyCFG/switch-to-select-two-case.ll
Log Message:
-----------
[SimplifyCFG] Simplify switch instruction that has duplicate arms (#114262)
I noticed that the two C functions emitted different IR:
```
int switch_duplicate_arms(int switch_val, int v, int w) {
switch (switch_val) {
default:
break;
case 0:
w = v;
break;
case 1:
w = v;
break;
}
return w;
}
int if_duplicate_arms(int switch_val, int v, int w) {
if (switch_val == 0)
w = v;
else if (switch_val == 1)
w = v;
return v0;
}
```
We generate IR that looks like this:
```
define i32 @switch_duplicate_arms(i32 %0, i32 %1, i32 %2, i32 %3) {
switch i32 %1, label %7 [
i32 0, label %5
i32 1, label %6
]
5:
br label %7
6:
br label %7
7:
%8 = phi i32 [ %3, %4 ], [ %2, %6 ], [ %2, %5 ]
ret i32 %8
}
define i32 @if_duplicate_arms(i32 %0, i32 %1, i32 %2, i32 %3) {
%5 = icmp ult i32 %1, 2
%6 = select i1 %5, i32 %2, i32 %3
ret i32 %6
}
```
For `switch_duplicate_arms`, taking case 0 and 1 are the same since %5
and %6
branch to the same location and the incoming values for %8 are the same
from
those blocks. We could remove one on the duplicate switch targets and
update
the switch with the single target.
On RISC-V, prior to this patch, we generate the following code:
```
switch_duplicate_arms:
li a4, 1
beq a1, a4, .LBB0_2
mv a0, a3
bnez a1, .LBB0_3
.LBB0_2:
mv a0, a2
.LBB0_3:
ret
if_duplicate_arms:
li a4, 2
mv a0, a2
bltu a1, a4, .LBB1_2
mv a0, a3
.LBB1_2:
ret
```
After this patch, the O3 code is optimized to the icmp + select pair,
which
gives us the same code gen as `if_duplicate_arms`, as desired. This
results
is one less branch instruction in the final assembly.
This may help with both code size and further switch simplification. I
found
that this patch causes no significant impact to spec2006/int/ref and
spec2017/intrate/ref.
---------
Co-authored-by: Min Hsu <min at myhsu.dev>
To unsubscribe from these emails, change your notification settings at https://github.com/llvm/llvm-project/settings/notifications
More information about the All-commits
mailing list