[llvm] [GVNHoist] - Split Parent when profitable to do so. (PR #106842)

Pawan Nirpal via llvm-commits llvm-commits at lists.llvm.org
Sat Aug 31 03:31:46 PDT 2024


pawan-nirpal-031 wrote:

for the below input 

```
define dso_local void @B(i32 noundef %x, i32 noundef %y) local_unnamed_addr {
entry:
  switch i32 %x, label %sw.epilog [
    i32 1, label %sw.bb
    i32 2, label %sw.bb1
    i32 3, label %sw.bb2
    i32 4, label %sw.bb4
  ]

sw.bb:
  %sub = sub nsw i32 1, %y
  tail call void @foo(i32 noundef %sub) #2
  br label %sw.epilog

sw.bb1:
  %div = sdiv i32 2, %y
  tail call void @bar(i32 noundef %div) #2
  br label %sw.epilog

sw.bb2:
  %div3 = sdiv i32 2, %y
  tail call void @baz(i32 noundef %div3) #2
  br label %sw.epilog

sw.bb4:
  %div5 = sdiv i32 2, %y
  tail call void @bal(i32 noundef %div5) #2
  br label %sw.epilog

sw.epilog:
  ret void
}

declare void @foo(i32 noundef) local_unnamed_addr #1

declare void @bar(i32 noundef) local_unnamed_addr #1

declare void @baz(i32 noundef) local_unnamed_addr #1

declare void @bal(i32 noundef) local_unnamed_addr #1

```

it generates ```hoist.block``` out of place, it does not look at the right place control flow wise. 

```
define dso_local void @B(i32 noundef %x, i32 noundef %y) local_unnamed_addr {
entry:
  br label %hoist.block

sw.bb:                                            ; No predecessors!
  %sub = sub nsw i32 1, %y
  tail call void @foo(i32 noundef %sub)
  br label %sw.epilog

sw.bb1:                                           ; preds = %hoist.block
  %0 = phi i32 [ %3, %hoist.block ]
  %div = sdiv i32 2, %y
  tail call void @bar(i32 noundef %0)
  br label %sw.epilog

sw.bb2:                                           ; preds = %hoist.block
  %1 = phi i32 [ %3, %hoist.block ]
  %div3 = sdiv i32 2, %y
  tail call void @baz(i32 noundef %1)
  br label %sw.epilog

sw.bb4:                                           ; preds = %hoist.block
  %2 = phi i32 [ %3, %hoist.block ]
  %div5 = sdiv i32 2, %y
  tail call void @bal(i32 noundef %2)
  br label %sw.epilog

sw.epilog:                                        ; preds = %hoist.block, %sw.bb4, %sw.bb2, %sw.bb1, %sw.bb
  ret void

hoist.block:                                      ; preds = %entry
  %3 = sdiv i32 2, %y
  switch i32 %x, label %sw.epilog [
    i32 2, label %sw.bb1
    i32 3, label %sw.bb2
    i32 4, label %sw.bb4
  ]
}
```

and for a test like the one below 

```
define dso_local void @B(i32 noundef %x, i32 noundef %y) local_unnamed_addr {
entry:
  switch i32 %x, label %sw.epilog [
    i32 1, label %sw.bb
    i32 2, label %sw.bb1
    i32 3, label %sw.bb2
    i32 4, label %sw.bb4
  ]

sw.bb:
  %bb.sub = sub nsw i32 1, %y
  %bb.div = sdiv i32 2, %y
  %bb.add = add nsw i32 4, %y
  %bb.sub2 = sub nsw i32 3, %y
  tail call void @foo(i32 noundef %bb.sub) #2
  tail call void @foo(i32 noundef %bb.div) #2
  tail call void @foo(i32 noundef %bb.add) #2
  tail call void @foo(i32 noundef %bb.sub2) #2
  br label %sw.epilog

sw.bb1:
  %bb1.sub = sub nsw i32 1, %y
  %bb1.div = sdiv i32 2, %y
  %bb1.add = add nsw i32 4, %y
  %bb1.sub2 = sub nsw i32 3, %y
  tail call void @bar(i32 noundef %bb1.div) #2
  tail call void @bar(i32 noundef %bb1.add) #2
  tail call void @bar(i32 noundef %bb1.sub) #2
  tail call void @bar(i32 noundef %bb1.sub2) #2
  br label %sw.epilog

sw.bb2:
  %bb2.sub = sub nsw i32 1, %y
  %bb2.add = add nsw i32 4, %y
  %bb2.sub2 = sub nsw i32 3, %y
  tail call void @baz(i32 noundef %bb2.sub) #2
  tail call void @baz(i32 noundef %bb2.add) #2
  tail call void @baz(i32 noundef %bb2.sub2) #2
  br label %sw.epilog

sw.bb4:
  %bb4.sub = sub nsw i32 1, %y
  %bb4.div = sdiv i32 2, %y
  %bb4.sub2 = sub nsw i32 3, %y
  tail call void @bal(i32 noundef %bb4.sub) #2
  tail call void @bal(i32 noundef %bb4.div) #2
  tail call void @bal(i32 noundef %bb4.sub2) #2
  br label %sw.epilog

sw.epilog:
  ret void
}
```

it does weirder things, 3 same predecessors and out of control flow. 

```
define dso_local void @B(i32 noundef %x, i32 noundef %y) local_unnamed_addr {
entry:
  switch i32 %x, label %sw.epilog [
    i32 1, label %hoist.block
    i32 2, label %hoist.block
    i32 3, label %hoist.block
    i32 4, label %sw.bb4
  ]

sw.bb:                                            ; preds = %hoist.block
  %0 = phi i32 [ %11, %hoist.block ]
  %1 = phi i32 [ %10, %hoist.block ]
  %2 = phi i32 [ %9, %hoist.block ]
  %bb.div = sdiv i32 2, %y
  tail call void @foo(i32 noundef %2)
  tail call void @foo(i32 noundef %bb.div)
  tail call void @foo(i32 noundef %1)
  tail call void @foo(i32 noundef %0)
  br label %sw.epilog

sw.bb1:                                           ; preds = %hoist.block
  %3 = phi i32 [ %11, %hoist.block ]
  %4 = phi i32 [ %10, %hoist.block ]
  %5 = phi i32 [ %9, %hoist.block ]
  %bb1.div = sdiv i32 2, %y
  tail call void @bar(i32 noundef %bb1.div)
  tail call void @bar(i32 noundef %4)
  tail call void @bar(i32 noundef %5)
  tail call void @bar(i32 noundef %3)
  br label %sw.epilog

sw.bb2:                                           ; preds = %hoist.block
  %6 = phi i32 [ %11, %hoist.block ]
  %7 = phi i32 [ %10, %hoist.block ]
  %8 = phi i32 [ %9, %hoist.block ]
  tail call void @baz(i32 noundef %8)
  tail call void @baz(i32 noundef %7)
  tail call void @baz(i32 noundef %6)
  br label %sw.epilog

sw.bb4:                                           ; preds = %entry
  %bb4.sub = sub nsw i32 1, %y
  %bb4.div = sdiv i32 2, %y
  %bb4.sub2 = sub nsw i32 3, %y
  tail call void @bal(i32 noundef %bb4.sub)
  tail call void @bal(i32 noundef %bb4.div)
  tail call void @bal(i32 noundef %bb4.sub2)
  br label %sw.epilog

sw.epilog:                                        ; preds = %hoist.block, %sw.bb4, %sw.bb2, %sw.bb1, %sw.bb, %entry
  ret void

hoist.block:                                      ; preds = %entry, %entry, %entry
  %9 = sub nsw i32 1, %y
  %10 = add nsw i32 4, %y
  %11 = sub nsw i32 3, %y
  switch i32 %x, label %sw.epilog [
    i32 1, label %sw.bb
    i32 2, label %sw.bb1
    i32 3, label %sw.bb2
  ]
}
```

https://github.com/llvm/llvm-project/pull/106842


More information about the llvm-commits mailing list