mirror of
https://github.com/RPCSX/llvm.git
synced 2025-04-17 15:40:04 +00:00

Summary: If one of the uses of the value is a single edge PHINode, handle it. Original: %val = something <suspend> %p = PHINode [%val] After Spill + Part13: %val = something %slot = gep val.spill.slot store %val, %slot <suspend> %p = load %slot Plus tiny fixes/changes: * use correct index for coro.free in CoroCleanup * fixup id parameter in coro.free to allow authoring coroutine in plain C with __builtins Reviewers: majnemer Subscribers: mehdi_amini, llvm-commits Differential Revision: https://reviews.llvm.org/D24242 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@281020 91177308-0d34-0410-b5e6-96231b3b80d8
112 lines
3.2 KiB
C++
112 lines
3.2 KiB
C++
//===- CoroCleanup.cpp - Coroutine Cleanup Pass ---------------------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
// This pass lowers all remaining coroutine intrinsics.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "CoroInternal.h"
|
|
#include "llvm/IR/InstIterator.h"
|
|
#include "llvm/IR/LegacyPassManager.h"
|
|
#include "llvm/Pass.h"
|
|
#include "llvm/Transforms/Scalar.h"
|
|
|
|
using namespace llvm;
|
|
|
|
#define DEBUG_TYPE "coro-cleanup"
|
|
|
|
namespace {
|
|
// Created on demand if CoroCleanup pass has work to do.
|
|
struct Lowerer : coro::LowererBase {
|
|
Lowerer(Module &M) : LowererBase(M) {}
|
|
bool lowerRemainingCoroIntrinsics(Function &F);
|
|
};
|
|
}
|
|
|
|
static void simplifyCFG(Function &F) {
|
|
llvm::legacy::FunctionPassManager FPM(F.getParent());
|
|
FPM.add(createCFGSimplificationPass());
|
|
|
|
FPM.doInitialization();
|
|
FPM.run(F);
|
|
FPM.doFinalization();
|
|
}
|
|
|
|
bool Lowerer::lowerRemainingCoroIntrinsics(Function &F) {
|
|
bool Changed = false;
|
|
|
|
for (auto IB = inst_begin(F), E = inst_end(F); IB != E;) {
|
|
Instruction &I = *IB++;
|
|
if (auto *II = dyn_cast<IntrinsicInst>(&I)) {
|
|
switch (II->getIntrinsicID()) {
|
|
default:
|
|
continue;
|
|
case Intrinsic::coro_begin:
|
|
II->replaceAllUsesWith(II->getArgOperand(1));
|
|
break;
|
|
case Intrinsic::coro_free:
|
|
II->replaceAllUsesWith(II->getArgOperand(1));
|
|
break;
|
|
case Intrinsic::coro_alloc:
|
|
II->replaceAllUsesWith(ConstantInt::getTrue(Context));
|
|
break;
|
|
case Intrinsic::coro_id:
|
|
II->replaceAllUsesWith(ConstantTokenNone::get(Context));
|
|
break;
|
|
}
|
|
II->eraseFromParent();
|
|
Changed = true;
|
|
}
|
|
}
|
|
|
|
if (Changed) {
|
|
// After replacement were made we can cleanup the function body a little.
|
|
simplifyCFG(F);
|
|
}
|
|
return Changed;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Top Level Driver
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
namespace {
|
|
|
|
struct CoroCleanup : FunctionPass {
|
|
static char ID; // Pass identification, replacement for typeid
|
|
|
|
CoroCleanup() : FunctionPass(ID) {}
|
|
|
|
std::unique_ptr<Lowerer> L;
|
|
|
|
// This pass has work to do only if we find intrinsics we are going to lower
|
|
// in the module.
|
|
bool doInitialization(Module &M) override {
|
|
if (coro::declaresIntrinsics(M, {"llvm.coro.alloc", "llvm.coro.begin",
|
|
"llvm.coro.free", "llvm.coro.id"}))
|
|
L = llvm::make_unique<Lowerer>(M);
|
|
return false;
|
|
}
|
|
|
|
bool runOnFunction(Function &F) override {
|
|
if (L)
|
|
return L->lowerRemainingCoroIntrinsics(F);
|
|
return false;
|
|
}
|
|
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
|
if (!L)
|
|
AU.setPreservesAll();
|
|
}
|
|
};
|
|
}
|
|
|
|
char CoroCleanup::ID = 0;
|
|
INITIALIZE_PASS(CoroCleanup, "coro-cleanup",
|
|
"Lower all coroutine related intrinsics", false, false)
|
|
|
|
Pass *llvm::createCoroCleanupPass() { return new CoroCleanup(); }
|