Skip to content

Commit ac328a9

Browse files
jayfoadPravin Jagtap
authored andcommitted
[GVN] Do not combine convergent calls in GVN/NewGVN
Note that this is very conservative since it will not even combine convergent calls that appear in the same basic block, but EarlyCSE will handle that case. Differential Revision: https://reviews.llvm.org/D150974 Change-Id: I3cad9a8750dc2d007e6e37ec4182e68d3fcd49a9
1 parent 3069f26 commit ac328a9

File tree

4 files changed

+85
-12
lines changed

4 files changed

+85
-12
lines changed

llvm/lib/Transforms/Scalar/GVN.cpp

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -461,15 +461,27 @@ void GVNPass::ValueTable::add(Value *V, uint32_t num) {
461461
}
462462

463463
uint32_t GVNPass::ValueTable::lookupOrAddCall(CallInst *C) {
464-
if (AA->doesNotAccessMemory(C) &&
465-
// FIXME: Currently the calls which may access the thread id may
466-
// be considered as not accessing the memory. But this is
467-
// problematic for coroutines, since coroutines may resume in a
468-
// different thread. So we disable the optimization here for the
469-
// correctness. However, it may block many other correct
470-
// optimizations. Revert this one when we detect the memory
471-
// accessing kind more precisely.
472-
!C->getFunction()->isPresplitCoroutine()) {
464+
// FIXME: Currently the calls which may access the thread id may
465+
// be considered as not accessing the memory. But this is
466+
// problematic for coroutines, since coroutines may resume in a
467+
// different thread. So we disable the optimization here for the
468+
// correctness. However, it may block many other correct
469+
// optimizations. Revert this one when we detect the memory
470+
// accessing kind more precisely.
471+
if (C->getFunction()->isPresplitCoroutine()) {
472+
valueNumbering[C] = nextValueNumber;
473+
return nextValueNumber++;
474+
}
475+
476+
// Do not combine convergent calls since they implicitly depend on the set of
477+
// threads that is currently executing, and they might be in different basic
478+
// blocks.
479+
if (C->isConvergent()) {
480+
valueNumbering[C] = nextValueNumber;
481+
return nextValueNumber++;
482+
}
483+
484+
if (AA->doesNotAccessMemory(C)) {
473485
Expression exp = createExpr(C);
474486
uint32_t e = assignExpNewValueNum(exp).first;
475487
valueNumbering[C] = e;
@@ -2768,9 +2780,6 @@ bool GVNPass::performScalarPRE(Instruction *CurInst) {
27682780
// We don't currently value number ANY inline asm calls.
27692781
if (CallB->isInlineAsm())
27702782
return false;
2771-
// Don't do PRE on convergent calls.
2772-
if (CallB->isConvergent())
2773-
return false;
27742783
}
27752784

27762785
uint32_t ValNo = VN.lookup(CurInst);

llvm/lib/Transforms/Scalar/NewGVN.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1617,6 +1617,12 @@ NewGVN::ExprResult NewGVN::performSymbolicCallEvaluation(Instruction *I) const {
16171617
if (CI->getFunction()->isPresplitCoroutine())
16181618
return ExprResult::none();
16191619

1620+
// Do not combine convergent calls since they implicitly depend on the set of
1621+
// threads that is currently executing, and they might be in different basic
1622+
// blocks.
1623+
if (CI->isConvergent())
1624+
return ExprResult::none();
1625+
16201626
if (AA->doesNotAccessMemory(CI)) {
16211627
return ExprResult::some(
16221628
createCallExpression(CI, TOPClass->getMemoryLeader()));
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2+
; RUN: opt -S -passes=gvn -o - %s | FileCheck %s
3+
4+
define i32 @foo(i1 %cond) {
5+
; CHECK-LABEL: @foo(
6+
; CHECK-NEXT: entry:
7+
; CHECK-NEXT: [[V0:%.*]] = call i32 @llvm.convergent()
8+
; CHECK-NEXT: br i1 [[COND:%.*]], label [[BODY:%.*]], label [[END:%.*]]
9+
; CHECK: body:
10+
; CHECK-NEXT: [[V1:%.*]] = call i32 @llvm.convergent()
11+
; CHECK-NEXT: br label [[END]]
12+
; CHECK: end:
13+
; CHECK-NEXT: [[RET:%.*]] = phi i32 [ [[V0]], [[ENTRY:%.*]] ], [ [[V1]], [[BODY]] ]
14+
; CHECK-NEXT: ret i32 [[RET]]
15+
;
16+
entry:
17+
%v0 = call i32 @llvm.convergent()
18+
br i1 %cond, label %body, label %end
19+
20+
body:
21+
%v1 = call i32 @llvm.convergent()
22+
br label %end
23+
24+
end:
25+
%ret = phi i32 [ %v0, %entry ], [ %v1, %body ]
26+
ret i32 %ret
27+
}
28+
29+
declare i32 @llvm.convergent() convergent nounwind readnone willreturn
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2+
; RUN: opt -S -passes=newgvn -o - %s | FileCheck %s
3+
4+
define i32 @foo(i1 %cond) {
5+
; CHECK-LABEL: @foo(
6+
; CHECK-NEXT: entry:
7+
; CHECK-NEXT: [[V0:%.*]] = call i32 @llvm.convergent()
8+
; CHECK-NEXT: br i1 [[COND:%.*]], label [[BODY:%.*]], label [[END:%.*]]
9+
; CHECK: body:
10+
; CHECK-NEXT: [[V1:%.*]] = call i32 @llvm.convergent()
11+
; CHECK-NEXT: br label [[END]]
12+
; CHECK: end:
13+
; CHECK-NEXT: [[RET:%.*]] = phi i32 [ [[V0]], [[ENTRY:%.*]] ], [ [[V1]], [[BODY]] ]
14+
; CHECK-NEXT: ret i32 [[RET]]
15+
;
16+
entry:
17+
%v0 = call i32 @llvm.convergent()
18+
br i1 %cond, label %body, label %end
19+
20+
body:
21+
%v1 = call i32 @llvm.convergent()
22+
br label %end
23+
24+
end:
25+
%ret = phi i32 [ %v0, %entry ], [ %v1, %body ]
26+
ret i32 %ret
27+
}
28+
29+
declare i32 @llvm.convergent() convergent nounwind readnone willreturn

0 commit comments

Comments
 (0)