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.