Halide  19.0.0
Halide compiler and libraries
IR.h
Go to the documentation of this file.
1 #ifndef HALIDE_IR_H
2 #define HALIDE_IR_H
3 
4 /** \file
5  * Subtypes for Halide expressions (\ref Halide::Expr) and statements (\ref Halide::Internal::Stmt)
6  */
7 
8 #include <string>
9 #include <vector>
10 
11 #include "Buffer.h"
12 #include "Expr.h"
13 #include "FunctionPtr.h"
15 #include "ModulusRemainder.h"
16 #include "Parameter.h"
17 #include "PrefetchDirective.h"
18 #include "Reduction.h"
19 #include "Type.h"
20 
21 namespace Halide {
22 namespace Internal {
23 
24 class Function;
25 
26 /** The actual IR nodes begin here. Remember that all the Expr
27  * nodes also have a public "type" property */
28 
29 /** Cast a node from one type to another. Can't change vector widths. */
30 struct Cast : public ExprNode<Cast> {
32 
33  static Expr make(Type t, Expr v);
34 
36 
37  /** Check if the cast is equivalent to a reinterpret. */
38  bool is_reinterpret() const {
39  return (type.is_int_or_uint() &&
41  type.bits() == value.type().bits());
42  }
43 };
44 
45 /** Reinterpret value as another type, without affecting any of the bits
46  * (on little-endian systems). */
47 struct Reinterpret : public ExprNode<Reinterpret> {
49 
50  static Expr make(Type t, Expr v);
51 
53 };
54 
55 /** The sum of two expressions */
56 struct Add : public ExprNode<Add> {
57  Expr a, b;
58 
59  static Expr make(Expr a, Expr b);
60 
62 };
63 
64 /** The difference of two expressions */
65 struct Sub : public ExprNode<Sub> {
66  Expr a, b;
67 
68  static Expr make(Expr a, Expr b);
69 
71 };
72 
73 /** The product of two expressions */
74 struct Mul : public ExprNode<Mul> {
75  Expr a, b;
76 
77  static Expr make(Expr a, Expr b);
78 
80 };
81 
82 /** The ratio of two expressions */
83 struct Div : public ExprNode<Div> {
84  Expr a, b;
85 
86  static Expr make(Expr a, Expr b);
87 
89 };
90 
91 /** The remainder of a / b. Mostly equivalent to '%' in C, except that
92  * the result here is always positive. For floats, this is equivalent
93  * to calling fmod. */
94 struct Mod : public ExprNode<Mod> {
95  Expr a, b;
96 
97  static Expr make(Expr a, Expr b);
98 
100 };
101 
102 /** The lesser of two values. */
103 struct Min : public ExprNode<Min> {
104  Expr a, b;
105 
106  static Expr make(Expr a, Expr b);
107 
109 };
110 
111 /** The greater of two values */
112 struct Max : public ExprNode<Max> {
113  Expr a, b;
114 
115  static Expr make(Expr a, Expr b);
116 
118 };
119 
120 /** Is the first expression equal to the second */
121 struct EQ : public ExprNode<EQ> {
122  Expr a, b;
123 
124  static Expr make(Expr a, Expr b);
125 
127 };
128 
129 /** Is the first expression not equal to the second */
130 struct NE : public ExprNode<NE> {
131  Expr a, b;
132 
133  static Expr make(Expr a, Expr b);
134 
136 };
137 
138 /** Is the first expression less than the second. */
139 struct LT : public ExprNode<LT> {
140  Expr a, b;
141 
142  static Expr make(Expr a, Expr b);
143 
145 };
146 
147 /** Is the first expression less than or equal to the second. */
148 struct LE : public ExprNode<LE> {
149  Expr a, b;
150 
151  static Expr make(Expr a, Expr b);
152 
154 };
155 
156 /** Is the first expression greater than the second. */
157 struct GT : public ExprNode<GT> {
158  Expr a, b;
159 
160  static Expr make(Expr a, Expr b);
161 
163 };
164 
165 /** Is the first expression greater than or equal to the second. */
166 struct GE : public ExprNode<GE> {
167  Expr a, b;
168 
169  static Expr make(Expr a, Expr b);
170 
172 };
173 
174 /** Logical and - are both expressions true */
175 struct And : public ExprNode<And> {
176  Expr a, b;
177 
178  static Expr make(Expr a, Expr b);
179 
181 };
182 
183 /** Logical or - is at least one of the expression true */
184 struct Or : public ExprNode<Or> {
185  Expr a, b;
186 
187  static Expr make(Expr a, Expr b);
188 
190 };
191 
192 /** Logical not - true if the expression false */
193 struct Not : public ExprNode<Not> {
195 
196  static Expr make(Expr a);
197 
199 };
200 
201 /** A ternary operator. Evalutes 'true_value' and 'false_value',
202  * then selects between them based on 'condition'. Equivalent to
203  * the ternary operator in C. */
204 struct Select : public ExprNode<Select> {
206 
208 
210 };
211 
212 /** Load a value from a named symbol if predicate is true. The buffer
213  * is treated as an array of the 'type' of this Load node. That is,
214  * the buffer has no inherent type. The name may be the name of an
215  * enclosing allocation, an input or output buffer, or any other
216  * symbol of type Handle(). */
217 struct Load : public ExprNode<Load> {
218  std::string name;
219 
221 
222  // If it's a load from an image argument or compiled-in constant
223  // image, this will point to that
225 
226  // If it's a load from an image parameter, this points to that
228 
229  // The alignment of the index. If the index is a vector, this is
230  // the alignment of the first lane.
232 
233  static Expr make(Type type, const std::string &name,
236  Expr predicate,
238 
240 };
241 
242 /** A linear ramp vector node. This is vector with 'lanes' elements,
243  * where element i is 'base' + i*'stride'. This is a convenient way to
244  * pass around vectors without busting them up into individual
245  * elements. E.g. a dense vector load from a buffer can use a ramp
246  * node with stride 1 as the index. */
247 struct Ramp : public ExprNode<Ramp> {
249  int lanes;
250 
251  static Expr make(Expr base, Expr stride, int lanes);
252 
254 };
255 
256 /** A vector with 'lanes' elements, in which every element is
257  * 'value'. This is a special case of the ramp node above, in which
258  * the stride is zero. */
259 struct Broadcast : public ExprNode<Broadcast> {
261  int lanes;
262 
263  static Expr make(Expr value, int lanes);
264 
266 };
267 
268 /** A let expression, like you might find in a functional
269  * language. Within the expression \ref Let::body, instances of the Var
270  * node \ref Let::name refer to \ref Let::value. */
271 struct Let : public ExprNode<Let> {
272  std::string name;
274 
275  static Expr make(const std::string &name, Expr value, Expr body);
276 
278 };
279 
280 /** The statement form of a let node. Within the statement 'body',
281  * instances of the Var named 'name' refer to 'value' */
282 struct LetStmt : public StmtNode<LetStmt> {
283  std::string name;
286 
287  static Stmt make(const std::string &name, Expr value, Stmt body);
288 
290 };
291 
292 /** If the 'condition' is false, then evaluate and return the message,
293  * which should be a call to an error function. */
294 struct AssertStmt : public StmtNode<AssertStmt> {
295  // if condition then val else error out with message
298 
300 
302 };
303 
304 /** This node is a helpful annotation to do with permissions. If 'is_produce' is
305  * set to true, this represents a producer node which may also contain updates;
306  * otherwise, this represents a consumer node. If the producer node contains
307  * updates, the body of the node will be a block of 'produce' and 'update'
308  * in that order. In a producer node, the access is read-write only (or write
309  * only if it doesn't have updates). In a consumer node, the access is read-only.
310  * None of this is actually enforced, the node is purely for informative purposes
311  * to help out our analysis during lowering. For every unique ProducerConsumer,
312  * there is an associated Realize node with the same name that creates the buffer
313  * being read from or written to in the body of the ProducerConsumer.
314  */
315 struct ProducerConsumer : public StmtNode<ProducerConsumer> {
316  std::string name;
319 
320  static Stmt make(const std::string &name, bool is_producer, Stmt body);
321 
322  static Stmt make_produce(const std::string &name, Stmt body);
323  static Stmt make_consume(const std::string &name, Stmt body);
324 
326 };
327 
328 /** Store a 'value' to the buffer called 'name' at a given 'index' if
329  * 'predicate' is true. The buffer is interpreted as an array of the
330  * same type as 'value'. The name may be the name of an enclosing
331  * Allocate node, an output buffer, or any other symbol of type
332  * Handle(). */
333 struct Store : public StmtNode<Store> {
334  std::string name;
336  // If it's a store to an output buffer, then this parameter points to it.
338 
339  // The alignment of the index. If the index is a vector, this is
340  // the alignment of the first lane.
342 
343  static Stmt make(const std::string &name, Expr value, Expr index,
345 
347 };
348 
349 /** This defines the value of a function at a multi-dimensional
350  * location. You should think of it as a store to a multi-dimensional
351  * array. It gets lowered to a conventional Store node. The name must
352  * correspond to an output buffer or the name of an enclosing Realize
353  * node. */
354 struct Provide : public StmtNode<Provide> {
355  std::string name;
356  std::vector<Expr> values;
357  std::vector<Expr> args;
359 
360  static Stmt make(const std::string &name, const std::vector<Expr> &values, const std::vector<Expr> &args, const Expr &predicate);
361 
363 };
364 
365 /** Allocate a scratch area called with the given name, type, and
366  * size. The buffer lives for at most the duration of the body
367  * statement, within which it may or may not be freed explicitly with
368  * a Free node with a matching name. Allocation only occurs if the
369  * condition evaluates to true. Within the body of the allocation,
370  * defines a symbol with the given name and the type Handle(). */
371 struct Allocate : public StmtNode<Allocate> {
372  std::string name;
375  std::vector<Expr> extents;
376 
377  // A boolean condition that determines if the allocation needs to be made at all.
379 
380  // These override the code generator dependent malloc and free
381  // equivalents if provided. If the new_expr succeeds, that is it
382  // returns non-nullptr, the function named be free_function is
383  // guaranteed to be called. The free function signature must match
384  // that of the code generator dependent free (typically
385  // halide_free). If free_function is left empty, code generator
386  // default will be called.
388  std::string free_function;
389 
390  // Extra padding elements to allow for overreads. Elements in the padding
391  // have undetermined values, but are guaranteed safe to load.
392  int padding;
393 
395 
396  static Stmt make(const std::string &name, Type type, MemoryType memory_type,
397  const std::vector<Expr> &extents,
399  Expr new_expr = Expr(), const std::string &free_function = std::string(), int padding = 0);
400 
401  /** A routine to check if the extents are all constants, and if so verify
402  * the total size is less than 2^31 - 1. If the result is constant, but
403  * overflows, this routine asserts. This returns 0 if the extents are
404  * not all constants; otherwise, it returns the total constant allocation
405  * size. Does not include any padding bytes. */
406  static int32_t constant_allocation_size(const std::vector<Expr> &extents, const std::string &name);
408 
410 };
411 
412 /** Free the resources associated with the given buffer. */
413 struct Free : public StmtNode<Free> {
414  std::string name;
415 
416  static Stmt make(const std::string &name);
417 
419 };
420 
421 /** Allocate a multi-dimensional buffer of the given type and
422  * size. Create some scratch memory that will back the function 'name'
423  * over the range specified in 'bounds'. The bounds are a vector of
424  * (min, extent) pairs for each dimension. Allocation only occurs if
425  * the condition evaluates to true.
426  */
427 struct Realize : public StmtNode<Realize> {
428  std::string name;
429  std::vector<Type> types;
434 
435  static Stmt make(const std::string &name, const std::vector<Type> &types, MemoryType memory_type, const Region &bounds, Expr condition, Stmt body);
436 
438 };
439 
440 /** A sequence of statements to be executed in-order. 'first' is never
441  a Block, so this can be treated as a linked list. */
442 struct Block : public StmtNode<Block> {
444 
446 
447  /** Construct zero or more Blocks to invoke a list of statements in order.
448  * This method may not return a Block statement if stmts.size() <= 1. */
449  static Stmt make(const std::vector<Stmt> &stmts);
450 
452 };
453 
454 /** A pair of statements executed concurrently. Both statements are
455  * joined before the Stmt ends. This is the parallel equivalent to
456  * Block. */
457 struct Fork : public StmtNode<Fork> {
459 
461 
463 };
464 
465 /** An if-then-else block. 'else' may be undefined. */
466 struct IfThenElse : public StmtNode<IfThenElse> {
469 
471 
473 };
474 
475 /** Evaluate and discard an expression, presumably because it has some side-effect. */
476 struct Evaluate : public StmtNode<Evaluate> {
478 
479  static Stmt make(Expr v);
480 
482 };
483 
484 /** A function call. This can represent a call to some extern function
485  * (like sin), but it's also our multi-dimensional version of a Load,
486  * so it can be a load from an input image, or a call to another
487  * halide function. These two types of call nodes don't survive all
488  * the way down to code generation - the lowering process converts
489  * them to Load nodes. */
490 struct Call : public ExprNode<Call> {
491  std::string name;
492  std::vector<Expr> args;
493  typedef enum { Image, ///< A load from an input image
494  Extern, ///< A call to an external C-ABI function, possibly with side-effects
495  ExternCPlusPlus, ///< A call to an external C-ABI function, possibly with side-effects
496  PureExtern, ///< A call to a guaranteed-side-effect-free external function
497  Halide, ///< A call to a Func
498  Intrinsic, ///< A possibly-side-effecty compiler intrinsic, which has special handling during codegen
499  PureIntrinsic ///< A side-effect-free version of the above.
502 
503  // Halide uses calls internally to represent certain operations
504  // (instead of IR nodes). These are matched by name. Note that
505  // these are deliberately char* (rather than std::string) so that
506  // they can be referenced at static-initialization time without
507  // risking ambiguous initalization order; we use a typedef to simplify
508  // declaration.
509  typedef const char *const ConstString;
510 
511  // enums for various well-known intrinsics. (It is not *required* that all
512  // intrinsics have an enum entry here, but as a matter of style, it is recommended.)
513  // Note that these are only used in the API; inside the node, they are translated
514  // into a name. (To recover the name, call get_intrinsic_name().)
515  //
516  // Please keep this list sorted alphabetically; the specific enum values
517  // are *not* guaranteed to be stable across time.
518  enum IntrinsicOp {
528 
529  // Bundle multiple exprs together temporarily for analysis (e.g. CSE)
533 
534  // Concatenate bits of the args, with least significant bits as the
535  // first arg (i.e. little-endian)
543 
544  // Extract some contiguous slice of bits from the argument starting at
545  // the nth bit, counting from the least significant bit, with the number
546  // of bits determined by the return type.
580 
581  // Round a floating point value to nearest integer, with ties going to even
583 
597 
598  // Marks the point in lowering where the outermost skip stages checks
599  // should be introduced.
601 
602  // Takes a realization name and a loop variable. Declares that values of
603  // the realization that were stored on earlier loop iterations of the
604  // given loop are potentially loaded in this loop iteration somewhere
605  // after this point. Must occur inside a Realize node and For node of
606  // the given names but outside any corresponding ProducerConsumer
607  // nodes. Communicates to storage folding that sliding window took
608  // place.
610 
611  // Compute (arg[0] + arg[1]) / 2, assuming arg[0] < arg[1].
618 
619  // One-sided variants of widening_add, widening_mul, and widening_sub.
620  // arg[0] + widen(arg[1])
622  // arg[0] * widen(arg[1])
624  // arg[0] - widen(arg[1])
626 
632 
634 
635  IntrinsicOpCount // Sentinel: keep last.
636  };
637 
638  static const char *get_intrinsic_name(IntrinsicOp op);
639 
640  // We also declare some symbolic names for some of the runtime
641  // functions that we want to construct Call nodes to here to avoid
642  // magic string constants and the potential risk of typos.
664 
665  // If it's a call to another halide function, this call node holds
666  // a possibly-weak reference to that function.
668 
669  // If that function has multiple values, which value does this
670  // call node refer to?
672 
673  // If it's a call to an image, this call nodes hold a
674  // pointer to that image's buffer
676 
677  // If it's a call to an image parameter, this call node holds a
678  // pointer to that
680 
681  static Expr make(Type type, IntrinsicOp op, const std::vector<Expr> &args, CallType call_type,
683  const Buffer<> &image = Buffer<>(), Parameter param = Parameter());
684 
685  static Expr make(Type type, const std::string &name, const std::vector<Expr> &args, CallType call_type,
688 
689  /** Convenience constructor for calls to other halide functions */
690  static Expr make(const Function &func, const std::vector<Expr> &args, int idx = 0);
691 
692  /** Convenience constructor for loads from concrete images */
693  static Expr make(const Buffer<> &image, const std::vector<Expr> &args) {
694  return make(image.type(), image.name(), args, Image, FunctionPtr(), 0, image, Parameter());
695  }
696 
697  /** Convenience constructor for loads from images parameters */
698  static Expr make(const Parameter &param, const std::vector<Expr> &args) {
699  return make(param.type(), param.name(), args, Image, FunctionPtr(), 0, Buffer<>(), param);
700  }
701 
702  /** Check if a call node is pure within a pipeline, meaning that
703  * the same args always give the same result, and the calls can be
704  * reordered, duplicated, unified, etc without changing the
705  * meaning of anything. Not transitive - doesn't guarantee the
706  * args themselves are pure. An example of a pure Call node is
707  * sqrt. If in doubt, don't mark a Call node as pure. */
708  bool is_pure() const {
709  return (call_type == PureExtern ||
710  call_type == Image ||
712  }
713 
714  bool is_intrinsic() const {
715  return (call_type == Intrinsic ||
717  }
718 
719  bool is_intrinsic(IntrinsicOp op) const {
720  return is_intrinsic() && this->name == get_intrinsic_name(op);
721  }
722 
723  bool is_intrinsic(std::initializer_list<IntrinsicOp> intrinsics) const {
724  for (IntrinsicOp i : intrinsics) {
725  if (is_intrinsic(i)) {
726  return true;
727  }
728  }
729  return false;
730  }
731 
732  bool is_tag() const {
734  }
735 
736  /** Returns a pointer to a call node if the expression is a call to
737  * one of the requested intrinsics. */
738  static const Call *as_intrinsic(const Expr &e, std::initializer_list<IntrinsicOp> intrinsics) {
739  if (const Call *c = e.as<Call>()) {
740  for (IntrinsicOp i : intrinsics) {
741  if (c->is_intrinsic(i)) {
742  return c;
743  }
744  }
745  }
746  return nullptr;
747  }
748 
749  static const Call *as_tag(const Expr &e) {
751  }
752 
753  bool is_extern() const {
754  return (call_type == Extern ||
756  call_type == PureExtern);
757  }
758 
760 };
761 
762 /** A named variable. Might be a loop variable, function argument,
763  * parameter, reduction variable, or something defined by a Let or
764  * LetStmt node. */
765 struct Variable : public ExprNode<Variable> {
766  std::string name;
767 
768  /** References to scalar parameters, or to the dimensions of buffer
769  * parameters hang onto those expressions. */
771 
772  /** References to properties of literal image parameters. */
774 
775  /** Reduction variables hang onto their domains */
777 
778  static Expr make(Type type, const std::string &name) {
779  return make(type, name, Buffer<>(), Parameter(), ReductionDomain());
780  }
781 
782  static Expr make(Type type, const std::string &name, Parameter param) {
783  return make(type, name, Buffer<>(), std::move(param), ReductionDomain());
784  }
785 
786  static Expr make(Type type, const std::string &name, const Buffer<> &image) {
787  return make(type, name, image, Parameter(), ReductionDomain());
788  }
789 
790  static Expr make(Type type, const std::string &name, ReductionDomain reduction_domain) {
791  return make(type, name, Buffer<>(), Parameter(), std::move(reduction_domain));
792  }
793 
794  static Expr make(Type type, const std::string &name, Buffer<> image,
796 
798 };
799 
800 /** A for loop. Execute the 'body' statement for all values of the
801  * variable 'name' from 'min' to 'min + extent'. There are four
802  * types of For nodes. A 'Serial' for loop is a conventional
803  * one. In a 'Parallel' for loop, each iteration of the loop
804  * happens in parallel or in some unspecified order. In a
805  * 'Vectorized' for loop, each iteration maps to one SIMD lane,
806  * and the whole loop is executed in one shot. For this case,
807  * 'extent' must be some small integer constant (probably 4, 8, or
808  * 16). An 'Unrolled' for loop compiles to a completely unrolled
809  * version of the loop. Each iteration becomes its own
810  * statement. Again in this case, 'extent' should be a small
811  * integer constant. */
812 struct For : public StmtNode<For> {
813  std::string name;
819 
820  static Stmt make(const std::string &name,
821  Expr min, Expr extent,
824  Stmt body);
825 
826  bool is_unordered_parallel() const {
828  }
829  bool is_parallel() const {
831  }
832 
834 };
835 
836 struct Acquire : public StmtNode<Acquire> {
840 
842 
844 };
845 
846 /** Construct a new vector by taking elements from another sequence of
847  * vectors. */
848 struct Shuffle : public ExprNode<Shuffle> {
849  std::vector<Expr> vectors;
850 
851  /** Indices indicating which vector element to place into the
852  * result. The elements are numbered by their position in the
853  * concatenation of the vector arguments. */
854  std::vector<int> indices;
855 
856  static Expr make(const std::vector<Expr> &vectors,
857  const std::vector<int> &indices);
858 
859  /** Convenience constructor for making a shuffle representing an
860  * interleaving of vectors of the same length. */
861  static Expr make_interleave(const std::vector<Expr> &vectors);
862 
863  /** Convenience constructor for making a shuffle representing a
864  * concatenation of the vectors. */
865  static Expr make_concat(const std::vector<Expr> &vectors);
866 
867  /** Convenience constructor for making a shuffle representing a
868  * broadcast of a vector. */
869  static Expr make_broadcast(Expr vector, int factor);
870 
871  /** Convenience constructor for making a shuffle representing a
872  * contiguous subset of a vector. */
873  static Expr make_slice(Expr vector, int begin, int stride, int size);
874 
875  /** Convenience constructor for making a shuffle representing
876  * extracting a single element. */
877  static Expr make_extract_element(Expr vector, int i);
878 
879  /** Check if this shuffle is an interleaving of the vector
880  * arguments. */
881  bool is_interleave() const;
882 
883  /** Check if this shuffle can be represented as a repeating pattern that
884  * repeats the same shuffle of the single input vector some number of times.
885  * For example: 0, 3, 1, 1, 0, 3, 1, 1, ....., 0, 3, 1, 1
886  */
887  bool is_broadcast() const;
888  int broadcast_factor() const;
889 
890  /** Check if this shuffle is a concatenation of the vector
891  * arguments. */
892  bool is_concat() const;
893 
894  /** Check if this shuffle is a contiguous strict subset of the
895  * vector arguments, and if so, the offset and stride of the
896  * slice. */
897  ///@{
898  bool is_slice() const;
899  int slice_begin() const {
900  return indices[0];
901  }
902  int slice_stride() const {
903  return indices.size() >= 2 ? indices[1] - indices[0] : 1;
904  }
905  ///@}
906 
907  /** Check if this shuffle is extracting a scalar from the vector
908  * arguments. */
909  bool is_extract_element() const;
910 
912 };
913 
914 /** Represent a multi-dimensional region of a Func or an ImageParam that
915  * needs to be prefetched. */
916 struct Prefetch : public StmtNode<Prefetch> {
917  std::string name;
918  std::vector<Type> types;
922 
924 
925  static Stmt make(const std::string &name, const std::vector<Type> &types,
926  const Region &bounds,
929 
931 };
932 
933 /**
934  * Represents a location where storage will be hoisted to for a Func / Realize
935  * node with a given name.
936  *
937  */
938 struct HoistedStorage : public StmtNode<HoistedStorage> {
939  std::string name;
941 
942  static Stmt make(const std::string &name,
943  Stmt body);
944 
946 };
947 
948 /** Lock all the Store nodes in the body statement.
949  * Typically the lock is implemented by an atomic operation
950  * (e.g. atomic add or atomic compare-and-swap).
951  * However, if necessary, the node can access a mutex buffer through
952  * mutex_name and mutex_args, by lowering this node into
953  * calls to acquire and release the lock. */
954 struct Atomic : public StmtNode<Atomic> {
955  std::string producer_name;
956  std::string mutex_name; // empty string if not using mutex
958 
959  static Stmt make(const std::string &producer_name,
960  const std::string &mutex_name,
961  Stmt body);
962 
964 };
965 
966 /** Horizontally reduce a vector to a scalar or narrower vector using
967  * the given commutative and associative binary operator. The reduction
968  * factor is dictated by the number of lanes in the input and output
969  * types. Groups of adjacent lanes are combined. The number of lanes
970  * in the input type must be a divisor of the number of lanes of the
971  * output type. */
972 struct VectorReduce : public ExprNode<VectorReduce> {
973  // 99.9% of the time people will use this for horizontal addition,
974  // but these are all of our commutative and associative primitive
975  // operators.
976  typedef enum {
983  Or,
984  } Operator;
985 
988 
989  static Expr make(Operator op, Expr vec, int lanes);
990 
992 };
993 
994 } // namespace Internal
995 } // namespace Halide
996 
997 #endif
Base classes for Halide expressions (Halide::Expr) and statements (Halide::Internal::Stmt)
Defines the Partition enum.
Routines for statically determining what expressions are divisible by.
Defines the internal representation of parameters to halide piplines.
Defines the PrefetchDirective struct.
Defines internal classes related to Reduction Domains.
Defines halide types.
#define HALIDE_EXPORT
Definition: Util.h:39
A Halide::Buffer is a named shared reference to a Halide::Runtime::Buffer.
Definition: Buffer.h:122
Type type() const
Definition: Buffer.h:533
const std::string & name() const
Definition: Buffer.h:367
A reference-counted handle to Halide's internal representation of a function.
Definition: Function.h:39
A reference-counted handle on a reduction domain, which is just a vector of ReductionVariable.
Definition: Reduction.h:33
A reference-counted handle to a parameter to a halide pipeline.
Definition: Parameter.h:40
const std::string & name() const
Get the name of this parameter.
Type type() const
Get the type of this parameter.
ForType
An enum describing a type of loop traversal.
Definition: Expr.h:406
bool is_unordered_parallel(ForType for_type)
Check if for_type executes for loop iterations in parallel and unordered.
bool is_parallel(ForType for_type)
Returns true if for_type executes for loop iterations in parallel.
IRNodeType
All our IR node types get unique IDs for the purposes of RTTI.
Definition: Expr.h:25
This file defines the class FunctionDAG, which is our representation of a Halide pipeline,...
@ Internal
Not visible externally, similar to 'static' linkage in C.
DeviceAPI
An enum describing a type of device API.
Definition: DeviceAPI.h:15
std::vector< Range > Region
A multi-dimensional box.
Definition: Expr.h:350
MemoryType
An enum describing different address spaces to be used with Func::store_in.
Definition: Expr.h:353
Partition
Different ways to handle loops with a potentially optimizable boundary conditions.
signed __INT32_TYPE__ int32_t
A fragment of Halide syntax.
Definition: Expr.h:258
HALIDE_ALWAYS_INLINE Type type() const
Get the type of this expression node.
Definition: Expr.h:327
static const IRNodeType _node_type
Definition: IR.h:843
static Stmt make(Expr semaphore, Expr count, Stmt body)
The sum of two expressions.
Definition: IR.h:56
static Expr make(Expr a, Expr b)
static const IRNodeType _node_type
Definition: IR.h:61
Allocate a scratch area called with the given name, type, and size.
Definition: IR.h:371
std::string name
Definition: IR.h:372
std::vector< Expr > extents
Definition: IR.h:375
static int32_t constant_allocation_size(const std::vector< Expr > &extents, const std::string &name)
A routine to check if the extents are all constants, and if so verify the total size is less than 2^3...
static const IRNodeType _node_type
Definition: IR.h:409
int32_t constant_allocation_size() const
MemoryType memory_type
Definition: IR.h:374
std::string free_function
Definition: IR.h:388
static Stmt make(const std::string &name, Type type, MemoryType memory_type, const std::vector< Expr > &extents, Expr condition, Stmt body, Expr new_expr=Expr(), const std::string &free_function=std::string(), int padding=0)
Logical and - are both expressions true.
Definition: IR.h:175
static const IRNodeType _node_type
Definition: IR.h:180
static Expr make(Expr a, Expr b)
If the 'condition' is false, then evaluate and return the message, which should be a call to an error...
Definition: IR.h:294
static const IRNodeType _node_type
Definition: IR.h:301
static Stmt make(Expr condition, Expr message)
Lock all the Store nodes in the body statement.
Definition: IR.h:954
static const IRNodeType _node_type
Definition: IR.h:963
static Stmt make(const std::string &producer_name, const std::string &mutex_name, Stmt body)
std::string mutex_name
Definition: IR.h:956
std::string producer_name
Definition: IR.h:955
A sequence of statements to be executed in-order.
Definition: IR.h:442
static Stmt make(const std::vector< Stmt > &stmts)
Construct zero or more Blocks to invoke a list of statements in order.
static Stmt make(Stmt first, Stmt rest)
static const IRNodeType _node_type
Definition: IR.h:451
A vector with 'lanes' elements, in which every element is 'value'.
Definition: IR.h:259
static Expr make(Expr value, int lanes)
static const IRNodeType _node_type
Definition: IR.h:265
A function call.
Definition: IR.h:490
static Expr make(Type type, const std::string &name, const std::vector< Expr > &args, CallType call_type, FunctionPtr func=FunctionPtr(), int value_index=0, Buffer<> image=Buffer<>(), Parameter param=Parameter())
static HALIDE_EXPORT ConstString buffer_get_max
Definition: IR.h:648
static Expr make(const Function &func, const std::vector< Expr > &args, int idx=0)
Convenience constructor for calls to other halide functions.
static HALIDE_EXPORT ConstString buffer_get_host_dirty
Definition: IR.h:653
static HALIDE_EXPORT ConstString buffer_set_bounds
Definition: IR.h:662
const char *const ConstString
Definition: IR.h:509
bool is_tag() const
Definition: IR.h:732
@ call_cached_indirect_function
Definition: IR.h:531
@ signed_integer_overflow
Definition: IR.h:595
@ unsafe_promise_clamped
Definition: IR.h:617
@ add_image_checks_marker
Definition: IR.h:521
@ rounding_mul_shift_right
Definition: IR.h:585
@ load_typed_struct_member
Definition: IR.h:564
@ profiling_enable_instance_marker
Definition: IR.h:572
@ size_of_halide_buffer_t
Definition: IR.h:596
bool is_extern() const
Definition: IR.h:753
@ Extern
A call to an external C-ABI function, possibly with side-effects.
Definition: IR.h:494
@ ExternCPlusPlus
A call to an external C-ABI function, possibly with side-effects.
Definition: IR.h:495
@ Image
A load from an input image.
Definition: IR.h:493
@ Halide
A call to a Func.
Definition: IR.h:497
@ Intrinsic
A possibly-side-effecty compiler intrinsic, which has special handling during codegen.
Definition: IR.h:498
@ PureExtern
A call to a guaranteed-side-effect-free external function.
Definition: IR.h:496
@ PureIntrinsic
A side-effect-free version of the above.
Definition: IR.h:499
std::string name
Definition: IR.h:491
static HALIDE_EXPORT ConstString buffer_get_min
Definition: IR.h:645
static const Call * as_intrinsic(const Expr &e, std::initializer_list< IntrinsicOp > intrinsics)
Returns a pointer to a call node if the expression is a call to one of the requested intrinsics.
Definition: IR.h:738
bool is_intrinsic() const
Definition: IR.h:714
static HALIDE_EXPORT ConstString buffer_get_device_interface
Definition: IR.h:651
static HALIDE_EXPORT ConstString buffer_get_dimensions
Definition: IR.h:644
static HALIDE_EXPORT ConstString buffer_get_device_dirty
Definition: IR.h:654
static HALIDE_EXPORT ConstString buffer_crop
Definition: IR.h:661
FunctionPtr func
Definition: IR.h:667
CallType call_type
Definition: IR.h:501
static HALIDE_EXPORT ConstString buffer_get_host
Definition: IR.h:649
static Expr make(const Buffer<> &image, const std::vector< Expr > &args)
Convenience constructor for loads from concrete images.
Definition: IR.h:693
static HALIDE_EXPORT ConstString buffer_get_device
Definition: IR.h:650
static HALIDE_EXPORT ConstString buffer_init
Definition: IR.h:659
bool is_pure() const
Check if a call node is pure within a pipeline, meaning that the same args always give the same resul...
Definition: IR.h:708
static HALIDE_EXPORT ConstString buffer_get_stride
Definition: IR.h:647
static HALIDE_EXPORT ConstString buffer_get_extent
Definition: IR.h:646
bool is_intrinsic(std::initializer_list< IntrinsicOp > intrinsics) const
Definition: IR.h:723
bool is_intrinsic(IntrinsicOp op) const
Definition: IR.h:719
static Expr make(const Parameter &param, const std::vector< Expr > &args)
Convenience constructor for loads from images parameters.
Definition: IR.h:698
static const IRNodeType _node_type
Definition: IR.h:759
static const char * get_intrinsic_name(IntrinsicOp op)
static HALIDE_EXPORT ConstString trace
Definition: IR.h:663
std::vector< Expr > args
Definition: IR.h:492
static HALIDE_EXPORT ConstString buffer_get_shape
Definition: IR.h:652
static Expr make(Type type, IntrinsicOp op, const std::vector< Expr > &args, CallType call_type, FunctionPtr func=FunctionPtr(), int value_index=0, const Buffer<> &image=Buffer<>(), Parameter param=Parameter())
Parameter param
Definition: IR.h:679
static const Call * as_tag(const Expr &e)
Definition: IR.h:749
static HALIDE_EXPORT ConstString buffer_is_bounds_query
Definition: IR.h:658
static HALIDE_EXPORT ConstString buffer_get_type
Definition: IR.h:655
static HALIDE_EXPORT ConstString buffer_set_device_dirty
Definition: IR.h:657
static HALIDE_EXPORT ConstString buffer_set_host_dirty
Definition: IR.h:656
static HALIDE_EXPORT ConstString buffer_init_from_buffer
Definition: IR.h:660
The actual IR nodes begin here.
Definition: IR.h:30
static const IRNodeType _node_type
Definition: IR.h:35
static Expr make(Type t, Expr v)
bool is_reinterpret() const
Check if the cast is equivalent to a reinterpret.
Definition: IR.h:38
The ratio of two expressions.
Definition: IR.h:83
static const IRNodeType _node_type
Definition: IR.h:88
static Expr make(Expr a, Expr b)
Is the first expression equal to the second.
Definition: IR.h:121
static const IRNodeType _node_type
Definition: IR.h:126
static Expr make(Expr a, Expr b)
Evaluate and discard an expression, presumably because it has some side-effect.
Definition: IR.h:476
static Stmt make(Expr v)
static const IRNodeType _node_type
Definition: IR.h:481
We use the "curiously recurring template pattern" to avoid duplicated code in the IR Nodes.
Definition: Expr.h:158
A for loop.
Definition: IR.h:812
Partition partition_policy
Definition: IR.h:818
std::string name
Definition: IR.h:813
DeviceAPI device_api
Definition: IR.h:816
ForType for_type
Definition: IR.h:815
bool is_parallel() const
Definition: IR.h:829
bool is_unordered_parallel() const
Definition: IR.h:826
static const IRNodeType _node_type
Definition: IR.h:833
static Stmt make(const std::string &name, Expr min, Expr extent, ForType for_type, Partition partition_policy, DeviceAPI device_api, Stmt body)
A pair of statements executed concurrently.
Definition: IR.h:457
static Stmt make(Stmt first, Stmt rest)
static const IRNodeType _node_type
Definition: IR.h:462
Free the resources associated with the given buffer.
Definition: IR.h:413
static const IRNodeType _node_type
Definition: IR.h:418
static Stmt make(const std::string &name)
std::string name
Definition: IR.h:414
A possibly-weak pointer to a Halide function.
Definition: FunctionPtr.h:27
Is the first expression greater than or equal to the second.
Definition: IR.h:166
static const IRNodeType _node_type
Definition: IR.h:171
static Expr make(Expr a, Expr b)
Is the first expression greater than the second.
Definition: IR.h:157
static const IRNodeType _node_type
Definition: IR.h:162
static Expr make(Expr a, Expr b)
Represents a location where storage will be hoisted to for a Func / Realize node with a given name.
Definition: IR.h:938
static Stmt make(const std::string &name, Stmt body)
static const IRNodeType _node_type
Definition: IR.h:945
const T * as() const
Downcast this ir node to its actual type (e.g.
Definition: Expr.h:205
An if-then-else block.
Definition: IR.h:466
static const IRNodeType _node_type
Definition: IR.h:472
static Stmt make(Expr condition, Stmt then_case, Stmt else_case=Stmt())
Is the first expression less than or equal to the second.
Definition: IR.h:148
static Expr make(Expr a, Expr b)
static const IRNodeType _node_type
Definition: IR.h:153
Is the first expression less than the second.
Definition: IR.h:139
static Expr make(Expr a, Expr b)
static const IRNodeType _node_type
Definition: IR.h:144
A let expression, like you might find in a functional language.
Definition: IR.h:271
std::string name
Definition: IR.h:272
static Expr make(const std::string &name, Expr value, Expr body)
static const IRNodeType _node_type
Definition: IR.h:277
The statement form of a let node.
Definition: IR.h:282
static Stmt make(const std::string &name, Expr value, Stmt body)
std::string name
Definition: IR.h:283
static const IRNodeType _node_type
Definition: IR.h:289
Load a value from a named symbol if predicate is true.
Definition: IR.h:217
std::string name
Definition: IR.h:218
static Expr make(Type type, const std::string &name, Expr index, Buffer<> image, Parameter param, Expr predicate, ModulusRemainder alignment)
Parameter param
Definition: IR.h:227
static const IRNodeType _node_type
Definition: IR.h:239
ModulusRemainder alignment
Definition: IR.h:231
The greater of two values.
Definition: IR.h:112
static const IRNodeType _node_type
Definition: IR.h:117
static Expr make(Expr a, Expr b)
The lesser of two values.
Definition: IR.h:103
static const IRNodeType _node_type
Definition: IR.h:108
static Expr make(Expr a, Expr b)
The remainder of a / b.
Definition: IR.h:94
static const IRNodeType _node_type
Definition: IR.h:99
static Expr make(Expr a, Expr b)
The result of modulus_remainder analysis.
The product of two expressions.
Definition: IR.h:74
static const IRNodeType _node_type
Definition: IR.h:79
static Expr make(Expr a, Expr b)
Is the first expression not equal to the second.
Definition: IR.h:130
static const IRNodeType _node_type
Definition: IR.h:135
static Expr make(Expr a, Expr b)
Logical not - true if the expression false.
Definition: IR.h:193
static Expr make(Expr a)
static const IRNodeType _node_type
Definition: IR.h:198
Logical or - is at least one of the expression true.
Definition: IR.h:184
static Expr make(Expr a, Expr b)
static const IRNodeType _node_type
Definition: IR.h:189
Represent a multi-dimensional region of a Func or an ImageParam that needs to be prefetched.
Definition: IR.h:916
static Stmt make(const std::string &name, const std::vector< Type > &types, const Region &bounds, const PrefetchDirective &prefetch, Expr condition, Stmt body)
static const IRNodeType _node_type
Definition: IR.h:930
PrefetchDirective prefetch
Definition: IR.h:920
std::vector< Type > types
Definition: IR.h:918
std::string name
Definition: IR.h:917
This node is a helpful annotation to do with permissions.
Definition: IR.h:315
static const IRNodeType _node_type
Definition: IR.h:325
static Stmt make_consume(const std::string &name, Stmt body)
static Stmt make_produce(const std::string &name, Stmt body)
static Stmt make(const std::string &name, bool is_producer, Stmt body)
This defines the value of a function at a multi-dimensional location.
Definition: IR.h:354
static const IRNodeType _node_type
Definition: IR.h:362
std::string name
Definition: IR.h:355
std::vector< Expr > values
Definition: IR.h:356
std::vector< Expr > args
Definition: IR.h:357
static Stmt make(const std::string &name, const std::vector< Expr > &values, const std::vector< Expr > &args, const Expr &predicate)
A linear ramp vector node.
Definition: IR.h:247
static const IRNodeType _node_type
Definition: IR.h:253
static Expr make(Expr base, Expr stride, int lanes)
Allocate a multi-dimensional buffer of the given type and size.
Definition: IR.h:427
static Stmt make(const std::string &name, const std::vector< Type > &types, MemoryType memory_type, const Region &bounds, Expr condition, Stmt body)
MemoryType memory_type
Definition: IR.h:430
std::vector< Type > types
Definition: IR.h:429
static const IRNodeType _node_type
Definition: IR.h:437
std::string name
Definition: IR.h:428
Reinterpret value as another type, without affecting any of the bits (on little-endian systems).
Definition: IR.h:47
static const IRNodeType _node_type
Definition: IR.h:52
static Expr make(Type t, Expr v)
A ternary operator.
Definition: IR.h:204
static Expr make(Expr condition, Expr true_value, Expr false_value)
static const IRNodeType _node_type
Definition: IR.h:209
Construct a new vector by taking elements from another sequence of vectors.
Definition: IR.h:848
static Expr make_slice(Expr vector, int begin, int stride, int size)
Convenience constructor for making a shuffle representing a contiguous subset of a vector.
bool is_interleave() const
Check if this shuffle is an interleaving of the vector arguments.
static Expr make_extract_element(Expr vector, int i)
Convenience constructor for making a shuffle representing extracting a single element.
bool is_extract_element() const
Check if this shuffle is extracting a scalar from the vector arguments.
bool is_broadcast() const
Check if this shuffle can be represented as a repeating pattern that repeats the same shuffle of the ...
static Expr make_concat(const std::vector< Expr > &vectors)
Convenience constructor for making a shuffle representing a concatenation of the vectors.
static Expr make(const std::vector< Expr > &vectors, const std::vector< int > &indices)
static const IRNodeType _node_type
Definition: IR.h:911
static Expr make_broadcast(Expr vector, int factor)
Convenience constructor for making a shuffle representing a broadcast of a vector.
std::vector< Expr > vectors
Definition: IR.h:849
bool is_concat() const
Check if this shuffle is a concatenation of the vector arguments.
bool is_slice() const
Check if this shuffle is a contiguous strict subset of the vector arguments, and if so,...
std::vector< int > indices
Indices indicating which vector element to place into the result.
Definition: IR.h:854
int slice_stride() const
Check if this shuffle is a contiguous strict subset of the vector arguments, and if so,...
Definition: IR.h:902
static Expr make_interleave(const std::vector< Expr > &vectors)
Convenience constructor for making a shuffle representing an interleaving of vectors of the same leng...
int slice_begin() const
Check if this shuffle is a contiguous strict subset of the vector arguments, and if so,...
Definition: IR.h:899
A reference-counted handle to a statement node.
Definition: Expr.h:427
Store a 'value' to the buffer called 'name' at a given 'index' if 'predicate' is true.
Definition: IR.h:333
std::string name
Definition: IR.h:334
static const IRNodeType _node_type
Definition: IR.h:346
Parameter param
Definition: IR.h:337
ModulusRemainder alignment
Definition: IR.h:341
static Stmt make(const std::string &name, Expr value, Expr index, Parameter param, Expr predicate, ModulusRemainder alignment)
The difference of two expressions.
Definition: IR.h:65
static const IRNodeType _node_type
Definition: IR.h:70
static Expr make(Expr a, Expr b)
A named variable.
Definition: IR.h:765
static Expr make(Type type, const std::string &name, const Buffer<> &image)
Definition: IR.h:786
static Expr make(Type type, const std::string &name, Parameter param)
Definition: IR.h:782
static Expr make(Type type, const std::string &name, Buffer<> image, Parameter param, ReductionDomain reduction_domain)
Buffer image
References to properties of literal image parameters.
Definition: IR.h:773
ReductionDomain reduction_domain
Reduction variables hang onto their domains.
Definition: IR.h:776
static Expr make(Type type, const std::string &name)
Definition: IR.h:778
Parameter param
References to scalar parameters, or to the dimensions of buffer parameters hang onto those expression...
Definition: IR.h:770
static Expr make(Type type, const std::string &name, ReductionDomain reduction_domain)
Definition: IR.h:790
std::string name
Definition: IR.h:766
static const IRNodeType _node_type
Definition: IR.h:797
Horizontally reduce a vector to a scalar or narrower vector using the given commutative and associati...
Definition: IR.h:972
static const IRNodeType _node_type
Definition: IR.h:991
static Expr make(Operator op, Expr vec, int lanes)
Types in the halide type system.
Definition: Type.h:283
HALIDE_ALWAYS_INLINE int bits() const
Return the bit size of a single element of this type.
Definition: Type.h:349
HALIDE_ALWAYS_INLINE bool is_int_or_uint() const
Is this type an integer type of any sort?
Definition: Type.h:447