
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.
218 lines
7.8 KiB
LLVM
218 lines
7.8 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt -passes='cgscc(inline)' -S %s | FileCheck %s
|
|
|
|
define void @nonconvergent_callee() alwaysinline {
|
|
; CHECK-LABEL: @nonconvergent_callee(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TOKEN:%.*]] = call token @llvm.experimental.convergence.anchor()
|
|
; CHECK-NEXT: call void @f(i32 0) [ "convergencectrl"(token [[TOKEN]]) ]
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%token = call token @llvm.experimental.convergence.anchor()
|
|
call void @f(i32 0) [ "convergencectrl"(token %token) ]
|
|
ret void
|
|
}
|
|
|
|
define void @convergent_callee(i32 %v) convergent alwaysinline {
|
|
; CHECK-LABEL: @convergent_callee(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TOKEN:%.*]] = call token @llvm.experimental.convergence.entry()
|
|
; CHECK-NEXT: call void @f(i32 [[V:%.*]]) [ "convergencectrl"(token [[TOKEN]]) ]
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%token = call token @llvm.experimental.convergence.entry()
|
|
call void @f(i32 %v) [ "convergencectrl"(token %token) ]
|
|
ret void
|
|
}
|
|
|
|
define void @test_nonconvergent() {
|
|
; CHECK-LABEL: @test_nonconvergent(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TOKEN_I:%.*]] = call token @llvm.experimental.convergence.anchor()
|
|
; CHECK-NEXT: call void @f(i32 0) [ "convergencectrl"(token [[TOKEN_I]]) ]
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
call void @nonconvergent_callee()
|
|
ret void
|
|
}
|
|
|
|
define void @test_convergent_basic(i1 %cond) {
|
|
; CHECK-LABEL: @test_convergent_basic(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TOKEN:%.*]] = call token @llvm.experimental.convergence.anchor()
|
|
; CHECK-NEXT: br i1 [[COND:%.*]], label [[THEN:%.*]], label [[END:%.*]]
|
|
; CHECK: then:
|
|
; CHECK-NEXT: call void @f(i32 0) [ "convergencectrl"(token [[TOKEN]]) ]
|
|
; CHECK-NEXT: br label [[END]]
|
|
; CHECK: end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%token = call token @llvm.experimental.convergence.anchor()
|
|
br i1 %cond, label %then, label %end
|
|
|
|
then:
|
|
call void @convergent_callee(i32 0) [ "convergencectrl"(token %token) ]
|
|
br label %end
|
|
|
|
end:
|
|
ret void
|
|
}
|
|
|
|
define void @test_convergent_no_token(i1 %cond) convergent {
|
|
; CHECK-LABEL: @test_convergent_no_token(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: call void @convergent_callee(i32 0)
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
call void @convergent_callee(i32 0)
|
|
ret void
|
|
}
|
|
|
|
define void @test_convergent_multiple() convergent {
|
|
; CHECK-LABEL: @test_convergent_multiple(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TOKEN:%.*]] = call token @llvm.experimental.convergence.entry()
|
|
; CHECK-NEXT: call void @f(i32 0) [ "convergencectrl"(token [[TOKEN]]) ]
|
|
; CHECK-NEXT: call void @f(i32 1) [ "convergencectrl"(token [[TOKEN]]) ]
|
|
; CHECK-NEXT: call void @f(i32 2) [ "convergencectrl"(token [[TOKEN]]) ]
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%token = call token @llvm.experimental.convergence.entry()
|
|
call void @convergent_callee(i32 0) [ "convergencectrl"(token %token) ]
|
|
call void @convergent_callee(i32 1) [ "convergencectrl"(token %token) ]
|
|
call void @convergent_callee(i32 2) [ "convergencectrl"(token %token) ]
|
|
ret void
|
|
}
|
|
|
|
define void @test_convergent_loop(i1 %cond) {
|
|
; CHECK-LABEL: @test_convergent_loop(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TOKEN:%.*]] = call token @llvm.experimental.convergence.anchor()
|
|
; CHECK-NEXT: br i1 [[COND:%.*]], label [[HDR:%.*]], label [[END:%.*]]
|
|
; CHECK: hdr:
|
|
; CHECK-NEXT: [[TOK_LOOP:%.*]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[TOKEN]]) ]
|
|
; CHECK-NEXT: call void @f(i32 0) [ "convergencectrl"(token [[TOK_LOOP]]) ]
|
|
; CHECK-NEXT: br i1 [[COND]], label [[HDR]], label [[END]]
|
|
; CHECK: end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%token = call token @llvm.experimental.convergence.anchor()
|
|
br i1 %cond, label %hdr, label %end
|
|
|
|
hdr:
|
|
%tok.loop = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %token) ]
|
|
call void @convergent_callee(i32 0) [ "convergencectrl"(token %tok.loop) ]
|
|
br i1 %cond, label %hdr, label %end
|
|
|
|
end:
|
|
ret void
|
|
}
|
|
|
|
define void @make_indirect_call(ptr %f, i32 %x) convergent alwaysinline {
|
|
; CHECK-LABEL: @make_indirect_call(
|
|
; CHECK-NEXT: [[TOKEN:%.*]] = call token @llvm.experimental.convergence.entry()
|
|
; CHECK-NEXT: call void [[F:%.*]](i32 [[X:%.*]]) #[[ATTR2:[0-9]+]] [ "convergencectrl"(token [[TOKEN]]) ]
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%token = call token @llvm.experimental.convergence.entry()
|
|
call void %f(i32 %x) convergent [ "convergencectrl"(token %token) ]
|
|
ret void
|
|
}
|
|
|
|
define void @test_indirect_call() convergent {
|
|
; CHECK-LABEL: @test_indirect_call(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TOKEN:%.*]] = call token @llvm.experimental.convergence.entry()
|
|
; CHECK-NEXT: call void @f(i32 0) [ "convergencectrl"(token [[TOKEN]]) ]
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%token = call token @llvm.experimental.convergence.entry()
|
|
call void @make_indirect_call(ptr @convergent_callee, i32 0) [ "convergencectrl"(token %token) ]
|
|
ret void
|
|
}
|
|
|
|
define void @recurse() convergent alwaysinline {
|
|
; CHECK-LABEL: @recurse(
|
|
; CHECK-NEXT: [[TOKEN:%.*]] = call token @llvm.experimental.convergence.entry()
|
|
; CHECK-NEXT: call void @recurse() [ "convergencectrl"(token [[TOKEN]]) ]
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%token = call token @llvm.experimental.convergence.entry()
|
|
call void @recurse() [ "convergencectrl"(token %token) ]
|
|
ret void
|
|
}
|
|
|
|
define void @test_recursive_call() convergent {
|
|
; CHECK-LABEL: @test_recursive_call(
|
|
; CHECK-NEXT: [[TOKEN:%.*]] = call token @llvm.experimental.convergence.entry()
|
|
; CHECK-NEXT: call void @recurse() [ "convergencectrl"(token [[TOKEN]]) ]
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%token = call token @llvm.experimental.convergence.entry()
|
|
call void @recurse() [ "convergencectrl"(token %token) ]
|
|
ret void
|
|
}
|
|
|
|
define i32 @outer_g(i32 %x) convergent alwaysinline {
|
|
; CHECK-LABEL: @outer_g(
|
|
; 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]]
|
|
;
|
|
%token = call token @llvm.experimental.convergence.entry()
|
|
%y = call i32 @g(i32 %x) [ "convergencectrl"(token %token) ]
|
|
ret i32 %y
|
|
}
|
|
|
|
define void @test_two_calls() convergent {
|
|
; CHECK-LABEL: @test_two_calls(
|
|
; CHECK-NEXT: [[TOKEN:%.*]] = call token @llvm.experimental.convergence.entry()
|
|
; CHECK-NEXT: [[Y_I:%.*]] = call i32 @g(i32 23) [ "convergencectrl"(token [[TOKEN]]) ]
|
|
; CHECK-NEXT: call void @f(i32 [[Y_I]]) [ "convergencectrl"(token [[TOKEN]]) ]
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%token = call token @llvm.experimental.convergence.entry()
|
|
%x = call i32 @outer_g(i32 23) [ "convergencectrl"(token %token) ]
|
|
call void @convergent_callee(i32 %x) [ "convergencectrl"(token %token) ]
|
|
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
|
|
|
|
declare token @llvm.experimental.convergence.entry()
|
|
declare token @llvm.experimental.convergence.anchor()
|
|
declare token @llvm.experimental.convergence.loop()
|