summaryrefslogtreecommitdiffstats
path: root/mlir/include/mlir/IR/Value.h
blob: 110c74f41f1235dbbf67ac004c137b2c337e08b1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
//===- Value.h - Base of the SSA Value hierarchy ----------------*- C++ -*-===//
//
// Copyright 2019 The MLIR Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// =============================================================================
//
// This file defines generic Value type and manipulation utilities.
//
//===----------------------------------------------------------------------===//

#ifndef MLIR_IR_VALUE_H
#define MLIR_IR_VALUE_H

#include "mlir/IR/Types.h"
#include "mlir/IR/UseDefLists.h"
#include "mlir/Support/LLVM.h"

namespace mlir {
class Block;
class Operation;
class Region;
class Value;

/// Operands contain a Value.
using OpOperand = IROperandImpl<Value>;

/// This is the common base class for all SSA values in the MLIR system,
/// representing a computable value that has a type and a set of users.
///
class Value : public IRObjectWithUseList {
public:
  /// This enumerates all of the SSA value kinds in the MLIR system.
  enum class Kind {
    BlockArgument, // block argument
    OpResult,      // operation result
  };

  ~Value() {}

  Kind getKind() const { return typeAndKind.getInt(); }

  Type getType() const { return typeAndKind.getPointer(); }

  /// Utility to get the associated MLIRContext that this value is defined in.
  MLIRContext *getContext() const { return getType().getContext(); }

  /// Mutate the type of this Value to be of the specified type.
  ///
  /// Note that this is an extremely dangerous operation which can create
  /// completely invalid IR very easily.  It is strongly recommended that you
  /// recreate IR objects with the right types instead of mutating them in
  /// place.
  void setType(Type newType) { typeAndKind.setPointer(newType); }

  /// Replace all uses of 'this' value with the new value, updating anything in
  /// the IR that uses 'this' to use the other value instead.  When this returns
  /// there are zero uses of 'this'.
  void replaceAllUsesWith(Value *newValue) {
    IRObjectWithUseList::replaceAllUsesWith(newValue);
  }

  /// If this value is the result of an operation, return the operation that
  /// defines it.
  Operation *getDefiningOp();

  /// If this value is the result of an operation, use it as a location,
  /// otherwise return an unknown location.
  Location getLoc();

  /// Return the Region in which this Value is defined.
  Region *getParentRegion();

  using use_iterator = ValueUseIterator<OpOperand>;
  using use_range = llvm::iterator_range<use_iterator>;

  inline use_iterator use_begin();
  inline use_iterator use_end();

  /// Returns a range of all uses, which is useful for iterating over all uses.
  inline use_range getUses();

  void print(raw_ostream &os);
  void dump();

protected:
  Value(Kind kind, Type type) : typeAndKind(type, kind) {}

private:
  llvm::PointerIntPair<Type, 1, Kind> typeAndKind;
};

inline raw_ostream &operator<<(raw_ostream &os, Value &value) {
  value.print(os);
  return os;
}

// Utility functions for iterating through Value uses.
inline auto Value::use_begin() -> use_iterator {
  return use_iterator((OpOperand *)getFirstUse());
}

inline auto Value::use_end() -> use_iterator { return use_iterator(nullptr); }

inline auto Value::getUses() -> llvm::iterator_range<use_iterator> {
  return {use_begin(), use_end()};
}

/// Block arguments are values.
class BlockArgument : public Value {
public:
  static bool classof(const Value *value) {
    return const_cast<Value *>(value)->getKind() == Kind::BlockArgument;
  }

  Block *getOwner() { return owner; }

  /// Returns the number of this argument.
  unsigned getArgNumber();

private:
  friend class Block; // For access to private constructor.
  BlockArgument(Type type, Block *owner)
      : Value(Value::Kind::BlockArgument, type), owner(owner) {}

  /// The owner of this operand.
  /// TODO: can encode this more efficiently to avoid the space hit of this
  /// through bitpacking shenanigans.
  Block *const owner;
};

/// This is a value defined by a result of an operation.
class OpResult : public Value {
public:
  OpResult(Type type, Operation *owner)
      : Value(Value::Kind::OpResult, type), owner(owner) {}

  static bool classof(const Value *value) {
    return const_cast<Value *>(value)->getKind() == Kind::OpResult;
  }

  Operation *getOwner() { return owner; }

  /// Returns the number of this result.
  unsigned getResultNumber();

private:
  /// The owner of this operand.
  /// TODO: can encode this more efficiently to avoid the space hit of this
  /// through bitpacking shenanigans.
  Operation *const owner;
};

} // namespace mlir

#endif
OpenPOWER on IntegriCloud