StableHLO status

When bootstrapping StableHLO from MHLO, we have inherited MHLO's implementation of many things, including prettyprinting, verification and shape inference. Thanks to that, we already have significant coverage of the opset, but there's still plenty to do to review the existing implementations for completeness and provide new implementations where none exist.

This live document is for the developers and the users to track the progress on various aspects of the opset - specification, verification, type inference, pretty printing, interpreter, etc.

How to use it

The progress of a StableHLO op, as mentioned in the corresponding row, on a particular aspect, as mentioned in the corresponding column, is tracked using one of the following tracking labels.

  • Generic labels
    • yes: there is a comprehensive implementation.
    • no: there is no implementation, but working on that is part of the roadmap. Note that Verifier can never be labeled as "no" because the ODS already implements some verification.
  • Customized labels for Verifier and Type Inference
    • yes: there is an implementation, and it's in sync with StableHLO semantics.
    • yes*: there is an implementation, and it's in sync with XLA semantics. Since XLA semantics is oftentimes underdocumented, we are using hlo_verifier.cc and shape_inference.cc as the reference.
    • revisit: there is an implementation, but it doesn't fall under "yes" or "yes*" - either because we haven't audited it yet, or because we have and found issues.
    • infeasible: there is no implementation, because it's infeasible. For example, because the result type of an op cannot be inferred from its operands and attributes.

Status

StableHLO Op Specification Verification Type Inference Pretty Printing Interpreter
abs yes yes yes yes yes
add yes yes yes yes yes
after_all yes yes yes yes yes
all_gather yes revisit no no yes
all_reduce yes revisit yes no yes
all_to_all yes revisit yes no yes
and yes yes yes yes yes
atan2 yes yes yes yes yes
batch_norm_grad yes revisit yes no revisit
batch_norm_inference yes revisit yes no revisit
batch_norm_training yes revisit yes no revisit
bitcast_convert yes yes infeasible yes yes
broadcast no yes* yes* yes revisit
broadcast_in_dim yes yes infeasible yes yes
case yes revisit yes no yes
cbrt yes yes yes yes yes
ceil yes yes yes yes yes
cholesky yes yes yes yes revisit
clamp yes revisit yes yes yes
collective_broadcast yes revisit yes no yes
collective_permute yes revisit yes no yes
compare yes yes yes yes yes
complex yes yes yes yes yes
composite yes yes infeasible yes yes
concatenate yes yes yes yes yes
constant yes yes yes yes yes
convert yes yes infeasible yes yes
convolution yes yes infeasible revisit yes
cosine yes yes yes yes yes
count_leading_zeros yes yes yes yes yes
create_token no yes* yes* yes revisit
cross-replica-sum no revisit yes* no revisit
custom_call yes yes infeasible yes yes
divide yes yes yes yes yes
dot no revisit infeasible yes revisit
dot_general yes revisit infeasible no yes
dynamic_broadcast_in_dim yes yes infeasible yes revisit
dynamic_conv yes yes infeasible revisit revisit
dynamic_gather yes yes infeasible no revisit
dynamic_iota yes yes infeasible yes revisit
dynamic_pad yes yes infeasible yes revisit
dynamic_reshape yes yes infeasible yes revisit
dynamic_slice yes yes yes yes yes
dynamic_update_slice yes yes yes yes yes
einsum no revisit no yes revisit
exponential yes yes yes yes yes
exponential_minus_one yes yes yes yes yes
fft yes revisit yes yes no
floor yes yes yes yes yes
gather yes yes yes no yes
get_dimension_size yes yes yes yes yes
get_tuple_element yes yes yes yes yes
if yes revisit yes no yes
imag yes yes yes yes yes
infeed yes yes infeasible no yes
iota yes yes infeasible yes yes
is_finite yes yes yes yes yes
log yes yes yes yes yes
log_plus_one yes yes yes yes yes
logistic yes yes yes yes yes
map yes revisit yes no yes
maximum yes yes yes yes yes
minimum yes yes yes yes yes
multiply yes yes yes yes yes
negate yes yes yes yes yes
not yes yes yes yes yes
optimization_barrier yes yes yes yes yes
or yes yes yes yes yes
outfeed yes yes yes no yes
pad yes yes yes yes yes
partition_id yes yes yes yes yes
popcnt yes yes yes yes yes
power yes yes yes yes yes
real yes yes yes yes yes
real_dynamic_slice no revisit no yes no
recv yes yes infeasible no yes
reduce yes revisit yes revisit yes
reduce_precision yes yes yes yes yes
reduce_scatter yes revisit no no yes
reduce_window yes revisit yes no yes
remainder yes yes yes yes yes
replica_id yes yes yes yes yes
reshape yes yes infeasible yes yes
return no revisit infeasible yes yes
reverse yes yes yes yes yes
rng yes yes yes yes revisit
rng_bit_generator yes revisit infeasible yes revisit
round_nearest_afz yes yes yes yes yes
round_nearest_even yes yes yes yes yes
rsqrt yes yes yes yes yes
scatter yes revisit yes no yes
select yes yes yes yes yes
select_and_scatter yes revisit yes no yes
send yes yes yes no yes
set_dimension_size no yes* yes* yes no
shift_left yes yes yes yes yes
shift_right_arithmetic yes yes yes yes yes
shift_right_logical yes yes yes yes yes
sign yes yes yes yes yes
sine yes yes yes yes yes
slice yes yes yes no yes
sort yes yes yes no yes
sqrt yes yes yes yes yes
subtract yes yes yes yes yes
tan yes yes yes yes yes
tanh yes yes yes yes yes
torch_index_select no revisit no no revisit
transpose yes yes yes yes yes
triangular_solve yes revisit yes no revisit
tuple yes yes yes yes yes
unary_einsum no revisit no yes revisit
uniform_dequantize yes yes yes yes yes
uniform_quantize yes revisit infeasible yes yes
while yes revisit yes revisit yes
xor yes yes yes yes yes

Type inference for quantized operations

The Type Inference column from the table above is intended to focus on non-quantized operations. For the majority of the quantized operations, it is not feasible to infer the result type because the quantization parameters of the result types may vary from those of the operands. With the exception of few cases where, operand and result types must match identically, or the op has constraints useful to infer result type, such ops are listed below: all_gather, all_to_all, case, collective_permute, compare, concatenate, constant, dynamic_slice, dynamic_update_slice, gather, get_tuple_element, if, infeed, is_finite, map, optimization_barrier, outfeed, pad, recv, reduce, reduce_scatter, reduce_window, reverse, scatter, select_and_scatter, send, slice, sort, transpose, tuple, uniform_dequantized, while.