[all-commits] [llvm/llvm-project] c62e2a: StructurizeCFG: Optimize phi insertion during ssa ...
Ruiling, Song via All-commits
all-commits at lists.llvm.org
Wed Aug 7 23:48:10 PDT 2024
Branch: refs/heads/main
Home: https://github.com/llvm/llvm-project
Commit: c62e2a2a4ed69d53a3c6ca5c24ee8d2504d6ba2b
https://github.com/llvm/llvm-project/commit/c62e2a2a4ed69d53a3c6ca5c24ee8d2504d6ba2b
Author: Ruiling, Song <ruiling.song at amd.com>
Date: 2024-08-08 (Thu, 08 Aug 2024)
Changed paths:
M llvm/lib/Transforms/Scalar/StructurizeCFG.cpp
M llvm/test/CodeGen/AMDGPU/agpr-copy-no-free-registers.ll
M llvm/test/CodeGen/AMDGPU/while-break.ll
M llvm/test/Transforms/StructurizeCFG/AMDGPU/loop-subregion-misordered.ll
M llvm/test/Transforms/StructurizeCFG/loop-break-phi.ll
Log Message:
-----------
StructurizeCFG: Optimize phi insertion during ssa reconstruction (#101301)
After investigating more while-break cases, I think we should try to
optimize
the way we reconstruct phi nodes. Previously, we reconstruct each phi
nodes separately, but this is not optimal. For example:
```
header:
%v.1 = phi float [ %v, %entry ], [ %v.2, %latch ]
br i1 %cc, label %if, label %latch
if:
%v.if = fadd float %v.1, 1.0
br i1 %cc2, label %latch, label %exit
latch:
%v.2 = phi float [ %v.if, %if ], [ %v.1, %header ]
br i1 %cc3, label %exit, label %header
exit:
%v.3 = phi float [ %v.2, %latch ], [ %v.if, %if ]
```
For this case, we have different copies of value `v`, but there is at
most one copy of value `v` alive at any program point shown above.
The existing ssa reconstruction will use the incoming values from the
old deleted phi. Below is a possible output after ssa reconstruction.
```
header:
%v.1 = phi float [ %v, %entry ], [ %v.loop, %Flow1 ]
br i1 %cc, label %if, label %flow
if:
%v.if = fadd float %v.1, 1.0
br label %flow
flow:
%v.exit.if = phi float [ %v.if, %if ], [ undef, %header ]
%v.latch = phi float [ %v.if, %if ], [ %v.1, %header ]
latch:
br label %flow1
flow1:
%v.loop = phi float [ %v.latch, %latch ], [ undef, %Flow ]
%v.exit = phi float [ %v.latch, %latch ], [ %v.exit.if, %Flow ]
exit:
%v.3 = phi float [ %v.exit, %flow1 ]
```
If we look closely, in order to reconstruct `v.1` `v.2` `v.3`, we are
having two simultaneous copies of `v` alive at `flow` and `flow1`.
We highly depend on register coalescer to coalesce them together.
But register coalescer may not always be able to coalesce them
because of the complexity in the chain of phi.
On the other side, now that we have only one copy of `v` alive at any
program point before the transform, why not simplify the phi network
as much as we can? Look at the incoming values of these PHIs:
```
header if latch
v.1: -- -- v.2
v.2: v.1 v.if --
v.3: -- v.if v.2
```
If we let them share the same incoming values for these three different
incoming blocks, then we would have only one copy of alive `v` at any
program point after ssa reconstruction. Something like:
```
header:
%v.1 = phi float [ %v, %entry ], [ %v.2, %Flow1 ]
br i1 %cc, label %if, label %flow
if:
%v.if = fadd float %v.1, 1.0
br label %flow
flow:
%v.2 = phi float [ %v.if, %if ], [ %v.1, %header ]
latch:
br label %flow1
flow1:
...
exit:
%v.3 = phi float [ %v.2, %flow1 ]
```
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