MLIR  15.0.0git
SCFToOpenMP.cpp
Go to the documentation of this file.
1 //===- SCFToOpenMP.cpp - Structured Control Flow to OpenMP conversion -----===//
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 implements a pass to convert scf.parallel operations into OpenMP
10 // parallel loops.
11 //
12 //===----------------------------------------------------------------------===//
13 
15 #include "../PassDetail.h"
24 #include "mlir/IR/SymbolTable.h"
26 
27 using namespace mlir;
28 
29 /// Matches a block containing a "simple" reduction. The expected shape of the
30 /// block is as follows.
31 ///
32 /// ^bb(%arg0, %arg1):
33 /// %0 = OpTy(%arg0, %arg1)
34 /// scf.reduce.return %0
35 template <typename... OpTy>
36 static bool matchSimpleReduction(Block &block) {
37  if (block.empty() || llvm::hasSingleElement(block) ||
38  std::next(block.begin(), 2) != block.end())
39  return false;
40 
41  if (block.getNumArguments() != 2)
42  return false;
43 
44  SmallVector<Operation *, 4> combinerOps;
45  Value reducedVal = matchReduction({block.getArguments()[1]},
46  /*redPos=*/0, combinerOps);
47 
48  if (!reducedVal || !reducedVal.isa<BlockArgument>() ||
49  combinerOps.size() != 1)
50  return false;
51 
52  return isa<OpTy...>(combinerOps[0]) &&
53  isa<scf::ReduceReturnOp>(block.back()) &&
54  block.front().getOperands() == block.getArguments();
55 }
56 
57 /// Matches a block containing a select-based min/max reduction. The types of
58 /// select and compare operations are provided as template arguments. The
59 /// comparison predicates suitable for min and max are provided as function
60 /// arguments. If a reduction is matched, `ifMin` will be set if the reduction
61 /// compute the minimum and unset if it computes the maximum, otherwise it
62 /// remains unmodified. The expected shape of the block is as follows.
63 ///
64 /// ^bb(%arg0, %arg1):
65 /// %0 = CompareOpTy(<one-of-predicates>, %arg0, %arg1)
66 /// %1 = SelectOpTy(%0, %arg0, %arg1) // %arg0, %arg1 may be swapped here.
67 /// scf.reduce.return %1
68 template <
69  typename CompareOpTy, typename SelectOpTy,
70  typename Predicate = decltype(std::declval<CompareOpTy>().getPredicate())>
71 static bool
72 matchSelectReduction(Block &block, ArrayRef<Predicate> lessThanPredicates,
73  ArrayRef<Predicate> greaterThanPredicates, bool &isMin) {
74  static_assert(
76  "only arithmetic and llvm select ops are supported");
77 
78  // Expect exactly three operations in the block.
79  if (block.empty() || llvm::hasSingleElement(block) ||
80  std::next(block.begin(), 2) == block.end() ||
81  std::next(block.begin(), 3) != block.end())
82  return false;
83 
84  // Check op kinds.
85  auto compare = dyn_cast<CompareOpTy>(block.front());
86  auto select = dyn_cast<SelectOpTy>(block.front().getNextNode());
87  auto terminator = dyn_cast<scf::ReduceReturnOp>(block.back());
88  if (!compare || !select || !terminator)
89  return false;
90 
91  // Block arguments must be compared.
92  if (compare->getOperands() != block.getArguments())
93  return false;
94 
95  // Detect whether the comparison is less-than or greater-than, otherwise bail.
96  bool isLess;
97  if (llvm::is_contained(lessThanPredicates, compare.getPredicate())) {
98  isLess = true;
99  } else if (llvm::is_contained(greaterThanPredicates,
100  compare.getPredicate())) {
101  isLess = false;
102  } else {
103  return false;
104  }
105 
106  if (select.getCondition() != compare.getResult())
107  return false;
108 
109  // Detect if the operands are swapped between cmpf and select. Match the
110  // comparison type with the requested type or with the opposite of the
111  // requested type if the operands are swapped. Use generic accessors because
112  // std and LLVM versions of select have different operand names but identical
113  // positions.
114  constexpr unsigned kTrueValue = 1;
115  constexpr unsigned kFalseValue = 2;
116  bool sameOperands = select.getOperand(kTrueValue) == compare.getLhs() &&
117  select.getOperand(kFalseValue) == compare.getRhs();
118  bool swappedOperands = select.getOperand(kTrueValue) == compare.getRhs() &&
119  select.getOperand(kFalseValue) == compare.getLhs();
120  if (!sameOperands && !swappedOperands)
121  return false;
122 
123  if (select.getResult() != terminator.getResult())
124  return false;
125 
126  // The reduction is a min if it uses less-than predicates with same operands
127  // or greather-than predicates with swapped operands. Similarly for max.
128  isMin = (isLess && sameOperands) || (!isLess && swappedOperands);
129  return isMin || (isLess & swappedOperands) || (!isLess && sameOperands);
130 }
131 
132 /// Returns the float semantics for the given float type.
133 static const llvm::fltSemantics &fltSemanticsForType(FloatType type) {
134  if (type.isF16())
135  return llvm::APFloat::IEEEhalf();
136  if (type.isF32())
137  return llvm::APFloat::IEEEsingle();
138  if (type.isF64())
139  return llvm::APFloat::IEEEdouble();
140  if (type.isF128())
141  return llvm::APFloat::IEEEquad();
142  if (type.isBF16())
143  return llvm::APFloat::BFloat();
144  if (type.isF80())
145  return llvm::APFloat::x87DoubleExtended();
146  llvm_unreachable("unknown float type");
147 }
148 
149 /// Returns an attribute with the minimum (if `min` is set) or the maximum value
150 /// (otherwise) for the given float type.
151 static Attribute minMaxValueForFloat(Type type, bool min) {
152  auto fltType = type.cast<FloatType>();
153  return FloatAttr::get(
154  type, llvm::APFloat::getLargest(fltSemanticsForType(fltType), min));
155 }
156 
157 /// Returns an attribute with the signed integer minimum (if `min` is set) or
158 /// the maximum value (otherwise) for the given integer type, regardless of its
159 /// signedness semantics (only the width is considered).
161  auto intType = type.cast<IntegerType>();
162  unsigned bitwidth = intType.getWidth();
163  return IntegerAttr::get(type, min ? llvm::APInt::getSignedMinValue(bitwidth)
164  : llvm::APInt::getSignedMaxValue(bitwidth));
165 }
166 
167 /// Returns an attribute with the unsigned integer minimum (if `min` is set) or
168 /// the maximum value (otherwise) for the given integer type, regardless of its
169 /// signedness semantics (only the width is considered).
171  auto intType = type.cast<IntegerType>();
172  unsigned bitwidth = intType.getWidth();
173  return IntegerAttr::get(type, min ? llvm::APInt::getNullValue(bitwidth)
174  : llvm::APInt::getAllOnesValue(bitwidth));
175 }
176 
177 /// Creates an OpenMP reduction declaration and inserts it into the provided
178 /// symbol table. The declaration has a constant initializer with the neutral
179 /// value `initValue`, and the reduction combiner carried over from `reduce`.
180 static omp::ReductionDeclareOp createDecl(PatternRewriter &builder,
181  SymbolTable &symbolTable,
182  scf::ReduceOp reduce,
183  Attribute initValue) {
184  OpBuilder::InsertionGuard guard(builder);
185  auto decl = builder.create<omp::ReductionDeclareOp>(
186  reduce.getLoc(), "__scf_reduction", reduce.getOperand().getType());
187  symbolTable.insert(decl);
188 
189  Type type = reduce.getOperand().getType();
190  builder.createBlock(&decl.initializerRegion(), decl.initializerRegion().end(),
191  {type}, {reduce.getOperand().getLoc()});
192  builder.setInsertionPointToEnd(&decl.initializerRegion().back());
193  Value init =
194  builder.create<LLVM::ConstantOp>(reduce.getLoc(), type, initValue);
195  builder.create<omp::YieldOp>(reduce.getLoc(), init);
196 
197  Operation *terminator = &reduce.getRegion().front().back();
198  assert(isa<scf::ReduceReturnOp>(terminator) &&
199  "expected reduce op to be terminated by redure return");
200  builder.setInsertionPoint(terminator);
201  builder.replaceOpWithNewOp<omp::YieldOp>(terminator,
202  terminator->getOperands());
203  builder.inlineRegionBefore(reduce.getRegion(), decl.reductionRegion(),
204  decl.reductionRegion().end());
205  return decl;
206 }
207 
208 /// Adds an atomic reduction combiner to the given OpenMP reduction declaration
209 /// using llvm.atomicrmw of the given kind.
210 static omp::ReductionDeclareOp addAtomicRMW(OpBuilder &builder,
211  LLVM::AtomicBinOp atomicKind,
212  omp::ReductionDeclareOp decl,
213  scf::ReduceOp reduce) {
214  OpBuilder::InsertionGuard guard(builder);
215  Type type = reduce.getOperand().getType();
216  Type ptrType = LLVM::LLVMPointerType::get(type);
217  Location reduceOperandLoc = reduce.getOperand().getLoc();
218  builder.createBlock(&decl.atomicReductionRegion(),
219  decl.atomicReductionRegion().end(), {ptrType, ptrType},
220  {reduceOperandLoc, reduceOperandLoc});
221  Block *atomicBlock = &decl.atomicReductionRegion().back();
222  builder.setInsertionPointToEnd(atomicBlock);
223  Value loaded = builder.create<LLVM::LoadOp>(reduce.getLoc(),
224  atomicBlock->getArgument(1));
225  builder.create<LLVM::AtomicRMWOp>(reduce.getLoc(), type, atomicKind,
226  atomicBlock->getArgument(0), loaded,
227  LLVM::AtomicOrdering::monotonic);
228  builder.create<omp::YieldOp>(reduce.getLoc(), ArrayRef<Value>());
229  return decl;
230 }
231 
232 /// Creates an OpenMP reduction declaration that corresponds to the given SCF
233 /// reduction and returns it. Recognizes common reductions in order to identify
234 /// the neutral value, necessary for the OpenMP declaration. If the reduction
235 /// cannot be recognized, returns null.
236 static omp::ReductionDeclareOp declareReduction(PatternRewriter &builder,
237  scf::ReduceOp reduce) {
238  Operation *container = SymbolTable::getNearestSymbolTable(reduce);
239  SymbolTable symbolTable(container);
240 
241  // Insert reduction declarations in the symbol-table ancestor before the
242  // ancestor of the current insertion point.
243  Operation *insertionPoint = reduce;
244  while (insertionPoint->getParentOp() != container)
245  insertionPoint = insertionPoint->getParentOp();
246  OpBuilder::InsertionGuard guard(builder);
247  builder.setInsertionPoint(insertionPoint);
248 
249  assert(llvm::hasSingleElement(reduce.getRegion()) &&
250  "expected reduction region to have a single element");
251 
252  // Match simple binary reductions that can be expressed with atomicrmw.
253  Type type = reduce.getOperand().getType();
254  Block &reduction = reduce.getRegion().front();
255  if (matchSimpleReduction<arith::AddFOp, LLVM::FAddOp>(reduction)) {
256  omp::ReductionDeclareOp decl = createDecl(builder, symbolTable, reduce,
257  builder.getFloatAttr(type, 0.0));
258  return addAtomicRMW(builder, LLVM::AtomicBinOp::fadd, decl, reduce);
259  }
260  if (matchSimpleReduction<arith::AddIOp, LLVM::AddOp>(reduction)) {
261  omp::ReductionDeclareOp decl = createDecl(builder, symbolTable, reduce,
262  builder.getIntegerAttr(type, 0));
263  return addAtomicRMW(builder, LLVM::AtomicBinOp::add, decl, reduce);
264  }
265  if (matchSimpleReduction<arith::OrIOp, LLVM::OrOp>(reduction)) {
266  omp::ReductionDeclareOp decl = createDecl(builder, symbolTable, reduce,
267  builder.getIntegerAttr(type, 0));
268  return addAtomicRMW(builder, LLVM::AtomicBinOp::_or, decl, reduce);
269  }
270  if (matchSimpleReduction<arith::XOrIOp, LLVM::XOrOp>(reduction)) {
271  omp::ReductionDeclareOp decl = createDecl(builder, symbolTable, reduce,
272  builder.getIntegerAttr(type, 0));
273  return addAtomicRMW(builder, LLVM::AtomicBinOp::_xor, decl, reduce);
274  }
275  if (matchSimpleReduction<arith::AndIOp, LLVM::AndOp>(reduction)) {
276  omp::ReductionDeclareOp decl = createDecl(
277  builder, symbolTable, reduce,
278  builder.getIntegerAttr(
279  type, llvm::APInt::getAllOnesValue(type.getIntOrFloatBitWidth())));
280  return addAtomicRMW(builder, LLVM::AtomicBinOp::_and, decl, reduce);
281  }
282 
283  // Match simple binary reductions that cannot be expressed with atomicrmw.
284  // TODO: add atomic region using cmpxchg (which needs atomic load to be
285  // available as an op).
286  if (matchSimpleReduction<arith::MulFOp, LLVM::FMulOp>(reduction)) {
287  return createDecl(builder, symbolTable, reduce,
288  builder.getFloatAttr(type, 1.0));
289  }
290 
291  // Match select-based min/max reductions.
292  bool isMin;
293  if (matchSelectReduction<arith::CmpFOp, arith::SelectOp>(
294  reduction, {arith::CmpFPredicate::OLT, arith::CmpFPredicate::OLE},
295  {arith::CmpFPredicate::OGT, arith::CmpFPredicate::OGE}, isMin) ||
296  matchSelectReduction<LLVM::FCmpOp, LLVM::SelectOp>(
297  reduction, {LLVM::FCmpPredicate::olt, LLVM::FCmpPredicate::ole},
298  {LLVM::FCmpPredicate::ogt, LLVM::FCmpPredicate::oge}, isMin)) {
299  return createDecl(builder, symbolTable, reduce,
300  minMaxValueForFloat(type, !isMin));
301  }
302  if (matchSelectReduction<arith::CmpIOp, arith::SelectOp>(
303  reduction, {arith::CmpIPredicate::slt, arith::CmpIPredicate::sle},
304  {arith::CmpIPredicate::sgt, arith::CmpIPredicate::sge}, isMin) ||
305  matchSelectReduction<LLVM::ICmpOp, LLVM::SelectOp>(
306  reduction, {LLVM::ICmpPredicate::slt, LLVM::ICmpPredicate::sle},
307  {LLVM::ICmpPredicate::sgt, LLVM::ICmpPredicate::sge}, isMin)) {
308  omp::ReductionDeclareOp decl = createDecl(
309  builder, symbolTable, reduce, minMaxValueForSignedInt(type, !isMin));
310  return addAtomicRMW(builder,
312  decl, reduce);
313  }
314  if (matchSelectReduction<arith::CmpIOp, arith::SelectOp>(
315  reduction, {arith::CmpIPredicate::ult, arith::CmpIPredicate::ule},
316  {arith::CmpIPredicate::ugt, arith::CmpIPredicate::uge}, isMin) ||
317  matchSelectReduction<LLVM::ICmpOp, LLVM::SelectOp>(
318  reduction, {LLVM::ICmpPredicate::ugt, LLVM::ICmpPredicate::ule},
319  {LLVM::ICmpPredicate::ugt, LLVM::ICmpPredicate::uge}, isMin)) {
320  omp::ReductionDeclareOp decl = createDecl(
321  builder, symbolTable, reduce, minMaxValueForUnsignedInt(type, !isMin));
322  return addAtomicRMW(
323  builder, isMin ? LLVM::AtomicBinOp::umin : LLVM::AtomicBinOp::umax,
324  decl, reduce);
325  }
326 
327  return nullptr;
328 }
329 
330 namespace {
331 
332 struct ParallelOpLowering : public OpRewritePattern<scf::ParallelOp> {
334 
335  LogicalResult matchAndRewrite(scf::ParallelOp parallelOp,
336  PatternRewriter &rewriter) const override {
337  // Declare reductions.
338  // TODO: consider checking it here is already a compatible reduction
339  // declaration and use it instead of redeclaring.
340  SmallVector<Attribute> reductionDeclSymbols;
341  for (auto reduce : parallelOp.getOps<scf::ReduceOp>()) {
342  omp::ReductionDeclareOp decl = declareReduction(rewriter, reduce);
343  if (!decl)
344  return failure();
345  reductionDeclSymbols.push_back(
346  SymbolRefAttr::get(rewriter.getContext(), decl.sym_name()));
347  }
348 
349  // Allocate reduction variables. Make sure the we don't overflow the stack
350  // with local `alloca`s by saving and restoring the stack pointer.
351  Location loc = parallelOp.getLoc();
352  Value one = rewriter.create<LLVM::ConstantOp>(
353  loc, rewriter.getIntegerType(64), rewriter.getI64IntegerAttr(1));
354  SmallVector<Value> reductionVariables;
355  reductionVariables.reserve(parallelOp.getNumReductions());
356  for (Value init : parallelOp.getInitVals()) {
357  assert((LLVM::isCompatibleType(init.getType()) ||
358  init.getType().isa<LLVM::PointerElementTypeInterface>()) &&
359  "cannot create a reduction variable if the type is not an LLVM "
360  "pointer element");
361  Value storage = rewriter.create<LLVM::AllocaOp>(
362  loc, LLVM::LLVMPointerType::get(init.getType()), one, 0);
363  rewriter.create<LLVM::StoreOp>(loc, init, storage);
364  reductionVariables.push_back(storage);
365  }
366 
367  // Replace the reduction operations contained in this loop. Must be done
368  // here rather than in a separate pattern to have access to the list of
369  // reduction variables.
370  for (auto pair :
371  llvm::zip(parallelOp.getOps<scf::ReduceOp>(), reductionVariables)) {
372  OpBuilder::InsertionGuard guard(rewriter);
373  scf::ReduceOp reduceOp = std::get<0>(pair);
374  rewriter.setInsertionPoint(reduceOp);
375  rewriter.replaceOpWithNewOp<omp::ReductionOp>(
376  reduceOp, reduceOp.getOperand(), std::get<1>(pair));
377  }
378 
379  // Create the parallel wrapper.
380  auto ompParallel = rewriter.create<omp::ParallelOp>(loc);
381  {
382 
383  OpBuilder::InsertionGuard guard(rewriter);
384  rewriter.createBlock(&ompParallel.region());
385 
386  // Replace the loop.
387  {
388  OpBuilder::InsertionGuard allocaGuard(rewriter);
389  auto loop = rewriter.create<omp::WsLoopOp>(
390  parallelOp.getLoc(), parallelOp.getLowerBound(),
391  parallelOp.getUpperBound(), parallelOp.getStep());
392  rewriter.create<omp::TerminatorOp>(loc);
393 
394  rewriter.inlineRegionBefore(parallelOp.getRegion(), loop.region(),
395  loop.region().begin());
396 
397  Block *ops = rewriter.splitBlock(&*loop.region().begin(),
398  loop.region().begin()->begin());
399 
400  rewriter.setInsertionPointToStart(&*loop.region().begin());
401 
402  auto scope = rewriter.create<memref::AllocaScopeOp>(parallelOp.getLoc(),
403  TypeRange());
404  rewriter.create<omp::YieldOp>(loc, ValueRange());
405  Block *scopeBlock = rewriter.createBlock(&scope.getBodyRegion());
406  rewriter.mergeBlocks(ops, scopeBlock);
407  auto oldYield = cast<scf::YieldOp>(scopeBlock->getTerminator());
408  rewriter.setInsertionPointToEnd(&*scope.getBodyRegion().begin());
409  rewriter.replaceOpWithNewOp<memref::AllocaScopeReturnOp>(
410  oldYield, oldYield->getOperands());
411  if (!reductionVariables.empty()) {
412  loop.reductionsAttr(
413  ArrayAttr::get(rewriter.getContext(), reductionDeclSymbols));
414  loop.reduction_varsMutable().append(reductionVariables);
415  }
416  }
417  }
418 
419  // Load loop results.
420  SmallVector<Value> results;
421  results.reserve(reductionVariables.size());
422  for (Value variable : reductionVariables) {
423  Value res = rewriter.create<LLVM::LoadOp>(loc, variable);
424  results.push_back(res);
425  }
426  rewriter.replaceOp(parallelOp, results);
427 
428  return success();
429  }
430 };
431 
432 /// Applies the conversion patterns in the given function.
433 static LogicalResult applyPatterns(ModuleOp module) {
434  ConversionTarget target(*module.getContext());
435  target.addIllegalOp<scf::ReduceOp, scf::ReduceReturnOp, scf::ParallelOp>();
436  target.addLegalDialect<omp::OpenMPDialect, LLVM::LLVMDialect,
437  memref::MemRefDialect>();
438 
439  RewritePatternSet patterns(module.getContext());
440  patterns.add<ParallelOpLowering>(module.getContext());
441  FrozenRewritePatternSet frozen(std::move(patterns));
442  return applyPartialConversion(module, target, frozen);
443 }
444 
445 /// A pass converting SCF operations to OpenMP operations.
446 struct SCFToOpenMPPass : public ConvertSCFToOpenMPBase<SCFToOpenMPPass> {
447  /// Pass entry point.
448  void runOnOperation() override {
449  if (failed(applyPatterns(getOperation())))
450  signalPassFailure();
451  }
452 };
453 
454 } // namespace
455 
456 std::unique_ptr<OperationPass<ModuleOp>> mlir::createConvertSCFToOpenMPPass() {
457  return std::make_unique<SCFToOpenMPPass>();
458 }
TODO: Remove this file when SCCP and integer range analysis have been ported to the new framework...
bool isF32() const
Definition: Types.cpp:23
iterator begin()
Definition: Block.h:134
MLIRContext * getContext() const
Definition: Builders.h:54
A special type of RewriterBase that coordinates the application of a rewrite pattern on the current I...
Definition: PatternMatch.h:600
Operation is a basic unit of execution within MLIR.
Definition: Operation.h:28
LogicalResult applyPartialConversion(ArrayRef< Operation *> ops, ConversionTarget &target, const FrozenRewritePatternSet &patterns, DenseSet< Operation *> *unconvertedOps=nullptr)
Below we define several entry points for operation conversion.
Operation & back()
Definition: Block.h:143
operand_range getOperands()
Returns an iterator on the underlying Value&#39;s.
Definition: Operation.h:302
This class represents a frozen set of patterns that can be processed by a pattern applicator...
Block represents an ordered list of Operations.
Definition: Block.h:29
Block & front()
Definition: Region.h:65
void setInsertionPoint(Block *block, Block::iterator insertPoint)
Set the insertion point to the specified location.
Definition: Builders.h:336
virtual Block * splitBlock(Block *block, Block::iterator before)
Split the operations starting at "before" (inclusive) out of the given block into a new block...
static Attribute minMaxValueForUnsignedInt(Type type, bool min)
Returns an attribute with the unsigned integer minimum (if min is set) or the maximum value (otherwis...
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value...
Definition: LogicalResult.h:72
std::unique_ptr< OperationPass< ModuleOp > > createConvertSCFToOpenMPPass()
Operation & front()
Definition: Block.h:144
static bool matchSelectReduction(Block &block, ArrayRef< Predicate > lessThanPredicates, ArrayRef< Predicate > greaterThanPredicates, bool &isMin)
Matches a block containing a select-based min/max reduction.
Definition: SCFToOpenMP.cpp:72
static Attribute minMaxValueForFloat(Type type, bool min)
Returns an attribute with the minimum (if min is set) or the maximum value (otherwise) for the given ...
virtual void inlineRegionBefore(Region &region, Region &parent, Region::iterator before)
Move the blocks that belong to "region" before the given position in another region "parent"...
BlockArgument getArgument(unsigned i)
Definition: Block.h:120
void addIllegalOp(OperationName op)
Register the given operation as illegal, i.e.
static constexpr const bool value
StringAttr insert(Operation *symbol, Block::iterator insertPt={})
Insert a new symbol into the table, and rename it as necessary to avoid collisions.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:48
static bool matchSimpleReduction(Block &block)
Matches a block containing a "simple" reduction.
Definition: SCFToOpenMP.cpp:36
FloatAttr getFloatAttr(Type type, double value)
Definition: Builders.cpp:193
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:56
Operation * create(const OperationState &state)
Creates an operation given the fields represented as an OperationState.
Definition: Builders.cpp:380
This class represents an efficient way to signal success or failure.
Definition: LogicalResult.h:26
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:62
bool isCompatibleType(Type type)
Returns true if the given type is compatible with the LLVM dialect.
Definition: LLVMTypes.cpp:822
virtual void replaceOp(Operation *op, ValueRange newValues)
This method replaces the results of the operation with the specified list of values.
bool isF80() const
Definition: Types.cpp:25
IntegerAttr getIntegerAttr(Type type, int64_t value)
Definition: Builders.cpp:170
IntegerAttr getI64IntegerAttr(int64_t value)
Definition: Builders.cpp:99
iterator end()
Definition: Block.h:135
unsigned getNumArguments()
Definition: Block.h:119
bool isF16() const
Definition: Types.cpp:22
Attributes are known-constant values of operations.
Definition: Attributes.h:24
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
Definition: Operation.h:172
IntegerType getIntegerType(unsigned width)
Definition: Builders.cpp:58
static LLVMPointerType get(MLIRContext *context, unsigned addressSpace=0)
Gets or creates an instance of LLVM dialect pointer type pointing to an object of pointee type in the...
Definition: LLVMTypes.cpp:188
This class provides an abstraction over the various different ranges of value types.
Definition: TypeRange.h:38
Value matchReduction(ArrayRef< BlockArgument > iterCarriedArgs, unsigned redPos, SmallVectorImpl< Operation *> &combinerOps)
Utility to match a generic reduction given a list of iteration-carried arguments, iterCarriedArgs and...
bool isF128() const
Definition: Types.cpp:26
BlockArgListType getArguments()
Definition: Block.h:76
This class represents an argument of a Block.
Definition: Value.h:300
static omp::ReductionDeclareOp createDecl(PatternRewriter &builder, SymbolTable &symbolTable, scf::ReduceOp reduce, Attribute initValue)
Creates an OpenMP reduction declaration and inserts it into the provided symbol table.
bool empty()
Definition: Block.h:139
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition: Types.h:72
static Value min(ImplicitLocOpBuilder &builder, Value value, Value bound)
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition: Value.h:85
bool isF64() const
Definition: Types.cpp:24
OpRewritePattern is a wrapper around RewritePattern that allows for matching and rewriting against an...
Definition: PatternMatch.h:355
void setInsertionPointToStart(Block *block)
Sets the insertion point to the start of the specified block.
Definition: Builders.h:369
bool isa() const
Definition: Value.h:90
RAII guard to reset the insertion point of the builder when destroyed.
Definition: Builders.h:286
RewritePatternSet & add(ConstructorArg &&arg, ConstructorArgs &&... args)
Add an instance of each of the pattern types &#39;Ts&#39; to the pattern list with the given arguments...
OpTy replaceOpWithNewOp(Operation *op, Args &&...args)
Replaces the result op with a new op that is created without verification.
Definition: PatternMatch.h:451
static omp::ReductionDeclareOp declareReduction(PatternRewriter &builder, scf::ReduceOp reduce)
Creates an OpenMP reduction declaration that corresponds to the given SCF reduction and returns it...
unsigned getIntOrFloatBitWidth() const
Return the bit width of an integer or a float type, assert failure on other types.
Definition: Types.cpp:91
This class allows for representing and managing the symbol table used by operations with the &#39;SymbolT...
Definition: SymbolTable.h:23
static Operation * getNearestSymbolTable(Operation *from)
Returns the nearest symbol table from a given operation from.
void setInsertionPointToEnd(Block *block)
Sets the insertion point to the end of the specified block.
Definition: Builders.h:374
static void applyPatterns(Region &region, const FrozenRewritePatternSet &patterns, ArrayRef< ReductionNode::Range > rangeToKeep, bool eraseOpNotInRange)
We implicitly number each operation in the region and if an operation&#39;s number falls into rangeToKeep...
static omp::ReductionDeclareOp addAtomicRMW(OpBuilder &builder, LLVM::AtomicBinOp atomicKind, omp::ReductionDeclareOp decl, scf::ReduceOp reduce)
Adds an atomic reduction combiner to the given OpenMP reduction declaration using llvm...
This class describes a specific conversion target.
Block * createBlock(Region *parent, Region::iterator insertPt={}, TypeRange argTypes=llvm::None, ArrayRef< Location > locs=llvm::None)
Add new block with &#39;argTypes&#39; arguments and set the insertion point to the end of it...
Definition: Builders.cpp:353
int compare(Fraction x, Fraction y)
Three-way comparison between two fractions.
Definition: Fraction.h:54
static Attribute minMaxValueForSignedInt(Type type, bool min)
Returns an attribute with the signed integer minimum (if min is set) or the maximum value (otherwise)...
static const llvm::fltSemantics & fltSemanticsForType(FloatType type)
Returns the float semantics for the given float type.
virtual void mergeBlocks(Block *source, Block *dest, ValueRange argValues=llvm::None)
Merge the operations of block &#39;source&#39; into the end of block &#39;dest&#39;.
This class helps build Operations.
Definition: Builders.h:184
This class provides an abstraction over the different types of ranges over Values.
Region & getRegion(unsigned index)
Returns the region held by this operation at position &#39;index&#39;.
Definition: Operation.h:484
static Value max(ImplicitLocOpBuilder &builder, Value value, Value bound)
bool isBF16() const
Definition: Types.cpp:21
U cast() const
Definition: Types.h:262