diff --git a/llvm/lib/Transforms/Scalar/GVN.cpp b/llvm/lib/Transforms/Scalar/GVN.cpp --- a/llvm/lib/Transforms/Scalar/GVN.cpp +++ b/llvm/lib/Transforms/Scalar/GVN.cpp @@ -473,6 +473,14 @@ return nextValueNumber++; } + // Do not combine convergent calls since they implicitly depend on the set of + // threads that is currently executing, and they might be in different basic + // blocks. + if (C->isConvergent()) { + valueNumbering[C] = nextValueNumber; + return nextValueNumber++; + } + if (AA->doesNotAccessMemory(C)) { Expression exp = createExpr(C); uint32_t e = assignExpNewValueNum(exp).first; @@ -2781,9 +2789,6 @@ // We don't currently value number ANY inline asm calls. if (CallB->isInlineAsm()) return false; - // Don't do PRE on convergent calls. - if (CallB->isConvergent()) - return false; } uint32_t ValNo = VN.lookup(CurInst); diff --git a/llvm/lib/Transforms/Scalar/NewGVN.cpp b/llvm/lib/Transforms/Scalar/NewGVN.cpp --- a/llvm/lib/Transforms/Scalar/NewGVN.cpp +++ b/llvm/lib/Transforms/Scalar/NewGVN.cpp @@ -1613,6 +1613,12 @@ if (CI->getFunction()->isPresplitCoroutine()) return ExprResult::none(); + // Do not combine convergent calls since they implicitly depend on the set of + // threads that is currently executing, and they might be in different basic + // blocks. + if (CI->isConvergent()) + return ExprResult::none(); + if (AA->doesNotAccessMemory(CI)) { return ExprResult::some( createCallExpression(CI, TOPClass->getMemoryLeader())); diff --git a/llvm/test/Transforms/GVN/convergent.ll b/llvm/test/Transforms/GVN/convergent.ll --- a/llvm/test/Transforms/GVN/convergent.ll +++ b/llvm/test/Transforms/GVN/convergent.ll @@ -7,9 +7,11 @@ ; CHECK-NEXT: [[V0:%.*]] = call i32 @llvm.convergent() ; CHECK-NEXT: br i1 [[COND:%.*]], label [[BODY:%.*]], label [[END:%.*]] ; CHECK: body: +; CHECK-NEXT: [[V1:%.*]] = call i32 @llvm.convergent() ; CHECK-NEXT: br label [[END]] ; CHECK: end: -; CHECK-NEXT: ret i32 [[V0]] +; CHECK-NEXT: [[RET:%.*]] = phi i32 [ [[V0]], [[ENTRY:%.*]] ], [ [[V1]], [[BODY]] ] +; CHECK-NEXT: ret i32 [[RET]] ; entry: %v0 = call i32 @llvm.convergent() diff --git a/llvm/test/Transforms/NewGVN/convergent.ll b/llvm/test/Transforms/NewGVN/convergent.ll --- a/llvm/test/Transforms/NewGVN/convergent.ll +++ b/llvm/test/Transforms/NewGVN/convergent.ll @@ -7,9 +7,11 @@ ; CHECK-NEXT: [[V0:%.*]] = call i32 @llvm.convergent() ; CHECK-NEXT: br i1 [[COND:%.*]], label [[BODY:%.*]], label [[END:%.*]] ; CHECK: body: +; CHECK-NEXT: [[V1:%.*]] = call i32 @llvm.convergent() ; CHECK-NEXT: br label [[END]] ; CHECK: end: -; CHECK-NEXT: ret i32 [[V0]] +; CHECK-NEXT: [[RET:%.*]] = phi i32 [ [[V0]], [[ENTRY:%.*]] ], [ [[V1]], [[BODY]] ] +; CHECK-NEXT: ret i32 [[RET]] ; entry: %v0 = call i32 @llvm.convergent()