Index: lib/Transforms/Scalar/SpeculateAroundPHIs.cpp =================================================================== --- lib/Transforms/Scalar/SpeculateAroundPHIs.cpp +++ lib/Transforms/Scalar/SpeculateAroundPHIs.cpp @@ -67,6 +67,14 @@ return false; } + if (auto CS = ImmutableCallSite(UI)) { + if (CS.isConvergent() || CS.cannotDuplicate()) { + LLVM_DEBUG(dbgs() << " Unsafe: convergent " + "callsite cannot de duplicated: " << *UI << '\n'); + return false; + } + } + // FIXME: This check is much too conservative. We're not going to move these // instructions onto new dynamic paths through the program unless there is // a call instruction between the use and the PHI node. And memory isn't Index: test/Transforms/SpeculateAroundPHIs/convergent.ll =================================================================== --- /dev/null +++ test/Transforms/SpeculateAroundPHIs/convergent.ll @@ -0,0 +1,65 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -S -passes=spec-phis < %s | FileCheck %s +; Make sure convergent and noduplicate calls aren't duplicated. + +declare i32 @llvm.convergent(i32) #0 +declare i32 @llvm.noduplicate(i32) #1 + +define i32 @test_convergent(i1 %flag, i32 %arg) #0 { +; CHECK-LABEL: @test_convergent( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[A:%.*]], label [[B:%.*]] +; CHECK: a: +; CHECK-NEXT: br label [[EXIT:%.*]] +; CHECK: b: +; CHECK-NEXT: br label [[EXIT]] +; CHECK: exit: +; CHECK-NEXT: [[P:%.*]] = phi i32 [ 7, [[A]] ], [ 11, [[B]] ] +; CHECK-NEXT: [[SUM:%.*]] = call i32 @llvm.convergent(i32 [[P]]) +; CHECK-NEXT: ret i32 [[SUM]] +; +entry: + br i1 %flag, label %a, label %b + +a: + br label %exit + +b: + br label %exit + +exit: + %p = phi i32 [ 7, %a ], [ 11, %b ] + %sum = call i32 @llvm.convergent(i32 %p) + ret i32 %sum +} + +define i32 @test_noduplicate(i1 %flag, i32 %arg) #1 { +; CHECK-LABEL: @test_noduplicate( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[A:%.*]], label [[B:%.*]] +; CHECK: a: +; CHECK-NEXT: br label [[EXIT:%.*]] +; CHECK: b: +; CHECK-NEXT: br label [[EXIT]] +; CHECK: exit: +; CHECK-NEXT: [[P:%.*]] = phi i32 [ 7, [[A]] ], [ 11, [[B]] ] +; CHECK-NEXT: [[SUM:%.*]] = call i32 @llvm.noduplicate(i32 [[P]]) +; CHECK-NEXT: ret i32 [[SUM]] +; +entry: + br i1 %flag, label %a, label %b + +a: + br label %exit + +b: + br label %exit + +exit: + %p = phi i32 [ 7, %a ], [ 11, %b ] + %sum = call i32 @llvm.noduplicate(i32 %p) + ret i32 %sum +} + +attributes #0 = { nounwind readnone convergent speculatable } +attributes #1 = { nounwind readnone noduplicate speculatable }