Skip to content

Commit

Permalink
[OPT] Search whole BB for convergence token. (llvm#112728)
Browse files Browse the repository at this point in the history
The spec for llvm.experimental.convergence.entry says that is must be in
the entry block for a function, and must preceed any other convergent
operation. It does not have to be the first instruction in the entry
block.

Inlining assumes that the call to llvm.experimental.convergence.entry
will be the first instruction after any phi instructions. This commit
modifies inlining to search the entire block for the call.
  • Loading branch information
s-perron authored Oct 30, 2024
1 parent 4015e18 commit f405c68
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 17 deletions.
38 changes: 21 additions & 17 deletions llvm/lib/Transforms/Utils/InlineFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,21 @@ namespace {
}
}
};

} // end anonymous namespace

static IntrinsicInst *getConvergenceEntry(BasicBlock &BB) {
auto *I = BB.getFirstNonPHI();
while (I) {
if (auto *IntrinsicCall = dyn_cast<ConvergenceControlInst>(I)) {
if (IntrinsicCall->isEntry()) {
return IntrinsicCall;
}
}
I = I->getNextNode();
}
return nullptr;
}

/// Get or create a target for the branch from ResumeInsts.
BasicBlock *LandingPadInliningInfo::getInnerResumeDest() {
if (InnerResumeDest) return InnerResumeDest;
Expand Down Expand Up @@ -2496,15 +2508,10 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
// fully implements convergence control tokens, there is no mixing of
// controlled and uncontrolled convergent operations in the whole program.
if (CB.isConvergent()) {
auto *I = CalledFunc->getEntryBlock().getFirstNonPHI();
if (auto *IntrinsicCall = dyn_cast<IntrinsicInst>(I)) {
if (IntrinsicCall->getIntrinsicID() ==
Intrinsic::experimental_convergence_entry) {
if (!ConvergenceControlToken) {
return InlineResult::failure(
"convergent call needs convergencectrl operand");
}
}
if (!ConvergenceControlToken &&
getConvergenceEntry(CalledFunc->getEntryBlock())) {
return InlineResult::failure(
"convergent call needs convergencectrl operand");
}
}

Expand Down Expand Up @@ -2795,13 +2802,10 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
}

if (ConvergenceControlToken) {
auto *I = FirstNewBlock->getFirstNonPHI();
if (auto *IntrinsicCall = dyn_cast<IntrinsicInst>(I)) {
if (IntrinsicCall->getIntrinsicID() ==
Intrinsic::experimental_convergence_entry) {
IntrinsicCall->replaceAllUsesWith(ConvergenceControlToken);
IntrinsicCall->eraseFromParent();
}
IntrinsicInst *IntrinsicCall = getConvergenceEntry(*FirstNewBlock);
if (IntrinsicCall) {
IntrinsicCall->replaceAllUsesWith(ConvergenceControlToken);
IntrinsicCall->eraseFromParent();
}
}

Expand Down
24 changes: 24 additions & 0 deletions llvm/test/Transforms/Inline/convergence-inline.ll
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,30 @@ define void @test_two_calls() convergent {
ret void
}

define i32 @token_not_first(i32 %x) convergent alwaysinline {
; CHECK-LABEL: @token_not_first(
; CHECK-NEXT: {{%.*}} = alloca ptr, align 8
; CHECK-NEXT: [[TOKEN:%.*]] = call token @llvm.experimental.convergence.entry()
; CHECK-NEXT: [[Y:%.*]] = call i32 @g(i32 [[X:%.*]]) [ "convergencectrl"(token [[TOKEN]]) ]
; CHECK-NEXT: ret i32 [[Y]]
;
%p = alloca ptr, align 8
%token = call token @llvm.experimental.convergence.entry()
%y = call i32 @g(i32 %x) [ "convergencectrl"(token %token) ]
ret i32 %y
}

define void @test_token_not_first() convergent {
; CHECK-LABEL: @test_token_not_first(
; CHECK-NEXT: [[TOKEN:%.*]] = call token @llvm.experimental.convergence.entry()
; CHECK-NEXT: {{%.*}} = call i32 @g(i32 23) [ "convergencectrl"(token [[TOKEN]]) ]
; CHECK-NEXT: ret void
;
%token = call token @llvm.experimental.convergence.entry()
%x = call i32 @token_not_first(i32 23) [ "convergencectrl"(token %token) ]
ret void
}

declare void @f(i32) convergent
declare i32 @g(i32) convergent

Expand Down

0 comments on commit f405c68

Please sign in to comment.