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 OpSpecificationVerificationType InferencePretty PrintingInterpreter
absyesyesyesyesyes
addyesyesyesyesyes
after_allyesyesyesyesyes
all_gatheryesrevisitnonoyes
all_reduceyesrevisityesnoyes
all_to_allyesrevisityesnoyes
andyesyesyesyesyes
atan2yesyesyesyesyes
batch_norm_gradyesrevisityesnorevisit
batch_norm_inferenceyesrevisityesnorevisit
batch_norm_trainingyesrevisityesnorevisit
bitcast_convertyesyesinfeasibleyesyes
broadcastnoyes*yes*yesrevisit
broadcast_in_dimyesyesinfeasibleyesyes
caseyesrevisityesnoyes
cbrtyesyesyesyesyes
ceilyesyesyesyesyes
choleskyyesyesyesyesrevisit
clampyesrevisityesyesyes
collective_broadcastyesrevisityesnoyes
collective_permuteyesrevisityesnoyes
compareyesyesyesyesyes
complexyesyesyesyesyes
compositeyesyesinfeasibleyesyes
concatenateyesyesyesyesyes
constantyesyesyesyesyes
convertyesyesinfeasibleyesyes
convolutionyesyesinfeasiblerevisityes
cosineyesyesyesyesyes
count_leading_zerosyesyesyesyesyes
create_tokennoyes*yes*yesrevisit
cross-replica-sumnorevisityes*norevisit
custom_callyesyesinfeasibleyesyes
divideyesyesyesyesyes
dotnorevisitinfeasibleyesrevisit
dot_generalyesrevisitinfeasiblenoyes
dynamic_broadcast_in_dimyesyesinfeasibleyesrevisit
dynamic_convyesyesinfeasiblerevisitrevisit
dynamic_gatheryesyesinfeasiblenorevisit
dynamic_iotayesyesinfeasibleyesrevisit
dynamic_padyesyesinfeasibleyesrevisit
dynamic_reshapeyesyesinfeasibleyesrevisit
dynamic_sliceyesyesyesyesyes
dynamic_update_sliceyesyesyesyesyes
einsumnorevisitnoyesrevisit
exponentialyesyesyesyesyes
exponential_minus_oneyesyesyesyesyes
fftyesrevisityesyesyes
flooryesyesyesyesyes
gatheryesyesyesnoyes
get_dimension_sizeyesyesyesyesyes
get_tuple_elementyesyesyesyesyes
ifyesrevisityesnoyes
imagyesyesyesyesyes
infeedyesyesinfeasiblenoyes
iotayesyesinfeasibleyesyes
is_finiteyesyesyesyesyes
logyesyesyesyesyes
log_plus_oneyesyesyesyesyes
logisticyesyesyesyesyes
mapyesrevisityesnoyes
maximumyesyesyesyesyes
minimumyesyesyesyesyes
multiplyyesyesyesyesyes
negateyesyesyesyesyes
notyesyesyesyesyes
optimization_barrieryesyesyesyesyes
oryesyesyesyesyes
outfeedyesyesyesnoyes
padyesyesyesyesyes
partition_idyesyesyesyesyes
popcntyesyesyesyesyes
poweryesyesyesyesyes
realyesyesyesyesyes
real_dynamic_slicenorevisitnoyesno
recvyesyesinfeasiblenoyes
reduceyesrevisityesrevisityes
reduce_precisionyesyesyesyesyes
reduce_scatteryesrevisitnonoyes
reduce_windowyesrevisityesnoyes
remainderyesyesyesyesyes
replica_idyesyesyesyesyes
reshapeyesyesinfeasibleyesyes
returnnorevisitinfeasibleyesyes
reverseyesyesyesyesyes
rngyesyesyesyesrevisit
rng_bit_generatoryesrevisitinfeasibleyesrevisit
round_nearest_afzyesyesyesyesyes
round_nearest_evenyesyesyesyesyes
rsqrtyesyesyesyesyes
scatteryesrevisityesnoyes
selectyesyesyesyesyes
select_and_scatteryesrevisityesnoyes
sendyesyesyesnoyes
set_dimension_sizenoyes*yes*yesno
shift_leftyesyesyesyesyes
shift_right_arithmeticyesyesyesyesyes
shift_right_logicalyesyesyesyesyes
signyesyesyesyesyes
sineyesyesyesyesyes
sliceyesyesyesnoyes
sortyesyesyesnoyes
sqrtyesyesyesyesyes
subtractyesyesyesyesyes
tanyesyesyesyesyes
tanhyesyesyesyesyes
torch_index_selectnorevisitnonorevisit
transposeyesyesyesyesyes
triangular_solveyesrevisityesnoyes
tupleyesyesyesyesyes
unary_einsumnorevisitnoyesrevisit
uniform_dequantizeyesyesyesyesyes
uniform_quantizeyesrevisitinfeasibleyesyes
whileyesrevisityesrevisityes
xoryesyesyesyesyes

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.