Coverage Report

Created: 2020-06-26 05:44

/home/arjun/llvm-project/mlir/include/mlir/Interfaces/SideEffectInterfaces.h
Line
Count
Source (jump to first uncovered line)
1
//===- SideEffectInterfaces.h - SideEffect in MLIR --------------*- C++ -*-===//
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
// This file contains traits, interfaces, and utilities for defining and
10
// querying the side effects of an operation.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#ifndef MLIR_INTERFACES_SIDEEFFECTS_H
15
#define MLIR_INTERFACES_SIDEEFFECTS_H
16
17
#include "mlir/IR/OpDefinition.h"
18
19
namespace mlir {
20
namespace SideEffects {
21
//===----------------------------------------------------------------------===//
22
// Effects
23
//===----------------------------------------------------------------------===//
24
25
/// This class represents a base class for a specific effect type.
26
class Effect {
27
public:
28
  /// This base class is used for derived effects that are non-parametric.
29
  template <typename DerivedEffect, typename BaseEffect = Effect>
30
  class Base : public BaseEffect {
31
  public:
32
    using BaseT = Base<DerivedEffect>;
33
34
    /// Return the unique identifier for the base effects class.
35
0
    static TypeID getEffectID() { return TypeID::get<DerivedEffect>(); }
Unexecuted instantiation: _ZN4mlir11SideEffects6Effect4BaseINS_13MemoryEffects4ReadES1_E11getEffectIDEv
Unexecuted instantiation: _ZN4mlir11SideEffects6Effect4BaseINS_13MemoryEffects5WriteES1_E11getEffectIDEv
Unexecuted instantiation: _ZN4mlir11SideEffects6Effect4BaseINS_13MemoryEffects8AllocateES1_E11getEffectIDEv
Unexecuted instantiation: _ZN4mlir11SideEffects6Effect4BaseINS_13MemoryEffects4FreeES1_E11getEffectIDEv
36
37
    /// 'classof' used to support llvm style cast functionality.
38
0
    static bool classof(const ::mlir::SideEffects::Effect *effect) {
39
0
      return effect->getEffectID() == BaseT::getEffectID();
40
0
    }
Unexecuted instantiation: _ZN4mlir11SideEffects6Effect4BaseINS_13MemoryEffects8AllocateENS3_6EffectEE7classofEPKS1_
Unexecuted instantiation: _ZN4mlir11SideEffects6Effect4BaseINS_13MemoryEffects4ReadENS3_6EffectEE7classofEPKS1_
Unexecuted instantiation: _ZN4mlir11SideEffects6Effect4BaseINS_13MemoryEffects4FreeENS3_6EffectEE7classofEPKS1_
Unexecuted instantiation: _ZN4mlir11SideEffects6Effect4BaseINS_13MemoryEffects5WriteENS3_6EffectEE7classofEPKS1_
41
42
    /// Returns a unique instance for the derived effect class.
43
0
    static DerivedEffect *get() {
44
0
      return BaseEffect::template get<DerivedEffect>();
45
0
    }
Unexecuted instantiation: _ZN4mlir11SideEffects6Effect4BaseINS_13MemoryEffects4ReadENS3_6EffectEE3getEv
Unexecuted instantiation: _ZN4mlir11SideEffects6Effect4BaseINS_13MemoryEffects5WriteENS3_6EffectEE3getEv
Unexecuted instantiation: _ZN4mlir11SideEffects6Effect4BaseINS_13MemoryEffects8AllocateENS3_6EffectEE3getEv
Unexecuted instantiation: _ZN4mlir11SideEffects6Effect4BaseINS_13MemoryEffects4FreeENS3_6EffectEE3getEv
46
    using BaseEffect::get;
47
48
  protected:
49
0
    Base() : BaseEffect(BaseT::getEffectID()) {}
Unexecuted instantiation: _ZN4mlir11SideEffects6Effect4BaseINS_13MemoryEffects4ReadENS3_6EffectEEC2Ev
Unexecuted instantiation: _ZN4mlir11SideEffects6Effect4BaseINS_13MemoryEffects5WriteENS3_6EffectEEC2Ev
Unexecuted instantiation: _ZN4mlir11SideEffects6Effect4BaseINS_13MemoryEffects8AllocateENS3_6EffectEEC2Ev
Unexecuted instantiation: _ZN4mlir11SideEffects6Effect4BaseINS_13MemoryEffects4FreeENS3_6EffectEEC2Ev
50
  };
51
52
  /// Return the unique identifier for the base effects class.
53
0
  TypeID getEffectID() const { return id; }
54
55
  /// Returns a unique instance for the given effect class.
56
0
  template <typename DerivedEffect> static DerivedEffect *get() {
57
0
    static_assert(std::is_base_of<Effect, DerivedEffect>::value,
58
0
                  "expected DerivedEffect to inherit from Effect");
59
0
60
0
    static DerivedEffect instance;
61
0
    return &instance;
62
0
  }
Unexecuted instantiation: _ZN4mlir11SideEffects6Effect3getINS_13MemoryEffects4ReadEEEPT_v
Unexecuted instantiation: _ZN4mlir11SideEffects6Effect3getINS_13MemoryEffects5WriteEEEPT_v
Unexecuted instantiation: _ZN4mlir11SideEffects6Effect3getINS_13MemoryEffects8AllocateEEEPT_v
Unexecuted instantiation: _ZN4mlir11SideEffects6Effect3getINS_13MemoryEffects4FreeEEEPT_v
63
64
protected:
65
0
  Effect(TypeID id) : id(id) {}
66
67
private:
68
  /// The id of the derived effect class.
69
  TypeID id;
70
};
71
72
//===----------------------------------------------------------------------===//
73
// Resources
74
//===----------------------------------------------------------------------===//
75
76
/// This class represents a specific resource that an effect applies to. This
77
/// class represents an abstract interface for a given resource.
78
class Resource {
79
public:
80
0
  virtual ~Resource() {}
81
82
  /// This base class is used for derived effects that are non-parametric.
83
  template <typename DerivedResource, typename BaseResource = Resource>
84
  class Base : public BaseResource {
85
  public:
86
    using BaseT = Base<DerivedResource>;
87
88
    /// Returns a unique instance for the given effect class.
89
0
    static DerivedResource *get() {
90
0
      static DerivedResource instance;
91
0
      return &instance;
92
0
    }
Unexecuted instantiation: _ZN4mlir11SideEffects8Resource4BaseINS0_15DefaultResourceES1_E3getEv
Unexecuted instantiation: _ZN4mlir11SideEffects8Resource4BaseINS0_32AutomaticAllocationScopeResourceES1_E3getEv
93
94
    /// Return the unique identifier for the base resource class.
95
0
    static TypeID getResourceID() { return TypeID::get<DerivedResource>(); }
Unexecuted instantiation: _ZN4mlir11SideEffects8Resource4BaseINS0_15DefaultResourceES1_E13getResourceIDEv
Unexecuted instantiation: _ZN4mlir11SideEffects8Resource4BaseINS0_32AutomaticAllocationScopeResourceES1_E13getResourceIDEv
96
97
    /// 'classof' used to support llvm style cast functionality.
98
    static bool classof(const Resource *resource) {
99
      return resource->getResourceID() == BaseT::getResourceID();
100
    }
101
102
  protected:
103
0
    Base() : BaseResource(BaseT::getResourceID()){};
Unexecuted instantiation: _ZN4mlir11SideEffects8Resource4BaseINS0_15DefaultResourceES1_EC2Ev
Unexecuted instantiation: _ZN4mlir11SideEffects8Resource4BaseINS0_32AutomaticAllocationScopeResourceES1_EC2Ev
104
  };
105
106
  /// Return the unique identifier for the base resource class.
107
0
  TypeID getResourceID() const { return id; }
108
109
  /// Return a string name of the resource.
110
  virtual StringRef getName() = 0;
111
112
protected:
113
0
  Resource(TypeID id) : id(id) {}
114
115
private:
116
  /// The id of the derived resource class.
117
  TypeID id;
118
};
119
120
/// A conservative default resource kind.
121
struct DefaultResource : public Resource::Base<DefaultResource> {
122
0
  StringRef getName() final { return "<Default>"; }
123
};
124
125
/// An automatic allocation-scope resource that is valid in the context of a
126
/// parent AutomaticAllocationScope trait.
127
struct AutomaticAllocationScopeResource
128
    : public Resource::Base<AutomaticAllocationScopeResource> {
129
0
  StringRef getName() final { return "AutomaticAllocationScope"; }
130
};
131
132
/// This class represents a specific instance of an effect. It contains the
133
/// effect being applied, a resource that corresponds to where the effect is
134
/// applied, and an optional value(either operand, result, or region entry
135
/// argument) that the effect is applied to.
136
template <typename EffectT> class EffectInstance {
137
public:
138
  EffectInstance(EffectT *effect, Resource *resource = DefaultResource::get())
139
0
      : effect(effect), resource(resource) {}
140
  EffectInstance(EffectT *effect, Value value,
141
                 Resource *resource = DefaultResource::get())
142
0
      : effect(effect), resource(resource), value(value) {}
143
144
  /// Return the effect being applied.
145
0
  EffectT *getEffect() const { return effect; }
146
147
  /// Return the value the effect is applied on, or nullptr if there isn't a
148
  /// known value being affected.
149
0
  Value getValue() const { return value; }
150
151
  /// Return the resource that the effect applies to.
152
0
  Resource *getResource() const { return resource; }
153
154
private:
155
  /// The specific effect being applied.
156
  EffectT *effect;
157
158
  /// The resource that the given value resides in.
159
  Resource *resource;
160
161
  /// The value that the effect applies to. This is optionally null.
162
  Value value;
163
};
164
} // namespace SideEffects
165
166
//===----------------------------------------------------------------------===//
167
// SideEffect Traits
168
//===----------------------------------------------------------------------===//
169
170
namespace OpTrait {
171
/// This trait indicates that the side effects of an operation includes the
172
/// effects of operations nested within its regions. If the operation has no
173
/// derived effects interfaces, the operation itself can be assumed to have no
174
/// side effects.
175
template <typename ConcreteType>
176
class HasRecursiveSideEffects
177
    : public TraitBase<ConcreteType, HasRecursiveSideEffects> {};
178
} // namespace OpTrait
179
180
//===----------------------------------------------------------------------===//
181
// Operation Memory-Effect Modeling
182
//===----------------------------------------------------------------------===//
183
184
namespace MemoryEffects {
185
/// This class represents the base class used for memory effects.
186
struct Effect : public SideEffects::Effect {
187
  using SideEffects::Effect::Effect;
188
189
  /// A base class for memory effects that provides helper utilities.
190
  template <typename DerivedEffect>
191
  using Base = SideEffects::Effect::Base<DerivedEffect, Effect>;
192
193
  static bool classof(const SideEffects::Effect *effect);
194
};
195
using EffectInstance = SideEffects::EffectInstance<Effect>;
196
197
/// The following effect indicates that the operation allocates from some
198
/// resource. An 'allocate' effect implies only allocation of the resource, and
199
/// not any visible mutation or dereference.
200
struct Allocate : public Effect::Base<Allocate> {};
201
202
/// The following effect indicates that the operation frees some resource that
203
/// has been allocated. An 'allocate' effect implies only de-allocation of the
204
/// resource, and not any visible allocation, mutation or dereference.
205
struct Free : public Effect::Base<Free> {};
206
207
/// The following effect indicates that the operation reads from some resource.
208
/// A 'read' effect implies only dereferencing of the resource, and not any
209
/// visible mutation.
210
struct Read : public Effect::Base<Read> {};
211
212
/// The following effect indicates that the operation writes to some resource. A
213
/// 'write' effect implies only mutating a resource, and not any visible
214
/// dereference or read.
215
struct Write : public Effect::Base<Write> {};
216
} // namespace MemoryEffects
217
218
//===----------------------------------------------------------------------===//
219
// SideEffect Interfaces
220
//===----------------------------------------------------------------------===//
221
222
/// Include the definitions of the side effect interfaces.
223
#include "mlir/Interfaces/SideEffectInterfaces.h.inc"
224
225
//===----------------------------------------------------------------------===//
226
// SideEffect Utilities
227
//===----------------------------------------------------------------------===//
228
229
/// Return true if the given operation is unused, and has no side effects on
230
/// memory that prevent erasing.
231
bool isOpTriviallyDead(Operation *op);
232
233
/// Return true if the given operation would be dead if unused, and has no side
234
/// effects on memory that would prevent erasing. This is equivalent to checking
235
/// `isOpTriviallyDead` if `op` was unused.
236
bool wouldOpBeTriviallyDead(Operation *op);
237
238
} // end namespace mlir
239
240
#endif // MLIR_INTERFACES_SIDEEFFECTS_H