From: Matt Arsenault Date: Wed, 29 May 2019 13:14:39 +0000 (+0000) Subject: SpeculateAroundPHIs: Respect convergent X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f53b32d49ea9cc2c8dcdd087c6b89c9c54e363a8;p=llvm SpeculateAroundPHIs: Respect convergent git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@361957 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/Scalar/SpeculateAroundPHIs.cpp b/lib/Transforms/Scalar/SpeculateAroundPHIs.cpp index 51e97cf1c78..c13fb3e0451 100644 --- a/lib/Transforms/Scalar/SpeculateAroundPHIs.cpp +++ b/lib/Transforms/Scalar/SpeculateAroundPHIs.cpp @@ -67,6 +67,14 @@ isSafeToSpeculatePHIUsers(PHINode &PN, DominatorTree &DT, 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 diff --git a/test/Transforms/SpeculateAroundPHIs/convergent.ll b/test/Transforms/SpeculateAroundPHIs/convergent.ll new file mode 100644 index 00000000000..6c035b28447 --- /dev/null +++ b/test/Transforms/SpeculateAroundPHIs/convergent.ll @@ -0,0 +1,98 @@ +; 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 +declare i32 @llvm.regular(i32) #2 + +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 +} + +; Otherwise identical function which should be transformed. +define i32 @test_reference(i1 %flag, i32 %arg) #2 { +; CHECK-LABEL: @test_reference( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[A:%.*]], label [[B:%.*]] +; CHECK: a: +; CHECK-NEXT: [[SUM_0:%.*]] = call i32 @llvm.regular(i32 7) +; CHECK-NEXT: br label [[EXIT:%.*]] +; CHECK: b: +; CHECK-NEXT: [[SUM_1:%.*]] = call i32 @llvm.regular(i32 11) +; CHECK-NEXT: br label [[EXIT]] +; CHECK: exit: +; CHECK-NEXT: [[SUM_PHI:%.*]] = phi i32 [ [[SUM_0]], [[A]] ], [ [[SUM_1]], [[B]] ] +; CHECK-NEXT: ret i32 [[SUM_PHI]] +; +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.regular(i32 %p) + ret i32 %sum +} + + +attributes #0 = { nounwind readnone convergent speculatable } +attributes #1 = { nounwind readnone noduplicate speculatable } +attributes #2 = { nounwind readnone speculatable }