diff --git a/llvm/lib/Transforms/Scalar/GVN.cpp b/llvm/lib/Transforms/Scalar/GVN.cpp index 3e30f15827158..9350b251e5a64 100644 --- a/llvm/lib/Transforms/Scalar/GVN.cpp +++ b/llvm/lib/Transforms/Scalar/GVN.cpp @@ -473,6 +473,14 @@ uint32_t GVNPass::ValueTable::lookupOrAddCall(CallInst *C) { 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 @@ bool GVNPass::performScalarPRE(Instruction *CurInst) { // 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 index 0647963e2d5a6..3de55759ed3a0 100644 --- a/llvm/lib/Transforms/Scalar/NewGVN.cpp +++ b/llvm/lib/Transforms/Scalar/NewGVN.cpp @@ -1613,6 +1613,12 @@ NewGVN::ExprResult NewGVN::performSymbolicCallEvaluation(Instruction *I) const { 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 index e44e77c59f958..80781bc4927da 100644 --- a/llvm/test/Transforms/GVN/convergent.ll +++ b/llvm/test/Transforms/GVN/convergent.ll @@ -7,9 +7,11 @@ define i32 @foo(i1 %cond) { ; 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 index c087e86d6115a..eceb071badcb0 100644 --- a/llvm/test/Transforms/NewGVN/convergent.ll +++ b/llvm/test/Transforms/NewGVN/convergent.ll @@ -7,9 +7,11 @@ define i32 @foo(i1 %cond) { ; 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()