Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[coroutines] Part 4[ab]: Coroutine Devirtualization: Lower coro.resum…
…e and coro.destroy. This is the forth patch in the coroutine series. CoroEaly pass now lowers coro.resume and coro.destroy intrinsics by replacing them with an indirect call to an address returned by coro.subfn.addr intrinsic. This is done so that CGPassManager recognizes devirtualization when CoroElide replaces a call to coro.subfn.addr with an appropriate function address. Patch by Gor Nishanov! Differential Revision: https://reviews.llvm.org/D22998 llvm-svn: 277765
- Loading branch information
Showing
8 changed files
with
278 additions
and
7 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
//===-- CoroInstr.h - Coroutine Intrinsics Instruction Wrappers -*- C++ -*-===// | ||
// | ||
// The LLVM Compiler Infrastructure | ||
// | ||
// This file is distributed under the University of Illinois Open Source | ||
// License. See LICENSE.TXT for details. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// This file defines classes that make it really easy to deal with intrinsic | ||
// functions with the isa/dyncast family of functions. In particular, this | ||
// allows you to do things like: | ||
// | ||
// if (auto *SF = dyn_cast<CoroSubFnInst>(Inst)) | ||
// ... SF->getFrame() ... SF->getAlloc() ... | ||
// | ||
// All intrinsic function calls are instances of the call instruction, so these | ||
// are all subclasses of the CallInst class. Note that none of these classes | ||
// has state or virtual methods, which is an important part of this gross/neat | ||
// hack working. | ||
// | ||
// The helpful comment above is borrowed from llvm/IntrinsicInst.h, we keep | ||
// coroutine intrinsic wrappers here since they are only used by the passes in | ||
// the Coroutine library. | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "llvm/IR/GlobalVariable.h" | ||
#include "llvm/IR/IntrinsicInst.h" | ||
|
||
namespace llvm { | ||
|
||
/// This class represents the llvm.coro.subfn.addr instruction. | ||
class LLVM_LIBRARY_VISIBILITY CoroSubFnInst : public IntrinsicInst { | ||
enum { FrameArg, IndexArg }; | ||
|
||
public: | ||
enum ResumeKind { | ||
ResumeIndex, | ||
DestroyIndex, | ||
IndexLast, | ||
IndexFirst = ResumeIndex | ||
}; | ||
|
||
Value *getFrame() const { return getArgOperand(FrameArg); } | ||
ResumeKind getIndex() const { | ||
int64_t Index = getRawIndex()->getValue().getSExtValue(); | ||
assert(Index >= IndexFirst && Index < IndexLast && | ||
"unexpected CoroSubFnInst index argument"); | ||
return static_cast<ResumeKind>(Index); | ||
} | ||
|
||
ConstantInt *getRawIndex() const { | ||
return cast<ConstantInt>(getArgOperand(IndexArg)); | ||
} | ||
|
||
// Methods to support type inquiry through isa, cast, and dyn_cast: | ||
static inline bool classof(const IntrinsicInst *I) { | ||
return I->getIntrinsicID() == Intrinsic::coro_subfn_addr; | ||
} | ||
static inline bool classof(const Value *V) { | ||
return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | ||
} | ||
}; | ||
|
||
} // End namespace llvm. |
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,41 @@ | ||
; Tests that CoroEarly pass correctly lowers coro.resume and coro.destroy | ||
; intrinsics. | ||
; RUN: opt < %s -S -coro-early | FileCheck %s | ||
|
||
; CHECK-LABEL: @callResume | ||
define void @callResume(i8* %hdl) { | ||
; CHECK-NEXT: entry | ||
entry: | ||
; CHECK-NEXT: %0 = call i8* @llvm.coro.subfn.addr(i8* %hdl, i8 0) | ||
; CHECK-NEXT: %1 = bitcast i8* %0 to void (i8*)* | ||
; CHECK-NEXT: call fastcc void %1(i8* %hdl) | ||
call void @llvm.coro.resume(i8* %hdl) | ||
|
||
; CHECK-NEXT: %2 = call i8* @llvm.coro.subfn.addr(i8* %hdl, i8 1) | ||
; CHECK-NEXT: %3 = bitcast i8* %2 to void (i8*)* | ||
; CHECK-NEXT: call fastcc void %3(i8* %hdl) | ||
call void @llvm.coro.destroy(i8* %hdl) | ||
|
||
ret void | ||
; CHECK-NEXT: ret void | ||
} | ||
|
||
; CHECK-LABEL: @eh | ||
define void @eh(i8* %hdl) personality i8* null { | ||
; CHECK-NEXT: entry | ||
entry: | ||
; CHECK-NEXT: %0 = call i8* @llvm.coro.subfn.addr(i8* %hdl, i8 0) | ||
; CHECK-NEXT: %1 = bitcast i8* %0 to void (i8*)* | ||
; CHECK-NEXT: invoke fastcc void %1(i8* %hdl) | ||
invoke void @llvm.coro.resume(i8* %hdl) | ||
to label %cont unwind label %ehcleanup | ||
cont: | ||
ret void | ||
|
||
ehcleanup: | ||
%0 = cleanuppad within none [] | ||
cleanupret from %0 unwind to caller | ||
} | ||
|
||
declare void @llvm.coro.resume(i8*) | ||
declare void @llvm.coro.destroy(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