• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.
2
3Licensed under the Apache License, Version 2.0 (the "License");
4you may not use this file except in compliance with the License.
5You may obtain a copy of the License at
6
7    http://www.apache.org/licenses/LICENSE-2.0
8
9Unless required by applicable law or agreed to in writing, software
10distributed under the License is distributed on an "AS IS" BASIS,
11WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12See the License for the specific language governing permissions and
13limitations under the License.
14==============================================================================*/
15
16// Defines "client" aligned HLO ops.
17// These ops are not necessarily orthogonal or optimized for transformation but
18// for ease of expression in certain cases deemed important for client
19// libraries (i.e. implicit broadcasting, helper ops, etc).
20// This dialect is considered to exist in addition to augment the mhlo
21// dialect for ergonomic needs, not duplicate/replace it.
22//
23// The typical use of this dialect is for client libraries to be able to emit
24// less constrained ops and rely on the conversion framework to lower any
25// chlo ops to canonical mhlo ops.
26//
27// See: https://www.tensorflow.org/xla/operation_semantics
28
29#ifndef CHLO_OPS
30#define CHLO_OPS
31
32include "mlir/IR/OpBase.td"
33include "mlir/Interfaces/InferTypeOpInterface.td"
34include "mlir/Interfaces/SideEffectInterfaces.td"
35include "mlir-hlo/Dialect/mhlo/IR/hlo_ops_base.td"
36include "mlir-hlo/Dialect/mhlo/IR/infer_fusibility_op_interface.td"
37
38def HLOClient_Dialect : Dialect {
39  let name = "chlo";
40  let cppNamespace = "::mlir::chlo";
41  let summary = [{
42    Client HLO Ops
43  }];
44
45  let description = [{
46    This dialect contains ops that align closely with the API surface area
47    of the XlaBuilder C++ API, where such ops have semantics that go beyond
48    what exists in the lower level dialects (such as `mhlo`). Essentially,
49    whenever the client library uses syntactic sugar or composition
50    of multiple ops for an API call, this dialect tries to model the API call
51    and provide conversion patterns to fully materialize into lower level
52    dialects.
53  }];
54}
55
56class HLOClient_Op<string mnemonic, list<OpTrait> traits> :
57    Op<HLOClient_Dialect, mnemonic, traits> {
58  // TODO(b/129012527) Much of this custom verification should be expressed as
59  // type constraints.
60  let verifier = [{ return Verify(*this); }];
61}
62
63//===----------------------------------------------------------------------===//
64// CHLO binary elementwise op definitions.
65// From the client perspective, each of these support both explicit rank
66// broadcasting (via the broadcast_dimensions attribute) and implicit degenerate
67// shape broadcasting.
68//
69// These correspond to operations in the chlo and mhlo dialects without the
70// "broadcast_" prefix, except that those ops require same-shaped operands and
71// results.
72//
73// See:
74//   https://www.tensorflow.org/xla/operation_semantics#element-wise_binary_arithmetic_operations
75//   https://www.tensorflow.org/xla/broadcasting
76//===----------------------------------------------------------------------===//
77
78class HLOClient_BroadcastBinaryElementwiseOp<
79  string mnemonic, list<OpTrait> traits> :
80        HLOClient_Op<mnemonic,
81            !listconcat(traits, [
82              DeclareOpInterfaceMethods<InferShapedTypeOpInterface,
83              ["reifyReturnTypeShapes"]>])> {
84  let arguments = (ins
85    HLO_Tensor:$lhs,
86    HLO_Tensor:$rhs,
87    // Explicit rank-broadcast dimension mappings. Defaults to "numpy" prefix
88    // padded rank-broadcast semantics if omitted.
89    OptionalAttr<BroadcastDimAttr>:$broadcast_dimensions
90  );
91
92  let builders = [
93    OpBuilderDAG<(ins "Value":$left, "Value":$right,
94      "DenseIntElementsAttr":$broadcast_dimensions)>];
95
96  let results = (outs HLO_Tensor);
97
98  let assemblyFormat = [{
99    $lhs `,` $rhs attr-dict `:`
100    `(` type($lhs) `,` type($rhs) `)` `->` type(results)
101  }];
102}
103
104def HLOClient_BroadcastAddOp : HLOClient_BroadcastBinaryElementwiseOp<"broadcast_add",
105    [Commutative, NoSideEffect, SameOperandsAndResultElementType]> {
106  string summary = "Addition operator (with optional broadcasting)";
107
108  string description = [{
109    Returns `lhs + rhs` element-wise.
110
111    See
112    https://www.tensorflow.org/xla/operation_semantics#element-wise_binary_arithmetic_operations.
113  }];
114}
115
116def HLOClient_BroadcastAtan2Op : HLOClient_BroadcastBinaryElementwiseOp<
117    "broadcast_atan2",
118    [NoSideEffect, SameOperandsAndResultElementType]> {
119  string summary = "Atan2 operator (with optional broadcasting)";
120
121  string description = [{
122    Returns `atan2(lhs/rhs)` element-wise.
123
124    See
125    https://www.tensorflow.org/xla/operation_semantics#element-wise_binary_arithmetic_operations.
126  }];
127}
128
129def HLOClient_BroadcastDivOp : HLOClient_BroadcastBinaryElementwiseOp<
130    "broadcast_divide",
131    [NoSideEffect, SameOperandsAndResultElementType]> {
132  string summary = "Division operator (with optional broadcasting)";
133
134  string description = [{
135    Returns `lhs / rhs` element-wise.
136
137    See
138    https://www.tensorflow.org/xla/operation_semantics#element-wise_binary_arithmetic_operations.
139  }];
140}
141
142def HLOClient_BroadcastMaxOp : HLOClient_BroadcastBinaryElementwiseOp<
143    "broadcast_maximum",
144    [Commutative, NoSideEffect, SameOperandsAndResultElementType]> {
145  string summary = "Maximum operator (with optional broadcasting)";
146
147  string description = [{
148    Returns `max(lhs, rhs)` element-wise.
149
150    See
151    https://www.tensorflow.org/xla/operation_semantics#element-wise_binary_arithmetic_operations.
152  }];
153}
154
155def HLOClient_BroadcastMinOp : HLOClient_BroadcastBinaryElementwiseOp<
156    "broadcast_minimum",
157    [Commutative, NoSideEffect, SameOperandsAndResultElementType]> {
158  string summary = "Minimum operator (with optional broadcasting)";
159
160  string description = [{
161    Returns `min(lhs, rhs)` element-wise.
162
163    See
164    https://www.tensorflow.org/xla/operation_semantics#element-wise_binary_arithmetic_operations.
165  }];
166}
167
168def HLOClient_BroadcastMulOp : HLOClient_BroadcastBinaryElementwiseOp<
169    "broadcast_multiply",
170    [Commutative, NoSideEffect, SameOperandsAndResultElementType]> {
171  string summary = "Multiplication operator (with optional broadcasting)";
172
173  string description = [{
174    Returns `lhs * rhs` element-wise.
175
176    See
177    https://www.tensorflow.org/xla/operation_semantics#element-wise_binary_arithmetic_operations.
178  }];
179}
180
181def HLOClient_BroadcastPolygammaOp : HLOClient_BroadcastBinaryElementwiseOp<
182    "broadcast_polygamma", [NoSideEffect, SameOperandsAndResultElementType]> {
183  let summary = "Polygamma function (with optional broadcasting)";
184
185  let description = [{
186    Returns `Polygamma(operand, operand)` element-wise.
187  }];
188}
189
190def HLOClient_BroadcastPowOp : HLOClient_BroadcastBinaryElementwiseOp<
191    "broadcast_power",
192    [NoSideEffect, SameOperandsAndResultElementType]> {
193  string summary = "Power operator (with optional broadcasting)";
194
195  string description = [{
196    Returns `lhs ^ rhs` element-wise.
197
198    See
199    https://www.tensorflow.org/xla/operation_semantics#element-wise_binary_arithmetic_operations.
200  }];
201}
202
203def HLOClient_BroadcastRemOp : HLOClient_BroadcastBinaryElementwiseOp<
204    "broadcast_remainder",
205    [NoSideEffect, SameOperandsAndResultElementType]> {
206  string summary = "Remainder operator (with optional broadcasting)";
207
208  string description = [{
209    Returns `lhs % rhs` element-wise.
210
211    See
212    https://www.tensorflow.org/xla/operation_semantics#element-wise_binary_arithmetic_operations.
213  }];
214}
215
216def HLOClient_BroadcastShiftLeftOp : HLOClient_BroadcastBinaryElementwiseOp<
217    "broadcast_shift_left",
218    [NoSideEffect, SameOperandsAndResultElementType]> {
219  string summary = "Shift left operator (with optional broadcasting)";
220
221  string description = [{
222    Returns `lhs << rhs` element-wise.
223
224    See
225    https://www.tensorflow.org/xla/operation_semantics#element-wise_binary_arithmetic_operations.
226  }];
227}
228
229def HLOClient_BroadcastShiftRightArithmeticOp : HLOClient_BroadcastBinaryElementwiseOp<
230    "broadcast_shift_right_arithmetic",
231    [NoSideEffect, SameOperandsAndResultElementType]> {
232  string summary = "Shift right arithmetic operator (with optional broadcasting)";
233
234  string description = [{
235    Returns `lhs >> rhs` element-wise.
236
237    See
238    https://www.tensorflow.org/xla/operation_semantics#element-wise_binary_arithmetic_operations.
239  }];
240}
241
242def HLOClient_BroadcastShiftRightLogicalOp : HLOClient_BroadcastBinaryElementwiseOp<
243    "broadcast_shift_right_logical",
244    [NoSideEffect, SameOperandsAndResultElementType]> {
245  string summary = "Shift right logical operator (with optional broadcasting)";
246
247  string description = [{
248    Returns `lhs >> rhs` element-wise.
249
250    See
251    https://www.tensorflow.org/xla/operation_semantics#element-wise_binary_arithmetic_operations.
252  }];
253}
254
255def HLOClient_BroadcastSubOp : HLOClient_BroadcastBinaryElementwiseOp<
256    "broadcast_subtract",
257    [NoSideEffect, SameOperandsAndResultElementType]> {
258  string summary = "Subtraction operator (with optional broadcasting)";
259
260  string description = [{
261    Returns `lhs - rhs` element-wise.
262
263    See
264    https://www.tensorflow.org/xla/operation_semantics#element-wise_binary_arithmetic_operations.
265  }];
266}
267
268def HLOClient_BroadcastZetaOp : HLOClient_BroadcastBinaryElementwiseOp<
269    "broadcast_zeta",
270    [NoSideEffect, SameOperandsAndResultElementType]> {
271  let summary = "Hurwitz zeta function";
272
273  let description = [{
274    Returns `Zeta(operand, operand)` element-wise.
275
276    $$
277    \(\zeta(x, q) = \sum_{n=0}^{\infty} (q + n)^{-x}\)
278    $$
279  }];
280
281  let arguments = (ins
282    HLO_FpTensor:$lhs,
283    HLO_FpTensor:$rhs,
284    // Explicit rank-broadcast dimension mappings. Defaults to "numpy" prefix
285    // padded rank-broadcast semantics if omitted.
286    OptionalAttr<BroadcastDimAttr>:$broadcast_dimensions
287  );
288  let results = (outs HLO_FpTensor);
289}
290
291//===----------------------------------------------------------------------===//
292// XLA binary logical elementwise op definitions.
293// The same description as the arithmetic binary elementwise ops applies.
294//===----------------------------------------------------------------------===//
295
296class HLOClient_BroadcastBinaryLogicalElementwiseOp<string mnemonic> :
297    HLOClient_BroadcastBinaryElementwiseOp<
298      mnemonic, [Commutative, NoSideEffect]> {
299  let arguments = (ins
300    HLO_PredOrIntTensor:$lhs,
301    HLO_PredOrIntTensor:$rhs,
302    // Explicit rank-broadcast dimension mappings. Defaults to "numpy" prefix
303    // padded rank-broadcast semantics if omitted.
304    OptionalAttr<BroadcastDimAttr>:$broadcast_dimensions
305  );
306}
307
308def HLOClient_BroadcastAndOp: HLOClient_BroadcastBinaryLogicalElementwiseOp<
309    "broadcast_and"> {
310  string summary = "Logical and operator (with optional broadcasting)";
311
312  string description = [{
313    Returns `logical_and(lhs, rhs)` element-wise.
314
315    See
316    https://www.tensorflow.org/xla/operation_semantics#element-wise_binary_arithmetic_operations.
317  }];
318}
319
320def HLOClient_BroadcastOrOp: HLOClient_BroadcastBinaryLogicalElementwiseOp<
321    "broadcast_or"> {
322  string summary = "Logical or operator (with optional broadcasting)";
323
324  string description = [{
325    Returns `logical_or(lhs, rhs)` element-wise.
326
327    See
328    https://www.tensorflow.org/xla/operation_semantics#element-wise_binary_arithmetic_operations.
329  }];
330}
331
332def HLOClient_BroadcastXorOp : HLOClient_BroadcastBinaryLogicalElementwiseOp<
333    "broadcast_xor"> {
334  string summary = "Logical xor operator (with optional broadcasting)";
335
336  string description = [{
337    Returns `logical_xor(lhs, rhs)` element-wise.
338
339    See
340    https://www.tensorflow.org/xla/operation_semantics#element-wise_binary_arithmetic_operations.
341  }];
342}
343
344//===----------------------------------------------------------------------===//
345// XLA non-broadcasting binary operations.
346//
347// These are operations that are supported by the XLA Builder API but that are
348// not part of the HLO compiler instructions as modelled by the MHLO dialect.
349//===----------------------------------------------------------------------===//
350
351def HLOClient_ZetaOp : HLOClient_Op<"zeta", [NoSideEffect,
352    SameOperandsAndResultType]> {
353  let summary = "Hurwitz zeta function";
354  let description = [{
355    Returns `Zeta(operand, operand)` element-wise.
356
357    $$
358    \(\zeta(x, q) = \sum_{n=0}^{\infty} (q + n)^{-x}\)
359    $$
360  }];
361
362  let arguments = (ins HLO_FpTensor:$x, HLO_FpTensor:$q);
363  let results = (outs HLO_FpTensor:$result);
364
365  let assemblyFormat = [{
366    $x `,` $q attr-dict `:` type($x) `,` type($q) `->` type(results)
367  }];
368}
369
370def HLOClient_PolygammaOp : HLOClient_Op<"polygamma", [NoSideEffect,
371    SameOperandsAndResultType]> {
372  let summary = "Polygamma function";
373  let description = [{
374    Returns `Polygamma(operand, operand)` element-wise.
375  }];
376
377  let arguments = (ins HLO_FpTensor:$n, HLO_FpTensor:$x);
378  let results = (outs HLO_FpTensor:$result);
379
380  let assemblyFormat = [{
381    $n `,` $x attr-dict `:` type($n) `,` type($x) `->` type(results)
382  }];
383}
384
385//===----------------------------------------------------------------------===//
386// Broadcasting complex op
387//===----------------------------------------------------------------------===//
388
389def HLOClient_BroadcastComplexOp : HLOClient_BroadcastBinaryElementwiseOp<
390    "broadcast_complex", [NoSideEffect]> {
391  string summary = "Complex operator (with optional broadcasting)";
392
393  string description = [{
394    Performs element-wise conversion of a pair of real and imaginary values to
395    a complex value.
396  }];
397
398  let arguments = (ins
399    HLO_FpTensor:$lhs,
400    HLO_FpTensor:$rhs,
401    // Explicit rank-broadcast dimension mappings. Defaults to "numpy" prefix
402    // padded rank-broadcast semantics if omitted.
403    OptionalAttr<BroadcastDimAttr>:$broadcast_dimensions
404  );
405  let results = (outs HLO_ComplexTensor);
406}
407
408//===----------------------------------------------------------------------===//
409// Unary op
410//===----------------------------------------------------------------------===//
411
412class HLOClient_UnaryElementwiseOp<string mnemonic, list<OpTrait> traits,
413    Type ArgTensorType, Type ResultTensorType> : HLOClient_Op<mnemonic,
414    !listconcat(traits, [InferFusibilityOpInterface, NoSideEffect,
415    SameOperandsAndResultShape])> {
416  let arguments = (ins ArgTensorType:$operand);
417  let results = (outs ResultTensorType:$result);
418
419  let assemblyFormat = [{
420    $operand attr-dict `:` type($operand) `->` type($result)
421  }];
422}
423
424def HLOClient_AcosOp : HLOClient_UnaryElementwiseOp<"acos",
425    [SameOperandsAndResultType], HLO_FpOrComplexTensor, HLO_FpOrComplexTensor> {
426  let summary = "Acos operator";
427
428  let description = [{
429    Returns `Acos(operand)` element-wise.
430
431    $$
432    \acos(x) = 2 * \atan(\sqrt(1 - x^2) / (1 + x)) if x != -1
433             = pi                                  if x == -1
434    $$
435  }];
436}
437
438def HLOClient_AcoshOp : HLOClient_UnaryElementwiseOp<"acosh",
439    [SameOperandsAndResultType], HLO_FpOrComplexTensor, HLO_FpOrComplexTensor> {
440  let summary = "Acosh operation";
441
442  let description = [{
443    Returns `Acosh(operand)` element-wise.
444
445    $$
446    \acosh(x) = log(x + sqrt(x^2 - 1))      if x >= -1
447    \acosh(x) = nan                         if x < -1
448    $$
449  }];
450}
451
452def HLOClient_AsinOp : HLOClient_UnaryElementwiseOp<"asin",
453    [SameOperandsAndResultType], HLO_FpOrComplexTensor, HLO_FpOrComplexTensor> {
454  let summary = "Asin operator";
455
456  let description = [{
457    Returns `Asin(operand)` element-wise.
458
459    $$
460    \asin(x) = 2 * atan(x / (1 + sqrt(1 - x^2)))
461    $$
462  }];
463}
464
465def HLOClient_AsinhOp : HLOClient_UnaryElementwiseOp<"asinh",
466    [SameOperandsAndResultType], HLO_FpOrComplexTensor, HLO_FpOrComplexTensor> {
467  let summary = "Asinh operation";
468
469  let description = [{
470    Returns `Asinh(operand)` element-wise.
471
472    $$
473    \asinh(x) = log(x + sqrt(x^2 + 1))
474    $$
475  }];
476}
477
478def HLOClient_AtanOp : HLOClient_UnaryElementwiseOp<"atan",
479    [SameOperandsAndResultType], HLO_FpOrComplexTensor, HLO_FpOrComplexTensor> {
480  let summary = "Atan operator";
481
482  let description = [{
483    Returns `Atan(operand)` element-wise.
484
485    $$
486    \atan(x) = \atan2(x, 1)
487    $$
488  }];
489}
490
491def HLOClient_AtanhOp : HLOClient_UnaryElementwiseOp<"atanh",
492    [SameOperandsAndResultType], HLO_FpOrComplexTensor, HLO_FpOrComplexTensor> {
493  let summary = "Atanh operator";
494
495  let description = [{
496    Returns `Atanh(operand)` element-wise.
497
498    $$
499    \atanh(x) = 0.5 * log((1 + x) / (1 - x)) if abs(x) <= 1
500              = nan                          otherwise
501    $$
502  }];
503}
504
505def HLOClient_ConjOp : HLOClient_UnaryElementwiseOp<"conj",
506    [SameOperandsAndResultType], HLO_FpOrComplexTensor, HLO_FpOrComplexTensor> {
507  let summary = "Conj operator";
508
509  let description = [{
510    Returns `Conj(operand)` element-wise.
511
512    $$
513    \conj(x) = (\real(x), \neg(\imag(x)))
514    $$
515  }];
516}
517
518def HLOClient_CoshOp : HLOClient_UnaryElementwiseOp<"cosh",
519    [SameOperandsAndResultType], HLO_FpOrComplexTensor, HLO_FpOrComplexTensor> {
520  let summary = "Cosh operator";
521
522  let description = [{
523    Returns `Cosh(operand)` element-wise.
524
525    $$
526    \cosh(x) = (e^x + e^-x) / 2
527    $$
528  }];
529}
530
531def HLOClient_SinhOp : HLOClient_UnaryElementwiseOp<"sinh",
532    [SameOperandsAndResultType], HLO_FpOrComplexTensor, HLO_FpOrComplexTensor> {
533  let summary = "Sinh operation";
534
535  let description = [{
536    Returns `Sinh(operand)` element-wise.
537
538    $$
539    \sinh(x) = (e^x - e^-x) / 2                     if |x| < 1
540             = e^(x + log(1/2)) - e^(-x + log(1/2)) otherwise.
541    $$
542  }];
543}
544
545def HLOClient_TanOp : HLOClient_UnaryElementwiseOp<"tan",
546    [SameOperandsAndResultType], HLO_FpOrComplexTensor, HLO_FpOrComplexTensor> {
547  let summary = "Tan operation";
548
549  let description = [{
550    Returns `Tan(operand)` element-wise.
551
552    $$
553    \tan(x) = \sin(x) / \cos(x)
554    $$
555  }];
556}
557
558def HLOClient_ConstantLikeOp : HLOClient_Op<"constant_like",
559    [NoSideEffect, SameOperandsAndResultShape,
560     InferTypeOpInterface,
561     DeclareOpInterfaceMethods<InferShapedTypeOpInterface>,
562     NativeOpTrait<"InferTensorType">]> {
563  let summary = "Constant like operator";
564
565  let description = [{
566    Returns a splat constant of the same shape as the operand.
567  }];
568
569  // TODO(jpienaar): value's type could be tightened.
570  let arguments = (ins AnyAttr:$value, HLO_Tensor:$operand);
571  let results = (outs HLO_Tensor);
572
573  let hasCanonicalizer = 1;
574}
575
576def HLOClient_DigammaOp : HLOClient_UnaryElementwiseOp<"digamma",
577    [SameOperandsAndResultType], HLO_FpTensor, HLO_FpTensor> {
578  let summary = "Digamma function";
579
580  let description = [{
581    Returns `Digamma(operand)` element-wise.
582  }];
583}
584
585def HLOClient_ErfOp : HLOClient_UnaryElementwiseOp<"erf",
586   [SameOperandsAndResultType], HLO_FpTensor, HLO_FpTensor> {
587  let summary = "Erfc operator";
588
589  let description = [{
590    Computes the Gauss error function of `x` element-wise.
591
592    erf(x) = erf_impl(x)            if |x| < 1
593           = 1 - erfc_impl(x)       otherwise
594  }];
595}
596
597def HLOClient_ErfcOp : HLOClient_UnaryElementwiseOp<"erfc",
598    [SameOperandsAndResultType], HLO_FpTensor, HLO_FpTensor> {
599  let summary = "Erfc operator";
600
601  let description = [{
602    Computes an approximation of the error function complement (1 - erf(x)).
603
604    erfc(x) = erfc_impl(x)           if |x| > 1
605            = 1 - erf_impl(x)        otherwise
606  }];
607}
608
609def HLOClient_IsInfOp : HLOClient_UnaryElementwiseOp<"is_inf",
610    [DeclareOpInterfaceMethods<InferTypeOpInterface>], HLO_FpTensor,
611    HLO_PredTensor> {
612  let summary = "IsInf predicate";
613
614  let description = [{
615    Returns if a value is +/-inf element-wise.
616  }];
617}
618
619def HLOClient_IsNegInfOp : HLOClient_UnaryElementwiseOp<"is_neg_inf",
620    [DeclareOpInterfaceMethods<InferTypeOpInterface>], HLO_FpTensor,
621    HLO_PredTensor> {
622  let summary = "IsNegInf predicate";
623
624  let description = [{
625    Returns if a value is -inf element-wise.
626  }];
627}
628
629def HLOClient_IsPosInfOp : HLOClient_UnaryElementwiseOp<"is_pos_inf",
630    [DeclareOpInterfaceMethods<InferTypeOpInterface>], HLO_FpTensor,
631    HLO_PredTensor> {
632  let summary = "IsPosInf predicate";
633
634  let description = [{
635    Returns if a value is +inf element-wise.
636  }];
637}
638
639def HLOClient_LgammaOp : HLOClient_UnaryElementwiseOp<"lgamma",
640    [SameOperandsAndResultType], HLO_FpTensor, HLO_FpTensor> {
641  let summary = "Lgamma function";
642
643  let description = [{
644    Returns `Lgamma(operand)` element-wise.
645  }];
646}
647
648//===----------------------------------------------------------------------===//
649// Broadcasting compare op
650//===----------------------------------------------------------------------===//
651
652def HLOClient_BroadcastCompareOp : HLOClient_BroadcastBinaryElementwiseOp<
653    "broadcast_compare", [NoSideEffect]> {
654  string summary = "Compare operator (with optional broadcasting)";
655
656  string description = [{
657    Compares `lhs` and `rhs` elementwise according to `comparison_direction`
658    and `compare_type`. If unspecified, `compare_type` is FLOAT for float element
659    types, SIGNED for signed element types and UNSIGNED for unsigned element
660    types.
661
662    See
663    https://www.tensorflow.org/xla/operation_semantics#element-wise_comparison_operations.
664  }];
665
666  let arguments = (ins
667    HLO_Tensor:$lhs,
668    HLO_Tensor:$rhs,
669    OptionalAttr<BroadcastDimAttr>:$broadcast_dimensions,
670    HLO_ComparisonDirectionAttr:$comparison_direction,
671    OptionalAttr<HLO_ComparisonTypeAttr>:$compare_type
672  );
673  let results = (outs HLO_PredTensor);
674
675  let builders = [
676    OpBuilderDAG<(ins "Value":$lhs, "Value":$rhs,
677      "DenseIntElementsAttr":$broadcast_dimensions,
678      "StringAttr":$comparison_direction, CArg<"StringAttr", "{}">:$compare_type)>];
679}
680
681#endif  // CHLO_OPS
682