Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Transforms/Coroutines/CoroCleanup.cpp
Line
Count
Source
1
//===- CoroCleanup.cpp - Coroutine Cleanup Pass ---------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
// This pass lowers all remaining coroutine intrinsics.
9
//===----------------------------------------------------------------------===//
10
11
#include "CoroInternal.h"
12
#include "llvm/IR/IRBuilder.h"
13
#include "llvm/IR/InstIterator.h"
14
#include "llvm/IR/LegacyPassManager.h"
15
#include "llvm/Pass.h"
16
#include "llvm/Transforms/Scalar.h"
17
18
using namespace llvm;
19
20
#define DEBUG_TYPE "coro-cleanup"
21
22
namespace {
23
// Created on demand if CoroCleanup pass has work to do.
24
struct Lowerer : coro::LowererBase {
25
  IRBuilder<> Builder;
26
11
  Lowerer(Module &M) : LowererBase(M), Builder(Context) {}
27
  bool lowerRemainingCoroIntrinsics(Function &F);
28
};
29
}
30
31
18
static void simplifyCFG(Function &F) {
32
18
  llvm::legacy::FunctionPassManager FPM(F.getParent());
33
18
  FPM.add(createCFGSimplificationPass());
34
18
35
18
  FPM.doInitialization();
36
18
  FPM.run(F);
37
18
  FPM.doFinalization();
38
18
}
39
40
2
static void lowerSubFn(IRBuilder<> &Builder, CoroSubFnInst *SubFn) {
41
2
  Builder.SetInsertPoint(SubFn);
42
2
  Value *FrameRaw = SubFn->getFrame();
43
2
  int Index = SubFn->getIndex();
44
2
45
2
  auto *FrameTy = StructType::get(
46
2
      SubFn->getContext(), {Builder.getInt8PtrTy(), Builder.getInt8PtrTy()});
47
2
  PointerType *FramePtrTy = FrameTy->getPointerTo();
48
2
49
2
  Builder.SetInsertPoint(SubFn);
50
2
  auto *FramePtr = Builder.CreateBitCast(FrameRaw, FramePtrTy);
51
2
  auto *Gep = Builder.CreateConstInBoundsGEP2_32(FrameTy, FramePtr, 0, Index);
52
2
  auto *Load = Builder.CreateLoad(FrameTy->getElementType(Index), Gep);
53
2
54
2
  SubFn->replaceAllUsesWith(Load);
55
2
}
56
57
59
bool Lowerer::lowerRemainingCoroIntrinsics(Function &F) {
58
59
  bool Changed = false;
59
59
60
1.01k
  for (auto IB = inst_begin(F), E = inst_end(F); IB != E;) {
61
958
    Instruction &I = *IB++;
62
958
    if (auto *II = dyn_cast<IntrinsicInst>(&I)) {
63
47
      switch (II->getIntrinsicID()) {
64
47
      default:
65
5
        continue;
66
47
      case Intrinsic::coro_begin:
67
17
        II->replaceAllUsesWith(II->getArgOperand(1));
68
17
        break;
69
47
      case Intrinsic::coro_free:
70
1
        II->replaceAllUsesWith(II->getArgOperand(1));
71
1
        break;
72
47
      case Intrinsic::coro_alloc:
73
5
        II->replaceAllUsesWith(ConstantInt::getTrue(Context));
74
5
        break;
75
47
      case Intrinsic::coro_id:
76
17
        II->replaceAllUsesWith(ConstantTokenNone::get(Context));
77
17
        break;
78
47
      case Intrinsic::coro_subfn_addr:
79
2
        lowerSubFn(Builder, cast<CoroSubFnInst>(II));
80
2
        break;
81
42
      }
82
42
      II->eraseFromParent();
83
42
      Changed = true;
84
42
    }
85
958
  }
86
59
87
59
  if (Changed) {
88
18
    // After replacement were made we can cleanup the function body a little.
89
18
    simplifyCFG(F);
90
18
  }
91
59
  return Changed;
92
59
}
93
94
//===----------------------------------------------------------------------===//
95
//                              Top Level Driver
96
//===----------------------------------------------------------------------===//
97
98
namespace {
99
100
struct CoroCleanup : FunctionPass {
101
  static char ID; // Pass identification, replacement for typeid
102
103
37
  CoroCleanup() : FunctionPass(ID) {
104
37
    initializeCoroCleanupPass(*PassRegistry::getPassRegistry());
105
37
  }
106
107
  std::unique_ptr<Lowerer> L;
108
109
  // This pass has work to do only if we find intrinsics we are going to lower
110
  // in the module.
111
37
  bool doInitialization(Module &M) override {
112
37
    if (coro::declaresIntrinsics(M, {"llvm.coro.alloc", "llvm.coro.begin",
113
37
                                     "llvm.coro.subfn.addr", "llvm.coro.free",
114
37
                                     "llvm.coro.id"}))
115
11
      L = llvm::make_unique<Lowerer>(M);
116
37
    return false;
117
37
  }
118
119
198
  bool runOnFunction(Function &F) override {
120
198
    if (L)
121
59
      return L->lowerRemainingCoroIntrinsics(F);
122
139
    return false;
123
139
  }
124
37
  void getAnalysisUsage(AnalysisUsage &AU) const override {
125
37
    if (!L)
126
37
      AU.setPreservesAll();
127
37
  }
128
198
  StringRef getPassName() const override { return "Coroutine Cleanup"; }
129
};
130
}
131
132
char CoroCleanup::ID = 0;
133
INITIALIZE_PASS(CoroCleanup, "coro-cleanup",
134
                "Lower all coroutine related intrinsics", false, false)
135
136
36
Pass *llvm::createCoroCleanupPass() { return new CoroCleanup(); }