Coverage Report

Created: 2020-06-26 05:44

/home/arjun/llvm-project/mlir/lib/Interfaces/SideEffectInterfaces.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- SideEffectInterfaces.cpp - SideEffects in MLIR ---------------------===//
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
9
#include "mlir/Interfaces/SideEffectInterfaces.h"
10
11
using namespace mlir;
12
13
//===----------------------------------------------------------------------===//
14
// SideEffect Interfaces
15
//===----------------------------------------------------------------------===//
16
17
/// Include the definitions of the side effect interfaces.
18
#include "mlir/Interfaces/SideEffectInterfaces.cpp.inc"
19
20
//===----------------------------------------------------------------------===//
21
// MemoryEffects
22
//===----------------------------------------------------------------------===//
23
24
0
bool MemoryEffects::Effect::classof(const SideEffects::Effect *effect) {
25
0
  return isa<Allocate>(effect) || isa<Free>(effect) || isa<Read>(effect) ||
26
0
         isa<Write>(effect);
27
0
}
28
29
//===----------------------------------------------------------------------===//
30
// SideEffect Utilities
31
//===----------------------------------------------------------------------===//
32
33
0
bool mlir::isOpTriviallyDead(Operation *op) {
34
0
  return op->use_empty() && wouldOpBeTriviallyDead(op);
35
0
}
36
37
/// Internal implementation of `mlir::wouldOpBeTriviallyDead` that also
38
/// considers terminator operations as dead if they have no side effects. This
39
/// allows for marking region operations as trivially dead without always being
40
/// conservative of terminators.
41
0
static bool wouldOpBeTriviallyDeadImpl(Operation *rootOp) {
42
0
  // The set of operations to consider when checking for side effects.
43
0
  SmallVector<Operation *, 1> effectingOps(1, rootOp);
44
0
  while (!effectingOps.empty()) {
45
0
    Operation *op = effectingOps.pop_back_val();
46
0
47
0
    // If the operation has recursive effects, push all of the nested operations
48
0
    // on to the stack to consider.
49
0
    bool hasRecursiveEffects = op->hasTrait<OpTrait::HasRecursiveSideEffects>();
50
0
    if (hasRecursiveEffects) {
51
0
      for (Region &region : op->getRegions()) {
52
0
        for (auto &block : region) {
53
0
          for (auto &nestedOp : block)
54
0
            effectingOps.push_back(&nestedOp);
55
0
        }
56
0
      }
57
0
    }
58
0
59
0
    // If the op has memory effects, try to characterize them to see if the op
60
0
    // is trivially dead here.
61
0
    if (auto effectInterface = dyn_cast<MemoryEffectOpInterface>(op)) {
62
0
      // Check to see if this op either has no effects, or only allocates/reads
63
0
      // memory.
64
0
      SmallVector<MemoryEffects::EffectInstance, 1> effects;
65
0
      effectInterface.getEffects(effects);
66
0
      if (!llvm::all_of(effects, [op](const MemoryEffects::EffectInstance &it) {
67
0
            // We can drop allocations if the value is a result of the
68
0
            // operation.
69
0
            if (isa<MemoryEffects::Allocate>(it.getEffect()))
70
0
              return it.getValue() && it.getValue().getDefiningOp() == op;
71
0
            // Otherwise, the effect must be a read.
72
0
            return isa<MemoryEffects::Read>(it.getEffect());
73
0
          })) {
74
0
        return false;
75
0
      }
76
0
      continue;
77
0
78
0
      // Otherwise, if the op has recursive side effects we can treat the
79
0
      // operation itself as having no effects.
80
0
    } else if (hasRecursiveEffects) {
81
0
      continue;
82
0
    }
83
0
84
0
    // If there were no effect interfaces, we treat this op as conservatively
85
0
    // having effects.
86
0
    return false;
87
0
  }
88
0
89
0
  // If we get here, none of the operations had effects that prevented marking
90
0
  // 'op' as dead.
91
0
  return true;
92
0
}
93
94
0
bool mlir::wouldOpBeTriviallyDead(Operation *op) {
95
0
  if (!op->isKnownNonTerminator())
96
0
    return false;
97
0
  return wouldOpBeTriviallyDeadImpl(op);
98
0
}