Skip to content

Commit

Permalink
Teach LoopUnswitch not to perform non-trivial unswitching on loops co…
Browse files Browse the repository at this point in the history
…ntaining convergent operations.

Doing so could cause the post-unswitching convergent ops to be
control-dependent on the unswitch condition where they were not before.
This check could be refined to allow unswitching where the convergent
operation was already control-dependent on the unswitch condition.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@249874 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
resistor committed Oct 9, 2015
1 parent 9f41a7c commit 2f10e78
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 0 deletions.
14 changes: 14 additions & 0 deletions lib/Transforms/Scalar/LoopUnswitch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,20 @@ bool LoopUnswitch::processCurrentLoop() {
return true;
}

// Do not unswitch loops containing convergent operations, as we might be
// making them control dependent on the unswitch value when they were not
// before.
// FIXME: This could be refined to only bail if the convergent operation is
// not already control-dependent on the unswitch value.
for (const auto BB : currentLoop->blocks()) {
for (const auto &I : *BB) {
const auto CI = dyn_cast<CallInst>(&I);
if (!CI) continue;
if (CI->isConvergent())
return false;
}
}

// Do not do non-trivial unswitch while optimizing for size.
// FIXME: Use Function::optForSize().
if (OptimizeForSize ||
Expand Down
39 changes: 39 additions & 0 deletions test/Transforms/LoopUnswitch/basictest.ll
Original file line number Diff line number Diff line change
Expand Up @@ -64,5 +64,44 @@ loop_exit:
; CHECK: }
}

; This simple test would normally unswitch, but should be inhibited by the presence of
; the convergent call that is not control-dependent on the unswitch condition.

; CHECK-LABEL: @test3(
define i32 @test3(i32* %var) {
%mem = alloca i32
store i32 2, i32* %mem
%c = load i32, i32* %mem

br label %loop_begin

loop_begin:

%var_val = load i32, i32* %var

; CHECK: call void @conv()
; CHECK-NOT: call void @conv()
call void @conv() convergent

switch i32 %c, label %default [
i32 1, label %inc
i32 2, label %dec
]

inc:
call void @incf() noreturn nounwind
br label %loop_begin
dec:
call void @decf() noreturn nounwind
br label %loop_begin
default:
br label %loop_exit
loop_exit:
ret i32 0
; CHECK: }
}


declare void @incf() noreturn
declare void @decf() noreturn
declare void @conv() convergent

0 comments on commit 2f10e78

Please sign in to comment.