Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Coroutines] Offering llvm.coro.align intrinsic
It is a known problem that we can't align the switch-based coroutine frame if the alignment exceeds std::max_align_t (which is 16 usually). We could solve the problem on the middle-end by dynamically transforming or in the frontend by emitting aligned allocation function. If we need to solve it in the frontend, the middle end need to offer an intrinsic to tell the alignment at least. This patch tries to offer such an intrinsic called llvm.coro.align. Reviewed By: https://reviews.llvm.org/D117542 Differential revision: https://reviews.llvm.org/D117542
- Loading branch information
1 parent
76b7423
commit c8ecf12
Showing
12 changed files
with
315 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
; Tests that the coro.align intrinsic could be lowered to correct alignment | ||
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s | ||
|
||
define i8* @f() "coroutine.presplit"="1" { | ||
entry: | ||
%x = alloca i64 | ||
%y = alloca i64 | ||
%id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null) | ||
%size = call i32 @llvm.coro.size.i32() | ||
%align = call i32 @llvm.coro.align.i32() | ||
%alloc = call i8* @aligned_alloc(i32 %align, i32 %size) | ||
%hdl = call i8* @llvm.coro.begin(token %id, i8* %alloc) | ||
%sp1 = call i8 @llvm.coro.suspend(token none, i1 false) | ||
switch i8 %sp1, label %suspend [i8 0, label %resume | ||
i8 1, label %cleanup] | ||
resume: | ||
%x.alias = bitcast i64* %x to i32* | ||
call void @capture_call(i32* %x.alias) | ||
%y.alias = bitcast i64* %y to i32* | ||
call void @nocapture_call(i32* %y.alias) | ||
br label %cleanup | ||
|
||
cleanup: | ||
%mem = call i8* @llvm.coro.free(token %id, i8* %hdl) | ||
call void @free(i8* %mem) | ||
br label %suspend | ||
|
||
suspend: | ||
call i1 @llvm.coro.end(i8* %hdl, i1 0) | ||
ret i8* %hdl | ||
} | ||
|
||
; %x needs to go to the frame since it's escaped; %y will stay as local since it doesn't escape. | ||
; CHECK: %f.Frame = type { void (%f.Frame*)*, void (%f.Frame*)*, i64, i1 } | ||
; CHECK-LABEL: define i8* @f() | ||
; CHECK: %[[ALLOC:.+]] = call i8* @aligned_alloc(i32 8, i32 32) | ||
; CHECK-NEXT: call noalias nonnull i8* @llvm.coro.begin(token %id, i8* %[[ALLOC]]) | ||
|
||
declare i8* @llvm.coro.free(token, i8*) | ||
declare i32 @llvm.coro.size.i32() | ||
declare i32 @llvm.coro.align.i32() | ||
declare i8 @llvm.coro.suspend(token, i1) | ||
declare void @llvm.coro.resume(i8*) | ||
declare void @llvm.coro.destroy(i8*) | ||
|
||
declare token @llvm.coro.id(i32, i8*, i8*, i8*) | ||
declare i1 @llvm.coro.alloc(token) | ||
declare i8* @llvm.coro.begin(token, i8*) | ||
declare i1 @llvm.coro.end(i8*, i1) | ||
|
||
declare void @capture_call(i32*) | ||
declare void @nocapture_call(i32* nocapture) | ||
declare noalias i8* @aligned_alloc(i32, i32) | ||
declare void @free(i8*) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
; Tests that the coro.align intrinsic could be lowered to correct alignment | ||
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s | ||
|
||
define i8* @f() "coroutine.presplit"="1" { | ||
entry: | ||
%id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null) | ||
%size = call i32 @llvm.coro.size.i32() | ||
%align = call i32 @llvm.coro.align.i32() | ||
%alloc = call i8* @aligned_alloc(i32 %align, i32 %size) | ||
%hdl = call i8* @llvm.coro.begin(token %id, i8* %alloc) | ||
%sp1 = call i8 @llvm.coro.suspend(token none, i1 false) | ||
switch i8 %sp1, label %suspend [i8 0, label %resume | ||
i8 1, label %cleanup] | ||
resume: | ||
br label %cleanup | ||
|
||
cleanup: | ||
%mem = call i8* @llvm.coro.free(token %id, i8* %hdl) | ||
call void @free(i8* %mem) | ||
br label %suspend | ||
|
||
suspend: | ||
call i1 @llvm.coro.end(i8* %hdl, i1 0) | ||
ret i8* %hdl | ||
} | ||
|
||
; %x needs to go to the frame since it's escaped; %y will stay as local since it doesn't escape. | ||
; CHECK: %f.Frame = type { void (%f.Frame*)*, void (%f.Frame*)*, i1 } | ||
; CHECK-LABEL: define i8* @f() | ||
; CHECK: %[[ALLOC:.+]] = call i8* @aligned_alloc(i32 8, i32 24) | ||
; CHECK-NEXT: call noalias nonnull i8* @llvm.coro.begin(token %id, i8* %[[ALLOC]]) | ||
|
||
declare i8* @llvm.coro.free(token, i8*) | ||
declare i32 @llvm.coro.size.i32() | ||
declare i32 @llvm.coro.align.i32() | ||
declare i8 @llvm.coro.suspend(token, i1) | ||
declare void @llvm.coro.resume(i8*) | ||
declare void @llvm.coro.destroy(i8*) | ||
|
||
declare token @llvm.coro.id(i32, i8*, i8*, i8*) | ||
declare i1 @llvm.coro.alloc(token) | ||
declare i8* @llvm.coro.begin(token, i8*) | ||
declare i1 @llvm.coro.end(i8*, i1) | ||
|
||
declare noalias i8* @aligned_alloc(i32, i32) | ||
declare void @free(i8*) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
; Tests that the coro.align intrinsic could be lowered to correct alignment | ||
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s | ||
|
||
define i8* @f() "coroutine.presplit"="1" { | ||
entry: | ||
%x = alloca i64, align 16 | ||
%y = alloca i64 | ||
%id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null) | ||
%size = call i32 @llvm.coro.size.i32() | ||
%align = call i32 @llvm.coro.align.i32() | ||
%alloc = call i8* @aligned_alloc(i32 %align, i32 %size) | ||
%hdl = call i8* @llvm.coro.begin(token %id, i8* %alloc) | ||
%sp1 = call i8 @llvm.coro.suspend(token none, i1 false) | ||
switch i8 %sp1, label %suspend [i8 0, label %resume | ||
i8 1, label %cleanup] | ||
resume: | ||
%x.alias = bitcast i64* %x to i32* | ||
call void @capture_call(i32* %x.alias) | ||
%y.alias = bitcast i64* %y to i32* | ||
call void @capture_call(i32* %y.alias) | ||
br label %cleanup | ||
|
||
cleanup: | ||
%mem = call i8* @llvm.coro.free(token %id, i8* %hdl) | ||
call void @free(i8* %mem) | ||
br label %suspend | ||
|
||
suspend: | ||
call i1 @llvm.coro.end(i8* %hdl, i1 0) | ||
ret i8* %hdl | ||
} | ||
|
||
; %x needs to go to the frame since it's escaped; %y will stay as local since it doesn't escape. | ||
; CHECK: %f.Frame = type { void (%f.Frame*)*, void (%f.Frame*)*, i64, i64, i1 } | ||
; CHECK-LABEL: define i8* @f() | ||
; CHECK: %[[ALLOC:.+]] = call i8* @aligned_alloc(i32 16, i32 40) | ||
; CHECK-NEXT: call noalias nonnull i8* @llvm.coro.begin(token %id, i8* %[[ALLOC]]) | ||
|
||
declare i8* @llvm.coro.free(token, i8*) | ||
declare i32 @llvm.coro.size.i32() | ||
declare i32 @llvm.coro.align.i32() | ||
declare i8 @llvm.coro.suspend(token, i1) | ||
declare void @llvm.coro.resume(i8*) | ||
declare void @llvm.coro.destroy(i8*) | ||
|
||
declare token @llvm.coro.id(i32, i8*, i8*, i8*) | ||
declare i1 @llvm.coro.alloc(token) | ||
declare i8* @llvm.coro.begin(token, i8*) | ||
declare i1 @llvm.coro.end(i8*, i1) | ||
|
||
declare void @capture_call(i32*) | ||
declare void @nocapture_call(i32* nocapture) | ||
declare noalias i8* @aligned_alloc(i32, i32) | ||
declare void @free(i8*) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
; Tests that the coro.align intrinsic could be lowered to correct alignment | ||
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s | ||
|
||
define i8* @f() "coroutine.presplit"="1" { | ||
entry: | ||
%x = alloca i1, align 64 | ||
%y = alloca i64 | ||
%id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null) | ||
%size = call i32 @llvm.coro.size.i32() | ||
%align = call i32 @llvm.coro.align.i32() | ||
%alloc = call i8* @aligned_alloc(i32 %align, i32 %size) | ||
%hdl = call i8* @llvm.coro.begin(token %id, i8* %alloc) | ||
%sp1 = call i8 @llvm.coro.suspend(token none, i1 false) | ||
switch i8 %sp1, label %suspend [i8 0, label %resume | ||
i8 1, label %cleanup] | ||
resume: | ||
%x.alias = bitcast i1* %x to i32* | ||
call void @capture_call(i32* %x.alias) | ||
%y.alias = bitcast i64* %y to i32* | ||
call void @capture_call(i32* %y.alias) | ||
br label %cleanup | ||
|
||
cleanup: | ||
%mem = call i8* @llvm.coro.free(token %id, i8* %hdl) | ||
call void @free(i8* %mem) | ||
br label %suspend | ||
|
||
suspend: | ||
call i1 @llvm.coro.end(i8* %hdl, i1 0) | ||
ret i8* %hdl | ||
} | ||
|
||
; %x needs to go to the frame since it's escaped; %y will stay as local since it doesn't escape. | ||
; CHECK: %f.Frame = type { void (%f.Frame*)*, void (%f.Frame*)*, i64, i1, [39 x i8], i1 } | ||
; CHECK-LABEL: define i8* @f() | ||
; CHECK: %[[ALLOC:.+]] = call i8* @aligned_alloc(i32 64, i32 72) | ||
; CHECK-NEXT: call noalias nonnull i8* @llvm.coro.begin(token %id, i8* %[[ALLOC]]) | ||
|
||
declare i8* @llvm.coro.free(token, i8*) | ||
declare i32 @llvm.coro.size.i32() | ||
declare i32 @llvm.coro.align.i32() | ||
declare i8 @llvm.coro.suspend(token, i1) | ||
declare void @llvm.coro.resume(i8*) | ||
declare void @llvm.coro.destroy(i8*) | ||
|
||
declare token @llvm.coro.id(i32, i8*, i8*, i8*) | ||
declare i1 @llvm.coro.alloc(token) | ||
declare i8* @llvm.coro.begin(token, i8*) | ||
declare i1 @llvm.coro.end(i8*, i1) | ||
|
||
declare void @capture_call(i32*) | ||
declare void @nocapture_call(i32* nocapture) | ||
declare noalias i8* @aligned_alloc(i32, i32) | ||
declare void @free(i8*) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
; Tests that the coro.align intrinsic could be lowered to correct alignment | ||
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s | ||
|
||
define i8* @f() "coroutine.presplit"="1" { | ||
entry: | ||
%x = alloca i1, align 64 | ||
%y = alloca i64, align 32 | ||
%id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null) | ||
%size = call i32 @llvm.coro.size.i32() | ||
%align = call i32 @llvm.coro.align.i32() | ||
%alloc = call i8* @aligned_alloc(i32 %align, i32 %size) | ||
%hdl = call i8* @llvm.coro.begin(token %id, i8* %alloc) | ||
%sp1 = call i8 @llvm.coro.suspend(token none, i1 false) | ||
switch i8 %sp1, label %suspend [i8 0, label %resume | ||
i8 1, label %cleanup] | ||
resume: | ||
%x.alias = bitcast i1* %x to i32* | ||
call void @capture_call(i32* %x.alias) | ||
%y.alias = bitcast i64* %y to i32* | ||
call void @capture_call(i32* %y.alias) | ||
br label %cleanup | ||
|
||
cleanup: | ||
%mem = call i8* @llvm.coro.free(token %id, i8* %hdl) | ||
call void @free(i8* %mem) | ||
br label %suspend | ||
|
||
suspend: | ||
call i1 @llvm.coro.end(i8* %hdl, i1 0) | ||
ret i8* %hdl | ||
} | ||
|
||
; %x needs to go to the frame since it's escaped; %y will stay as local since it doesn't escape. | ||
; CHECK: %f.Frame = type { void (%f.Frame*)*, void (%f.Frame*)*, i1, [15 x i8], i64, [24 x i8], i1 } | ||
; CHECK-LABEL: define i8* @f() | ||
; CHECK: %[[ALLOC:.+]] = call i8* @aligned_alloc(i32 64, i32 72) | ||
; CHECK-NEXT: call noalias nonnull i8* @llvm.coro.begin(token %id, i8* %[[ALLOC]]) | ||
|
||
declare i8* @llvm.coro.free(token, i8*) | ||
declare i32 @llvm.coro.size.i32() | ||
declare i32 @llvm.coro.align.i32() | ||
declare i8 @llvm.coro.suspend(token, i1) | ||
declare void @llvm.coro.resume(i8*) | ||
declare void @llvm.coro.destroy(i8*) | ||
|
||
declare token @llvm.coro.id(i32, i8*, i8*, i8*) | ||
declare i1 @llvm.coro.alloc(token) | ||
declare i8* @llvm.coro.begin(token, i8*) | ||
declare i1 @llvm.coro.end(i8*, i1) | ||
|
||
declare void @capture_call(i32*) | ||
declare void @nocapture_call(i32* nocapture) | ||
declare noalias i8* @aligned_alloc(i32, i32) | ||
declare void @free(i8*) |