[PATCH] D140974: [LICM][WIP] Transform and hoist select instructions if possible

luxufan via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 4 06:06:17 PST 2023


StephenFan created this revision.
StephenFan added reviewers: nikic, fhahn.
Herald added subscribers: asbirlea, hiraditya.
Herald added a project: All.
StephenFan requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Try to hoist select instruction that match the following and
%c and %cond are loop invariants:
Loop:

  %x = add i32 %y, %c
  %z = select i1 %cond, i32 %y, i32 %x

>
-

OutOfLoop:

  %a = select i1 %cond, i32 0, i32 %c
  ...

Loop:

  %z = add i32 %y, %a

TBH, I want to optimize the program:

  define dso_local i32 @test(i32 noundef %x) local_unnamed_addr #0 {
  entry:
    br label %for.cond
  
  for.cond:                                         ; preds = %for.inc, %entry
    %y.0 = phi i32 [ 0, %entry ], [ %y.1, %for.inc ]
    %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
    %cmp = icmp ult i32 %i.0, 1000
    br i1 %cmp, label %for.body, label %for.cond.cleanup
  
  for.cond.cleanup:                                 ; preds = %for.cond
    ret i32 %y.0
  
  for.body:                                         ; preds = %for.cond
    %tobool.not = icmp eq i32 %x, 0
    br i1 %tobool.not, label %for.inc, label %if.then
  
  if.then:                                          ; preds = %for.body
    %add = add nsw i32 %y.0, 10
    br label %for.inc
  
  for.inc:                                          ; preds = %for.body, %if.then
    %y.1 = phi i32 [ %add, %if.then ], [ %y.0, %for.body ]
    %inc = add nuw nsw i32 %i.0, 1
    br label %for.cond
  }

Idealy, it can be optimized to

  define dso_local i32 @test(i32 noundef %x) local_unnamed_addr #0 {
  entry:
    %tobool.not = icmp eq i32 %x, 0
    %0 = select i1 %tobool.not, i32 0, i32 10000
    ret i32 %0
  }

But SimplifyCFG transforms `for.body` and `if.then` to a select instruction. Which is:

  define dso_local i32 @test(i32 noundef %x) local_unnamed_addr {
  entry:
    br label %for.cond
  
  for.cond:                                         ; preds = %for.body, %entry
    %y.0 = phi i32 [ 0, %entry ], [ %spec.select, %for.body ]
    %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
    %cmp = icmp ult i32 %i.0, 1000
    br i1 %cmp, label %for.body, label %for.cond.cleanup
  
  for.cond.cleanup:                                 ; preds = %for.cond
    ret i32 %y.0
  
  for.body:                                         ; preds = %for.cond
    %tobool.not = icmp eq i32 %x, 0
    %add = add nsw i32 %y.0, 10
    %spec.select = select i1 %tobool.not, i32 %y.0, i32 %add
    %inc = add nuw nsw i32 %i.0, 1
    br label %for.cond
  }

This prevents it from being loop unswitched. In order to get the expected result, this patch hoisted the select instruction, so that indvars pass can rewrite the exit value.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D140974

Files:
  llvm/lib/Transforms/Scalar/LICM.cpp
  llvm/test/Transforms/LICM/select.ll

-------------- next part --------------
A non-text attachment was scrubbed...
Name: D140974.486254.patch
Type: text/x-patch
Size: 8390 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20230104/5f7742aa/attachment.bin>


More information about the llvm-commits mailing list