Torch Operator Support List

Torch Operator NameEager Mode OperatorMap Description & Graph Fusion DescriptionHBIR Operator NameBPU Support Constraints
torch.acoshorizon.nn.Acosif qat:
func.func @forward(%arg0){
%0 = "qnt.quantize"(%arg0)
%1 = "hbir.constant"()
%2 = "b30.lut"(%0, %1)
%3 = "qnt.dequantize"(%2)
%4 = "qnt.const_fake_quant"(%3)
return %4
}
b30.lutinputs:
Type: int8, int16
outputs:
If input is int8, output is int8; if input is int16, output is int8/int16
torch.acoshhorizon.nn.Acoshif qat:
func.func @forward(%arg0){
%0 = "qnt.quantize"(%arg0)
%1 = "hbir.constant"()
%2 = "b30.lut"(%0, %1)
%3 = "qnt.dequantize"(%2)
%4 = "qnt.const_fake_quant"(%3)
return %4
}
b30.lutinputs:
Type: int8, int16
outputs:
If input is int8, output is int8; if input is int16, output is int8/int16
torch.add
torch.Tensor.add
torch.nn.quantized.FloatFunctional OR
horizon.nn.quantized.FloatFunctional
if alpha == 1:
func.func @forward(%arg0, %arg1){
%0 = "hbir.add"(%arg0, %arg1)
return %0
}
hbir.addlhs:
Type: int8, int16, int32, if type is int32, this hbir.add op must be fusible to a Conv op
Shape: [*]
rhs:
Same as lhs
output:
Same as lhs
if alpha != 1:
func.func @forward(%arg0, %arg1){
%0 = "hbir.constant"()
%1 = "hbir.mul"(%arg1, %0)
%2 = "hbir.add"(%arg0, %1)
return %2
}
hbir.mullhs:
Type: int8, int16
Shape: [*]
rhs:
Same as lhs
output:
Same as lhs
hbir.addlhs:
Type: int8, int16, int32, if type is int32, this hbir.add op must be fusible to a Conv op
Shape: [*]
rhs:
Same as lhs
output:
Same as lhs
torch.argmax
torch.Tensor.argmax
Nonefunc.func @forward(%arg0){
%0 = "hbir.reduce_argmax"(%arg0)
return %0
}
hbir.reduce_argmaxinput:
Type: int8, int16
Shape: [*]
output:
Same as input, but output can be of type int32 or int64, as long as the size of the reduced axis can be represented using an int16 number
torch.argmin
torch.Tensor.argmin
Nonefunc.func @forward(%arg0){
%0 = "hbir.reduce_argmin"(%arg0)
return %0
}
hbir.reduce_argminTBD
torch.asinhorizon.nn.Asinif qat:
func.func @forward(%arg0){
%0 = "qnt.quantize"(%arg0)
%1 = "hbir.constant"()
%2 = "b30.lut"(%0, %1)
%3 = "qnt.dequantize"(%2)
%4 = "qnt.const_fake_quant"(%3)
return %4
}
b30.lutinputs:
Type: int8, int16
outputs:
If input is int8, output is int8; if input is int16, output is int8/int16
torch.asinhhorizon.nn.Asinhif qat:
func.func @forward(%arg0){
%0 = "hbir.constant"()
%1 = "hbir.max"(%arg0, %0)
%2 = "hbir.clip"(%1)
%3 = "qnt.quantize"(%2)
%4 = "hbir.constant"()
%5 = "b30.lut"(%3, %4)
%6 = "qnt.dequantize"(%5)
%7 = "qnt.const_fake_quant"(%6)
return %7
}
b30.lutinputs:
Type: int8, int16
outputs:
If input is int8, output is int8; if input is int16, output is int8/int16
hbir.maxlhs:
Type: int8, int16
Shape: [*]
rhs:
Same as lhs
output:
Same as lhs
hbir.clipinput:
Type: int8, int16
Shape: [*]
output:
Same as input
torch.atanhorizon.nn.Atanif qat:
func.func @forward(%arg0){
%0 = "qnt.quantize"(%arg0)
%1 = "hbir.constant"()
%2 = "b30.lut"(%0, %1)
%3 = "qnt.dequantize"(%2)
%4 = "qnt.const_fake_quant"(%3)
return %4
}
b30.lutinputs:
Type: int8, int16
outputs:
If input is int8, output is int8; if input is int16, output is int8/int16
torch.atanhhorizon.nn.Atanif qat:
func.func @forward(%arg0){
%0 = "qnt.quantize"(%arg0)
%1 = "hbir.constant"()
%2 = "b30.lut"(%0, %1)
%3 = "qnt.dequantize"(%2)
%4 = "qnt.const_fake_quant"(%3)
return %4
}
b30.lutinputs:
Type: int8, int16
outputs:
If input is int8, output is int8; if input is int16, output is int8/int16
torch.ceilhorizon.nn.Ceilif qat:
func.func @forward(%arg0){
%0 = "qnt.quantize"(%arg0)
%1 = "hbir.constant"()
%2 = "b30.lut"(%0, %1)
%3 = "qnt.dequantize"(%2)
%4 = "qnt.const_fake_quant"(%3)
return %4
}
b30.lutinputs:
Type: int8, int16
outputs:
If input is int8, output is int8; if input is int16, output is int8/int16
torch.clamp
torch.clip
torch.Tensor.clamp
torch.Tensor.clip
 if isinstance(args, scalar):
func.func @forward(%arg0, %arg1, %arg2){
%0 = "hbir.clip"(%arg0)
return %0
}
hbir.clipinput:
Type: int8, int16
Shape: [*]
output:
Same as input
if isinstance(args, Tensor):
func.func @forward(%arg0, %arg1, %arg2){
%0 = "hbir.max"(%arg0, %arg1)
%1 = "hbir.min"(%0, %arg2)
return %1
}
hbir.maxlhs:
Type: int8, int16
Shape: [*]
rhs:
Same as lhs
output:
Same as lhs
hbir.minlhs:
Type: int8, int16
Shape: [*]
rhs:
Same as lhs
output:
Same as lhs
torch.cat
torch.concat
torch.concatenate
torch.nn.quantized.FloatFunctional OR
horizon.nn.quantized.FloatFunctional
func.func @forward(%arg0){
%0 = "hbir.concat"(%arg0)
return %0
}
hbir.concatinputs:
Arg Number: inputs number ∈ [1, 1024]
Dim: all dims < 131072
size < 2G
output:
same as inputs
torch.coshorizon.nn.Cosif qat:
func.func @forward(%arg0){
%0 = "qnt.quantize"(%arg0)
%1 = "hbir.constant"()
%2 = "b30.lut"(%0, %1)
%3 = "qnt.dequantize"(%2)
%4 = "qnt.const_fake_quant"(%3)
return %4
}
b30.lutinputs:
Type: int8, int16
outputs:
If input is int8, output is int8; if input is int16, output is int8/int16
torch.coshhorizon.nn.Coshif qat:
func.func @forward(%arg0){
%0 = "qnt.quantize"(%arg0)
%1 = "hbir.constant"()
%2 = "b30.lut"(%0, %1)
%3 = "qnt.dequantize"(%2)
%4 = "qnt.const_fake_quant"(%3)
return %4
}
b30.lutinputs:
Type: int8, int16
outputs:
If input is int8, output is int8; if input is int16, output is int8/int16
torch.divhorizon.nn.Divif qat:
func.func @forward(%arg0, %arg1){
%0 = "qnt.quantize"(%arg1)
%1 = "hbir.constant"()
%2 = "b30.lut"(%0, %1)
%3 = "qnt.dequantize"(%2)
%4 = "qnt.const_fake_quant"(%3)
%5 = "hbir.mul"(%arg0, %4)
%6 = "qnt.const_fake_quant"(%5)
return %6
}
else:
func.func @forward(%arg0, %arg1){
%0 = "hbir.div"(%arg0, %arg1)
return %0
}
b30.lutinputs:
Type: int8, int16
outputs:
If input is int8, output is int8; if input is int16, output is int8/int16
hbir.mullhs:
Type: int8, int16
Shape: [*]
rhs:
Same as lhs
output:
Same as lhs
torch.eq
torch.Tensor.eq
 func.func @forward(%arg0, %arg1){
%0 = "hbir.equal"(%arg0, %arg1)
return %0
}
hbir.equallhs:
Type: int8, int16
Shape: [*]
rhs:
Same as lhs
output:
Type: bool8
torch.gt
torch.greater
torch.Tensor.gt
torch.Tensor.greater
 func.func @forward(%arg0, %arg1){
%0 = "hbir.greater"(%arg0, %arg1)
return %0
}
hbir.greaterTBD
torch.lt
torch.less
torch.Tensor.lt
torch.Tensor.less
 func.func @forward(%arg0, %arg1){
%0 = "hbir.less"(%arg0, %arg1)
return %0
}
hbir.lessTBD
torch.erfhorizon.nn.Erfif qat:
func.func @forward(%arg0){
%0 = "qnt.quantize"(%arg0)
%1 = "hbir.constant"()
%2 = "b30.lut"(%0, %1)
%3 = "qnt.dequantize"(%2)
%4 = "qnt.const_fake_quant"(%3)
return %4
}
b30.lutinputs:
Type: int8, int16
outputs:
If input is int8, output is int8; if input is int16, output is int8/int16
torch.exphorizon.nn.Expif qat:
func.func @forward(%arg0){
%0 = "qnt.quantize"(%arg0)
%1 = "hbir.constant"()
%2 = "b30.lut"(%0, %1)
%3 = "qnt.dequantize"(%2)
%4 = "qnt.const_fake_quant"(%3)
return %4
}
b30.lutinputs:
Type: int8, int16
outputs:
If input is int8, output is int8; if input is int16, output is int8/int16
torch.Tensor.expand func.func @forward(%arg0){
%0 = "hbir.reshape"(%arg0)
%1 = "hbir.concat"(%0, %0, %0)
return %1
}
hbir.reshapeinputs:
no limits
output:
same as inputs
hbir.concatinputs:
Arg Number: inputs number ∈ [1, 1024]
Dim: all dims < 131072
size < 2G
output:
same as inputs
torch.flatten
torch.Tensor.flatten
Nonefunc.func @forward(%arg0){
%0 = "hbir.reshape"(%arg0)
return %0
}
hbir.reshapeinputs:
no limits
output:
same as inputs
torch.floorhorizon.nn.Floorif qat:
func.func @forward(%arg0){
%0 = "qnt.quantize"(%arg0)
%1 = "hbir.constant"()
%2 = "b30.lut"(%0, %1)
%3 = "qnt.dequantize"(%2)
%4 = "qnt.const_fake_quant"(%3)
return %4
}
b30.lutinputs:
Type: int8, int16
outputs:
If input is int8, output is int8; if input is int16, output is int8/int16
torch.remainderhorizon.nn.Remainderfunc.func @forward(%arg0, %arg1) {
%0 = "hbir.mod"(%arg0, %arg1)
return %0
}
hbir.modTBD
torch.gather
torch.Tensor.gather
 func.func @forward(%arg0, %arg1){
%0 = "hbir.gather"(%arg0, %arg1)
return %0
}
hbir.gatherUnsupported
torch.index_select
torch.Tensor.index_select
Nonefunc.func @forward(%arg0){
%0 = "hbir.index"(%arg0)
return %0
}
hbir.indexTBD
torch.loghorizon.nn.HardLogif qat:
func.func @forward(%arg0){
%0 = "qnt.quantize"(%arg0)
%1 = "hbir.constant"()
%2 = "b30.lut"(%0, %1)
%3 = "qnt.dequantize"(%2)
%4 = "qnt.const_fake_quant"(%3)
return %4
}
b30.lutinputs:
Type: int8, int16
outputs:
If input is int8, output is int8; if input is int16, output is int8/int16
torch.Tensor.masked_fillNonefunc.func @forward(%arg0){
%0 = "hbir.constant"()
%1 = "hbir.constant"()
%2 = "hbir.where"(%0, %1, %arg0)
return %2
}
hbir.whereTBD
torch.matmulhorizon.nn.quantized.FloatFunctionalfunc.func @forward(%arg0, %arg1){
%0 = "hbir.matmul"(%arg0, %arg1)
return %0
}
hbir.matmullhs:
Type: int8, int16; lhs and rhs cannot both be int16
Shape: [*,M,C]
Dim: * ∈ [1, 4096], M,C ∈ [1, 8192]
rhs:
Type: int8, int16; lhs and rhs cannot both be int16
Shape: [*,C,N]
Dim: * ∈ [1, 4096]; C,N ∈ [1, 8192]
output:
Type: int8, int16, int32
Shape: [*,M,N]
Other constraints: same as lhs
torch.max
torch.Tensor.max
 if dim is None:
func.func @forward(%arg0){
%0 = "hbir.reduce_max"(%arg0)
return %0
}
hbir.reduce_maxinput:
Type: int8, int16
Shape: [*]
output:
Same as input
if dim is not None:
func.func @forward(%arg0){
%0 = "hbir.reduce_max"(%arg0)
%1 = "hbir.reduce_argmax"(%arg0)
return %0
}
hbir.reduce_maxinput:
Type: int8, int16
Shape: [*]
output:
Same as input
hbir.reduce_argmaxinput:
Type: int8, int16
Shape: [*]
output:
Same as input, but output can be of type int32 or int64, as long as the size of the reduced axis can be represented using an int16 number
if give two tensors:
func.func @forward(%arg0, %arg1){
%0 = "hbir.max"(%arg0, %arg1)
return %0
}
hbir.maxlhs:
Type: int8, int16
Shape: [*]
rhs:
Same as lhs
output:
Same as lhs
torch.meanhorizon.nn.quantized.FloatFunctionalfunc.func @forward(%arg0){
%0 = "hbir.reduce_mean"(%arg0)
return %0
}
hbir.reduce_meaninput:
Type: int8, int16
Shape: [*]
Dim: reduce axis dim size ∈ [1, 16384]
output:
Same as input
torch.min
torch.Tensor.min
 if dim is None:
func.func @forward(%arg0){
%0 = "hbir.reduce_min"(%arg0)
return %0
}
hbir.reduce_mininput:
Type: int8, int16
Shape: [*]
output:
Same as input
if dim is not None:
func.func @forward(%arg0){
%0 = "hbir.reduce_min"(%arg0)
%1 = "hbir.reduce_argmin"(%arg0)
return %0
}
hbir.reduce_mininput:
Type: int8, int16
Shape: [*]
output:
Same as input
hbir.reduce_argminTBD
if give two tensors:
func.func @forward(%arg0, %arg1){
%0 = "hbir.min"(%arg0, %arg1)
return %0
}
hbir.minlhs:
Type: int8, int16
Shape: [*]
rhs:
Same as lhs
output:
Same as lhs
torch.mul
torch.Tensor.mul
torch.nn.quantized.FloatFunctional or
horizon.nn.quantized.FloatFunctional
func.func @forward(%arg0, %arg1){
%0 = "hbir.mul"(%arg0, %arg1)
return %0
}
hbir.mullhs:
Type: int8, int16
Shape: [*]
rhs:
Same as lhs
output:
Same as lhs
torch.neg
torch.negative
torch.Tensor.neg
torch.Tensor.negative
Nonefunc.func @forward(%arg0){
%0 = "hbir.neg"(%arg0)
return %0
}
hbir.negTBD
torch.permute
torch.Tensor.permute
 func.func @forward(%arg0){
%0 = "hbir.transpose"(%arg0)
return %0
}
hbir.transposeinputs:
no limits
output:
same as inputs
torch.powhorizon.nn.Powif exponent == 2:
func.func @forward(%arg0){
%0 = "hbir.mul"(%arg0, %arg0)
return %0
}
hbir.mullhs:
Type: int8, int16
Shape: [*]
rhs:
Same as lhs
output:
Same as lhs
if exponent != 2 and float:
func.func @forward(%arg0){
%0 = "hbir.constant"()
%1 = "hbir.pow"(%arg0, %0)
return %1
}
hbir.powTBD
if exponent != 2 and qat:
func.func @forward(%arg0){
%0 = "qnt.quantize"(%arg0)
%1 = "hbir.constant"()
%2 = "b30.lut"(%0, %1)
%3 = "qnt.dequantize"(%2)
%4 = "qnt.const_fake_quant"(%3)
return %4
}
b30.lutinputs:
Type: int8, int16
outputs:
If input is int8, output is int8; if input is int16, output is int8/int16
torch.reciprocalhorizon.nn.Reciprocalif qat:
func.func @forward(%arg0){
%0 = "qnt.quantize"(%arg0)
%1 = "hbir.constant"()
%2 = "b30.lut"(%0, %1)
%3 = "qnt.dequantize"(%2)
%4 = "qnt.const_fake_quant"(%3)
return %4
}
b30.lutinputs:
Type: int8, int16
outputs:
If input is int8, output is int8; if input is int16, output is int8/int16
torch.remainderhorizon.nn.Remainderfunc.func @forward(%arg0, %arg1) {
%0 = "hbir.mod"(%arg0, %arg1)
return %0
}
hbir.modTBD
torch.repeat
torch.Tensor.repeat
 func.func @forward(%arg0){
%0 = "hbir.tile"(%arg0)
return %0
}
hbir.tileinputs:
no limits
output:
same as inputs
torch.reshape
torch.Tensor.reshape
torch.view
torch.Tensor.view
Nonefunc.func @forward(%arg0){
%0 = "hbir.reshape"(%arg0)
return %0
}
hbir.reshapeinputs:
no limits
output:
same as inputs
torch.scatter
torch.Tensor.scatter
horizon.nn.Scatterfunc.func @forward(%arg0, %arg1, %arg2){
%0 = "hbir.scatter_elements"(%arg0, %arg1, %arg2)
return %0
}
hbir.scatter_elementsTBD
torch.sign
torch.Tensor.sign
Nonefunc.func @forward(%arg0){
%0 = "hbir.sign"(%arg0)
return %0
}
hbir.signTBD
torch.sinhorizon.nn.Sinif qat:
func.func @forward(%arg0){
%0 = "qnt.quantize"(%arg0)
%1 = "hbir.constant"()
%2 = "b30.lut"(%0, %1)
%3 = "qnt.dequantize"(%2)
%4 = "qnt.const_fake_quant"(%3)
return %4
}
b30.lutinputs:
Type: int8, int16
outputs:
If input is int8, output is int8; if input is int16, output is int8/int16
torch.sinhhorizon.nn.Sinhif qat:
func.func @forward(%arg0){
%0 = "qnt.quantize"(%arg0)
%1 = "hbir.constant"()
%2 = "b30.lut"(%0, %1)
%3 = "qnt.dequantize"(%2)
%4 = "qnt.const_fake_quant"(%3)
return %4
}
b30.lutinputs:
Type: int8, int16
outputs:
If input is int8, output is int8; if input is int16, output is int8/int16
torch.split func.func @forward(%arg0){
%0 = "hbir.slice"(%arg0)
%1 = "hbir.slice"(%arg0)
%2 = "hbir.slice"(%arg0)
%3 = "hbir.slice"(%arg0)
return %0, %1, %2, %3
}
hbir.sliceinput:
Dim: all dims < 2097152
output:
Same as input
torch.sqrthorizon.nn.Sqrtif qat:
func.func @forward(%arg0){
%0 = "hbir.constant"()
%1 = "hbir.max"(%arg0, %0)
%2 = "hbir.clip"(%1)
%3 = "qnt.quantize"(%2)
%4 = "hbir.constant"()
%5 = "b30.lut"(%3, %4)
%6 = "qnt.dequantize"(%5)
%7 = "qnt.const_fake_quant"(%6)
return %7
}
b30.lutinputs:
Type: int8, int16
outputs:
If input is int8, output is int8; if input is int16, output is int8/int16
hbir.maxlhs:
Type: int8, int16
Shape: [*]
rhs:
Same as lhs
output:
Same as lhs
hbir.clipinput:
Type: int8, int16
Shape: [*]
output:
Same as input
torch.squeeze
torch.Tensor.squeeze
 func.func @forward(%arg0){
%0 = "hbir.reshape"(%arg0)
return %0
}
hbir.reshapeinputs:
no limits
output:
same as inputs
torch.subhorizon.nn.quantized.FloatFunctionalif alpha == 1:
func.func @forward(%arg0, %arg1){
%0 = "hbir.sub"(%arg0, %arg1)
return %0
}
hbir.sublhs:
Type: int8, int16
Shape: [*]
rhs:
Same as lhs
output:
Same as lhs
if alpha != 1:
func.func @forward(%arg0, %arg1){
%0 = "hbir.constant"()
%1 = "hbir.mul"(%arg1, %0)
%2 = "hbir.sub"(%arg0, %1)
return %2
}
hbir.mullhs:
Type: int8, int16
Shape: [*]
rhs:
Same as lhs
output:
Same as lhs
hbir.sublhs:
Type: int8, int16
Shape: [*]
rhs:
Same as lhs
output:
Same as lhs
torch.sumhorizon.nn.quantized.FloatFunctionalfunc.func @forward(%arg0){
%0 = "hbir.reduce_sum"(%arg0)
return %0
}
hbir.reduce_suminput:
Type: int8, int16
Shape: [*]
Dim: reduce axis dim size ∈ [1, 16384]
output:
Same as input
torch.tanhorizon.nn.Tanif qat:
func.func @forward(%arg0){
%0 = "qnt.quantize"(%arg0)
%1 = "hbir.constant"()
%2 = "b30.lut"(%0, %1)
%3 = "qnt.dequantize"(%2)
%4 = "qnt.const_fake_quant"(%3)
return %4
}
b30.lutinputs:
Type: int8, int16
outputs:
If input is int8, output is int8; if input is int16, output is int8/int16
torch.tanhhorizon.nn.Tanhif qat:
func.func @forward(%arg0){
%0 = "qnt.quantize"(%arg0)
%1 = "hbir.constant"()
%2 = "b30.lut"(%0, %1)
%3 = "qnt.dequantize"(%2)
%4 = "qnt.const_fake_quant"(%3)
return %4
}
b30.lutinputs:
Type: int8, int16
outputs:
If input is int8, output is int8; if input is int16, output is int8/int16
torch.to
torch.float
Nonefunc.func @forward(%arg0){
%0 = "hbir.cast"(%arg0)
return %0
}
hbir.castTBD
torch.topk
torch.Tensor.topk
 func.func @forward(%arg0){
%values, %indices = "hbir.topk"(%arg0)
return %values, %indices
}
hbir.topkUnsupported
torch.transpose
torch.Tensor.transpose
 func.func @forward(%arg0){
%0 = "hbir.transpose"(%arg0)
return %0
}
hbir.transposeinputs:
no limits
output:
same as inputs
torch.trilNonefunc.func @forward(%arg0){
%0 = "hbir.constant"()
%1 = "hbir.constant"()
%2 = "hbir.where"(%0, %arg0, 1)
return %2
}
hbir.whereTBD
torch.triuNonefunc.func @forward(%arg0){
%0 = "hbir.constant"()
%1 = "hbir.constant"()
%2 = "hbir.where"(%0, %arg0, 1)
return %2
}
hbir.whereTBD
torch.unsqueeze
torch.Tensor.unsqueeze
 func.func @forward(%arg0){
%0 = "hbir.reshape"(%arg0)
return %0
}
hbir.reshapeinputs:
no limits
output:
same as inputs
torch.where
torch.Tensor.where
horizon.nn.Wherefunc.func @forward(%arg0, %arg1){
%0 = "hbir.constant"()
%1 = "hbir.where"(%0, %arg0, %arg1)
return %1
}
hbir.whereTBD
torch.zeros_like
torch.ones_like
torch.full_like
torch.rand_like
Nonefunc.func @forward(%arg0){
%0 = "hbir.constant"()
return %0
}
hbir.constantNone
torch.nn.functional.adaptive_avg_pool1d
torch.nn.AdaptiveAvgPool1d
torch.nn.AdaptiveAvgPool1dfunc.func @forward(%arg0){
%0 = "hbir.reshape"(%arg0)
%1 = "hbir.avg_pool2d"(%0)
%2 = "hbir.reshape"(%1)
return %2
}
hbir.reshapeinputs:
no limits
output:
same as inputs
hbir.avg_pool2dinput:
Type: int8, int16
Shape: [*,H,W,C]
output:
Same as input
kernel:
Shape: [KH,KW]
Dim: KH, KW ∈ [1, 256]
stride:
Shape: [SH,SW]
Dim: SH, SW ∈ [1, 256]
pad:
Shape: [PN,PH,PW,PC]
PN,PH,PW,PC ∈ [-3, 256]
torch.nn.functional.adaptive_avg_pool2d
torch.nn.AdaptiveAvgPool2d
torch.nn.AdaptiveAvgPool2dfunc.func @forward(%arg0){
%0 = "hbir.transpose"(%arg0)
%1 = "hbir.avg_pool2d"(%0)
%2 = "hbir.transpose"(%1)
return %2
}
hbir.transposeinputs:
no limits
output:
same as inputs
hbir.avg_pool2dinput:
Type: int8, int16
Shape: [*,H,W,C]
output:
Same as input
kernel:
Shape: [KH,KW]
Dim: KH, KW ∈ [1, 256]
stride:
Shape: [SH,SW]
Dim: SH, SW ∈ [1, 256]
pad:
Shape: [PN,PH,PW,PC]
PN,PH,PW,PC ∈ [-3, 256]
torch.nn.functional.affine_grid func.func @forward(%arg0){
%0 = "hbir.constant"()
%1 = "hbir.transpose"(%arg0)
%2 = "hbir.matmul"(%0, %1)
%3 = "hbir.reshape"(%2)
return %3
}
hbir.transposeinputs:
no limits
output:
same as inputs
hbir.matmullhs:
Type: int8, int16; lhs and rhs cannot both be int16
Shape: [*,M,C]
Dim: * ∈ [1, 4096], M,C ∈ [1, 8192]
rhs:
Type: int8, int16; lhs and rhs cannot both be int16
Shape: [*,C,N]
Dim: * ∈ [1, 4096]; C,N ∈ [1, 8192]
output:
Type: int8, int16, int32
Shape: [*,M,N]
Other constraints: same as lhs
hbir.reshapeinputs:
no limits
output:
same as inputs
torch.nn.functional.avg_pool2d
torch.nn.AvgPool2d
 func.func @forward(%arg0){
%0 = "hbir.transpose"(%arg0)
%1 = "hbir.avg_pool2d"(%0)
%2 = "hbir.transpose"(%1)
return %2
}
hbir.transposeinputs:
no limits
output:
same as inputs
hbir.avg_pool2dinput:
Type: int8, int16
Shape: [*,H,W,C]
output:
Same as input
kernel:
Shape: [KH,KW]
Dim: KH, KW ∈ [1, 256]
stride:
Shape: [SH,SW]
Dim: SH, SW ∈ [1, 256]
pad:
Shape: [PN,PH,PW,PC]
PN,PH,PW,PC ∈ [-3, 256]
torch.nn.functional.dropout
torch.nn.Dropout
torch.nn.functional.dropout2d
torch.nn.Dropout2d
torch.nn.Dropoutfunc.func @forward(%arg0){
return %arg0
}
TBDTBD
torch.nn.EmbeddingNonefunc.func @forward(%arg0){
%0 = "hbir.constant"()
%1 = "hbir.reshape"(%arg0)
%2 = "hbir.gather_nd"(%0, %1)
%3 = "hbir.reshape"(%2)
return %3
}
hbir.gather_ndTBD
hbir.reshapeinputs:
no limits
output:
same as inputs
torch.nn.functional.gelu
torch.nn.GELU
torch.nn.GELUif qat:
func.func @forward(%arg0){
%0 = "qnt.quantize"(%arg0)
%1 = "hbir.constant"()
%2 = "b30.lut"(%0, %1)
%3 = "qnt.dequantize"(%2)
%4 = "qnt.const_fake_quant"(%3)
return %4
}
b30.lutinputs:
Type: int8, int16
outputs:
If input is int8, output is int8; if input is int16, output is int8/int16
torch.nn.functional.glu
torch.nn.GLU
torch.nn.GLUmodule {
func.func @forward(%arg0){
%0 = "qnt.const_fake_quant"(%arg0)
%1 = "hbir.slice"(%0)
%2 = "hbir.slice"(%0)
%3 = "qnt.quantize"(%2)
%4 = "hbir.constant"()
%5 = "b25.lut"(%3, %4)
%6 = "qnt.dequantize"(%5)
%7 = "qnt.const_fake_quant"(%6)
%8 = "hbir.mul"(%1, %7)
%9 = "qnt.const_fake_quant"(%8)
return %9
}
}
b30.lutinputs:
Type: int8, int16
outputs:
If input is int8, output is int8; if input is int16, output is int8/int16
hbir.sliceinput:
Dim: all dims < 2097152
output:
Same as input
hbir.mullhs:
Type: int8, int16
Shape: [*]
rhs:
Same as lhs
output:
Same as lhs
torch.nn.functional.grid_sample func.func @forward(%arg0, %arg1){
%0 = "hbir.transpose"(%arg0)
%1 = "hbir.grid_sample"(%0, %arg1)
%2 = "hbir.transpose"(%1)
return %2
}
hbir.transposeinputs:
no limits
output:
same as inputs
hbir.grid_sampleinput:
Type: int8
Shape: [*,H,W,C]
Dim: H,W ∈ [1, 1024]; H\*W ≤ 720\*1024; other dims ∈ [1, 65536]
grid:
Type: int16
Shape: [*,H,W,2]
output:
Same as input except Dim constraints
torch.nn.functional.hardsigmoid
torch.nn.HardSigmoid
torch.nn.HardSigmoidif qat:
func.func @forward(%arg0){
%0 = "qnt.quantize"(%arg0)
%1 = "hbir.constant"()
%2 = "b30.lut"(%0, %1)
%3 = "qnt.dequantize"(%2)
%4 = "qnt.const_fake_quant"(%3)
return %4
}
b30.lutinputs:
Type: int8, int16
outputs:
If input is int8, output is int8; if input is int16, output is int8/int16
torch.nn.functional.interpolate
torch.nn.Upsample
torch.nn.UpsamplingNearest2d
torch.nn.UpsamplingBilinear2d
 func.func @forward(%arg0){
%0 = "hbir.transpose"(%arg0)
%1 = "hbir.resize2d"(%0)
%2 = "hbir.transpose"(%1)
return %2
}
hbir.transposeinputs:
no limits
output:
same as inputs
hbir.resize2dinput:
Type: int8
Shape: [*,H,W,C]
output:
Same as input
torch.nn.functional.leaky_relu
torch.nn.LeakyReLU
torch.nn.LeakyReLUif qat:
func.func @forward(%arg0){
%0 = "qnt.quantize"(%arg0)
%1 = "hbir.constant"()
%2 = "b30.lut"(%0, %1)
%3 = "qnt.dequantize"(%2)
%4 = "qnt.const_fake_quant"(%3)
return %4
}
b30.lutinputs:
Type: int8, int16
outputs:
If input is int8, output is int8; if input is int16, output is int8/int16
torch.nn.functional.pad
torch.nn.ConstantPad1d
torch.nn.ConstantPad2d
torch.nn.ConstantPad3d
torch.nn.ReplicationPad1d
torch.nn.ReplicationPad2d
torch.nn.ReplicationPad3d
torch.nn.ZeroPad2d
 func.func @forward(%arg0){
%0 = "hbir.pad"(%arg0)
return %0
}
hbir.padinput:
Type: int64, uint64 and f64 are not supported when expansionMode is 'constant' else no constraints
Dim: all dims < 737280 when expansionMode is not 'constant' else no constraints
output:
Same as input
torch.nn.functional.pixel_shuffle
torch.nn.PixelShuffle
 func.func @forward(%arg0){
%0 = "hbir.reshape"(%arg0)
%1 = "hbir.transpose"(%0)
%2 = "hbir.reshape"(%1)
return %2
}
hbir.reshapeinputs:
no limits
output:
same as inputs
hbir.transposeinputs:
no limits
output:
same as inputs
torch.nn.functional.pixel_unshuffle
torch.nn.PixelUnshuffle
 func.func @forward(%arg0){
%0 = "hbir.reshape"(%arg0)
%1 = "hbir.transpose"(%0)
%2 = "hbir.reshape"(%1)
return %2
}
hbir.reshapeinputs:
no limits
output:
same as inputs
hbir.transposeinputs:
no limits
output:
same as inputs
torch.nn.functional.relu
torch.nn.ReLU
torch.nn.ReLUfunc.func @forward(%arg0){
%0 = "hbir.relu"(%arg0)
return %0
}
hbir.reluinput:
Type: int8, int16, int32
Shape: [*]
output:
Same as input
torch.nn.functional.relu6(fused)
torch.nn.ReLU6(fused)
torch.nn.ReLU6func.func @forward(%arg0){
%0 = "hbir.clip"(%arg0)
return %0
}
hbir.clipinput:
Type: int8, int16
Shape: [*]
output:
Same as input
torch.nn.functional.silu
torch.nn.SiLU
torch.nn.SiLUif qat:
func.func @forward(%arg0){
%0 = "qnt.quantize"(%arg0)
%1 = "hbir.constant"()
%2 = "b30.lut"(%0, %1)
%3 = "qnt.dequantize"(%2)
%4 = "qnt.const_fake_quant"(%3)
return %4
}
b30.lutinputs:
Type: int8, int16
outputs:
If input is int8, output is int8; if input is int16, output is int8/int16
torch.nn.functional.softmax
torch.nn.Softmax
torch.nn.Softmaxif float:
func.func @forward(%arg0) {
%0 = "hbir.softmax"(%arg0)
return %0
}
hbir.softmaxUnsupported
if qat:
func.func @forward(%arg0){
%0 = "hbir.cast_type"(%arg0)
%1 = "hbir.reduce_max"(%0)
%2 = "hbir.reduce_argmax"(%0)
%3 = "hbir.sub"(%0, %1)
%4 = "qnt.const_fake_quant"(%3)
%5 = "qnt.quantize"(%4)
%6 = "hbir.constant"()
%7 = "b30.lut"(%5, %6)
%8 = "qnt.dequantize"(%7)
%9 = "qnt.const_fake_quant"(%8)
%10 = "hbir.reduce_sum"(%9)
%11 = "qnt.const_fake_quant"(%10)
%12 = "qnt.quantize"(%11)
%13 = "hbir.constant"()
%14 = "b30.lut"(%12, %13)
%15 = "qnt.dequantize"(%14)
%16 = "qnt.const_fake_quant"(%15)
%17 = "hbir.mul"(%9, %16)
%18 = "qnt.const_fake_quant"(%17)
return %18
}
hbir.reduce_maxinput:
Type: int8, int16
Shape: [*]
output:
Same as input
hbir.reduce_argmaxinput:
Type: int8, int16
Shape: [*]
output:
Same as input, but output can be of type int32 or int64, as long as the size of the reduced axis can be represented using an int16 number
hbir.sublhs:
Type: int8, int16
Shape: [*]
rhs:
Same as lhs
output:
Same as lhs
b30.lutinputs:
Type: int8, int16
outputs:
If input is int8, output is int8; if input is int16, output is int8/int16
hbir.reduce_suminput:
Type: int8, int16
Shape: [*]
Dim: reduce axis dim size ∈ [1, 16384]
output:
Same as input
hbir.mullhs:
Type: int8, int16
Shape: [*]
rhs:
Same as lhs
output:
Same as lhs
torch.nn.functional.softplus
torch.nn.Softplus
Noneif qat:
func.func @forward(%arg0){
%0 = "qnt.quantize"(%arg0)
%1 = "hbir.constant"()
%2 = "b30.lut"(%0, %1)
%3 = "qnt.dequantize"(%2)
%4 = "qnt.const_fake_quant"(%3)
return %4
}
b30.lutinputs:
Type: int8, int16
outputs:
If input is int8, output is int8; if input is int16, output is int8/int16
torch.nn.Conv2d if float:
func.func @forward(%arg0){
%0 = "hbir.constant"()
%1 = "hbir.constant"()
%2 = "hbir.transpose"(%arg0)
%3 = "hbir.transpose"(%0)
%4 = "hbir.conv2d"(%2, %3, %1)
%5 = "hbir.transpose"(%4)
return %5
}
hbir.transposeinputs:
no limits
output:
same as inputs
hbir.conv2dinput:
Type: int8, int16; input and weight cannot both be int16
Shape: [*,H,W,C]
Dim: * ∈ [1, 4096]; H,W,C ∈ [1, 65536]
weight:
Type: int8, int16; input and weight cannot both be int16
Shape: [N,KH,KW,C]
Dim: C ∈ [1, 8192]; KH,KW ∈ [1, 31]; N ∈ [1, 65536] if fout is the last layer of conv else [1, 8192]
Size: KH\*KW\*C ∈ [1, 65536]
bias:
Type: f32
output:
Type: int8, int16, int32
Other constraints: same as fin
stride:
Shape: [SH,SW]
Dim: SH,SW ∈ [1, 256]; SH,SW ∈ {1} if dilation > 1
pad:
Shape: [PN,PH,PW,PC]
Dim: PN,PH,PW,PC ∈ [-1, 256]
groupNum:
fin.c is divisible by group number
dilation:
Shape: [DH,DW]
Dim: DH,DW ∈ [1, 18]
others:
Don't support even stride when conv is a depthwise conv
For each group, fin.c ∈ [1, 8192], KH\*KW\*fin.c ∈ [1, 65535], fin.c = C when group = 1
if qat:
func.func @forward(%arg0){
%0 = "hbir.constant"()
%1 = "qnt.const_fake_quant"(%0)
%2 = "hbir.constant"()
%3 = "hbir.transpose"(%arg0)
%4 = "hbir.transpose"(%1)
%5 = "hbir.conv2d"(%3, %4, %2)
%6 = "hbir.transpose"(%5)
%7 = "qnt.const_fake_quant"(%6)
return %7
}
hbir.transposeinputs:
no limits
output:
same as inputs
hbir.conv2dinput:
Type: int8, int16; input and weight cannot both be int16
Shape: [*,H,W,C]
Dim: * ∈ [1, 4096]; H,W,C ∈ [1, 65536]
weight:
Type: int8, int16; input and weight cannot both be int16
Shape: [N,KH,KW,C]
Dim: C ∈ [1, 8192]; KH,KW ∈ [1, 31]; N ∈ [1, 65536] if fout is the last layer of conv else [1, 8192]
Size: KH\*KW\*C ∈ [1, 65536]
bias:
Type: f32
output:
Type: int8, int16, int32
Other constraints: same as fin
stride:
Shape: [SH,SW]
Dim: SH,SW ∈ [1, 256]; SH,SW ∈ {1} if dilation > 1
pad:
Shape: [PN,PH,PW,PC]
Dim: PN,PH,PW,PC ∈ [-1, 256]
groupNum:
fin.c is divisible by group number
dilation:
Shape: [DH,DW]
Dim: DH,DW ∈ [1, 18]
others:
Don't support even stride when conv is a depthwise conv
For each group, fin.c ∈ [1, 8192], KH\*KW\*fin.c ∈ [1, 65535], fin.c = C when group = 1
torch.nn.ConvTranspose2d if float:
func.func @forward(%arg0){
%0 = "hbir.constant"()
%1 = "hbir.constant"()
%2 = "hbir.transpose"(%arg0)
%3 = "hbir.transpose"(%0)
%4 = "hbir.conv2dtranspose"(%2, %3, %1)
%5 = "hbir.transpose"(%4)
return %5
}
hbir.transposeinputs:
no limits
output:
same as inputs
hbir.conv2dtransposeinput:
Type: int8, int16; input and weight cannot both be int16
Shape: [*,H,W,C]
Dim: * ∈ [1, 128]; H,W ∈ [1, 65536]; C ∈ [1, 2048]
weight:
Type: int8, int16; input and weight cannot both be int16
Shape: [N,KH,KW,C]
Dim: N,C ∈ [1, 2048]; KH,KW ∈ [1, 14]
Size: KH\*KW\*C ∈ [1, 65536]
bias:
Type: f32
output:
Same as input, the type additionally supports int32
stride:
Shape: [SH,SW]
Dim: SH,SW ∈ [1, 14]; SH < KH; SW < KW;
pad:
Shape: [PN,PH,PW,PC]
Dim: PN,PH,PW,PC ∈ [0, 256]
dilation:
Shape: [DH,DW]
Dim: DH,DW ∈ {1}
if qat:
func.func @forward(%arg0){
%0 = "hbir.constant"()
%1 = "qnt.const_fake_quant"(%0)
%2 = "hbir.reshape"(%1)
%3 = "hbir.transpose"(%2)
%4 = "hbir.reshape"(%3)
%5 = "hbir.constant"()
%6 = "hbir.transpose"(%arg0)
%7 = "hbir.transpose"(%4)
%8 = "hbir.conv2dtranspose"(%6, %7, %5)
%9 = "hbir.transpose"(%8)
%10 = "qnt.const_fake_quant"(%9)
return %10
}
hbir.transposeinputs:
no limits
output:
same as inputs
hbir.conv2dtransposeinput:
Type: int8, int16; input and weight cannot both be int16
Shape: [*,H,W,C]
Dim: * ∈ [1, 128]; H,W ∈ [1, 65536]; C ∈ [1, 2048]
weight:
Type: int8, int16; input and weight cannot both be int16
Shape: [N,KH,KW,C]
Dim: N,C ∈ [1, 2048]; KH,KW ∈ [1, 14]
Size: KH\*KW\*C ∈ [1, 65536]
bias:
Type: f32
output:
Same as input, the type additionally supports int32
stride:
Shape: [SH,SW]
Dim: SH,SW ∈ [1, 14]; SH < KH; SW < KW;
pad:
Shape: [PN,PH,PW,PC]
Dim: PN,PH,PW,PC ∈ [0, 256]
dilation:
Shape: [DH,DW]
Dim: DH,DW ∈ {1}
torch.nn.Identity func.func @forward(%arg0){
return %arg0
}
TBDTBD
torch.nn.LayerNorm if float:
func.func @forward(%arg0){
%0 = "hbir.layernorm"(%arg0)
return %0
}
hbir.layernormTBD
if qat:
func.func @forward(%arg0){
%0 = "hbir.cast_type"(%arg0)
%1 = "hbir.reduce_mean"(%0)
%2 = "qnt.const_fake_quant"(%1)
%3 = "hbir.sub"(%0, %2)
%4 = "qnt.const_fake_quant"(%3)
%5 = "hbir.mul"(%4, %4)
%6 = "qnt.const_fake_quant"(%5)
%7 = "hbir.reduce_mean"(%6)
%8 = "qnt.const_fake_quant"(%7)
%9 = "qnt.quantize"(%8)
%10 = "hbir.constant"()
%11 = "b30.lut"(%9, %10)
%12 = "qnt.dequantize"(%11)
%13 = "qnt.const_fake_quant"(%12)
%14 = "hbir.mul"(%4, %13)
%15 = "qnt.const_fake_quant"(%14)
%16 = "hbir.constant"()
%17 = "qnt.const_fake_quant"(%16)
%18 = "hbir.mul"(%15, %17)
%19 = "qnt.const_fake_quant"(%18)
%20 = "hbir.constant"()
%21 = "qnt.const_fake_quant"(%20)
%22 = "hbir.add"(%19, %21)
%23 = "qnt.const_fake_quant"(%22)
return %23
}
hbir.reduce_meaninput:
Type: int8, int16
Shape: [*]
Dim: reduce axis dim size ∈ [1, 16384]
output:
Same as input
hbir.sublhs:
Type: int8, int16
Shape: [*]
rhs:
Same as lhs
output:
Same as lhs
hbir.mullhs:
Type: int8, int16
Shape: [*]
rhs:
Same as lhs
output:
Same as lhs
b30.lutinputs:
Type: int8, int16
outputs:
If input is int8, output is int8; if input is int16, output is int8/int16
hbir.mullhs:
Type: int8, int16
Shape: [*]
rhs:
Same as lhs
output:
Same as lhs
hbir.addlhs:
Type: int8, int16, int32, if type is int32, this hbir.add op must be fusible to a Conv op
Shape: [*]
rhs:
Same as lhs
output:
Same as lhs
horizon.nn.LayerNorm if float and dim is None:
func.func @forward(%arg0){
%0 = "hbir.layernorm"(%arg0)
return %0
}
hbir.layernormTBD
if float and dim is not None:
func.func @forward(%arg0){
%0 = "hbir.reduce_mean"(%arg0)
%1 = "hbir.sub"(%arg0, %0)
%2 = "hbir.mul"(%1, %1)
%3 = "hbir.reduce_mean"(%2)
%4 = "hbir.rsqrt"(%3)
%5 = "hbir.mul"(%1, %4)
%6 = "hbir.constant"()
%7 = "hbir.mul"(%5, %6)
%8 = "hbir.constant"()
%9 = "hbir.add"(%7, %8)
return %9
}
hbir.reduce_meaninput:
Type: int8, int16
Shape: [*]
Dim: reduce axis dim size ∈ [1, 16384]
output:
Same as input
hbir.sublhs:
Type: int8, int16
Shape: [*]
rhs:
Same as lhs
output:
Same as lhs
hbir.mullhs:
Type: int8, int16
Shape: [*]
rhs:
Same as lhs
output:
Same as lhs
hbir.rsqrtTBD
hbir.addlhs:
Type: int8, int16, int32, if type is int32, this hbir.add op must be fusible to a Conv op
Shape: [*]
rhs:
Same as lhs
output:
Same as lhs
if qat:
func.func @forward(%arg0){
%0 = "hbir.cast_type"(%arg0)
%1 = "hbir.reduce_mean"(%0)
%2 = "qnt.const_fake_quant"(%1)
%3 = "hbir.sub"(%0, %2)
%4 = "qnt.const_fake_quant"(%3)
%5 = "hbir.mul"(%4, %4)
%6 = "qnt.const_fake_quant"(%5)
%7 = "hbir.reduce_mean"(%6)
%8 = "qnt.const_fake_quant"(%7)
%9 = "qnt.quantize"(%8)
%10 = "hbir.constant"()
%11 = "b30.lut"(%9, %10)
%12 = "qnt.dequantize"(%11)
%13 = "qnt.const_fake_quant"(%12)
%14 = "hbir.mul"(%4, %13)
%15 = "qnt.const_fake_quant"(%14)
%16 = "hbir.constant"()
%17 = "qnt.const_fake_quant"(%16)
%18 = "hbir.mul"(%15, %17)
%19 = "qnt.const_fake_quant"(%18)
%20 = "hbir.constant"()
%21 = "qnt.const_fake_quant"(%20)
%22 = "hbir.add"(%19, %21)
%23 = "qnt.const_fake_quant"(%22)
return %23
}
hbir.reduce_meaninput:
Type: int8, int16
Shape: [*]
Dim: reduce axis dim size ∈ [1, 16384]
output:
Same as input
hbir.sublhs:
Type: int8, int16
Shape: [*]
rhs:
Same as lhs
output:
Same as lhs
hbir.mullhs:
Type: int8, int16
Shape: [*]
rhs:
Same as lhs
output:
Same as lhs
b30.lutinputs:
Type: int8, int16
outputs:
If input is int8, output is int8; if input is int16, output is int8/int16
hbir.mullhs:
Type: int8, int16
Shape: [*]
rhs:
Same as lhs
output:
Same as lhs
hbir.addlhs:
Type: int8, int16, int32, if type is int32, this hbir.add op must be fusible to a Conv op
Shape: [*]
rhs:
Same as lhs
output:
Same as lhs
torch.nn.MaxPool2d func.func @forward(%arg0){
%0 = "hbir.transpose"(%arg0)
%1 = "hbir.max_pool2d"(%0)
%2 = "hbir.transpose"(%1)
return %2
}
hbir.transposeinputs:
no limits
output:
same as inputs
hbir.max_pool2dinput:
Type: int8, int16
Shape: [*,H,W,C]
output:
Same as input
kernel:
Shape: [KH,KW]
Dim: KH, KW ∈ [1, 256]
stride:
Shape: [SH,SW]
Dim: SH, SW ∈ [1, 256]
pad:
Shape: [PN,PH,PW,PC]
PN,PH,PW,PC ∈ [-3, 256]
torch.nn.MultiheadAttentionNonefunc.func @forward(%arg0, %arg1, %arg2, %arg3, %arg4){
%0 = "hbir.transpose"(%arg0)
%1 = "hbir.transpose"(%arg1)
%2 = "hbir.transpose"(%arg2)
%3 = "hbir.constant"()
%4 = "hbir.constant"()
%5 = "hbir.linear"(%0, %3, %4)
%6 = "hbir.constant"()
%7 = "hbir.constant"()
%8 = "hbir.linear"(%1, %6, %7)
%9 = "hbir.constant"()
%10 = "hbir.constant"()
%11 = "hbir.linear"(%2, %9, %10)
%12 = "hbir.constant"()
%13 = "hbir.concat"(%8, %12)
%14 = "hbir.constant"()
%15 = "hbir.concat"(%11, %14)
%16 = "hbir.pad"(%arg4)
%17 = "hbir.pad"(%arg3)
%18 = "hbir.reshape"(%5)
%19 = "hbir.transpose"(%18)
%20 = "hbir.reshape"(%13)
%21 = "hbir.transpose"(%20)
%22 = "hbir.reshape"(%15)
%23 = "hbir.transpose"(%22)
%24 = "hbir.constant"()
%25 = "hbir.concat"(%21, %24)
%26 = "hbir.constant"()
%27 = "hbir.concat"(%23, %26)
%28 = "hbir.pad"(%16)
%29 = "hbir.pad"(%17)
%30 = "hbir.reshape"(%28)
%31 = "hbir.reshape"(%29)
%32 = "hbir.logical_or"(%30, %31)
%33 = "hbir.constant"()
%34 = "hbir.constant"()
%35 = "hbir.where"(%32, %34, %33)
%36 = "hbir.constant"()
%37 = "hbir.mul"(%19, %36)
%38 = "hbir.transpose"(%25)
%39 = "hbir.matmul"(%37, %38)
%40 = "hbir.tile"(%35)
%41 = "hbir.reshape"(%40)
%42 = "hbir.add"(%39, %41)
%43 = "hbir.softmax"(%42)
%44 = "hbir.matmul"(%43, %27)
%45 = "hbir.transpose"(%44)
%46 = "hbir.reshape"(%45)
%47 = "hbir.constant"()
%48 = "hbir.constant"()
%49 = "hbir.linear"(%46, %47, %48)
%50 = "hbir.reshape"(%43)
%51 = "hbir.reduce_mean"(%50)
%52 = "hbir.transpose"(%49)
return %52, %51
}
hbir.transposeinputs:
no limits
output:
same as inputs
hbir.linearinput:
Type: int8
Shape: [*,C_in]
Dim: *, C_in ∈ [1, 65536]
weight:
Type: int8
Shape: [C_out, C_in]
Dim: C_in,C_out ∈ [1, 8192]; C_in\*C_out ∈ [1, 65536]
bias:
Type: f32
output:
Type: int8, int16, int32
Other constraints: same as input
hbir.padinput:
Type: int64, uint64 and f64 are not supported when expansionMode is 'constant' else no constraints
Dim: all dims < 737280 when expansionMode is not 'constant' else no constraints
output:
Same as input
hbir.reshapeinputs:
no limits
output:
same as inputs
hbir.concatinputs:
Arg Number: inputs number ∈ [1, 1024]
Dim: all dims < 131072
size < 2G
output:
same as inputs
hbir.logical_orTBD
hbir.whereTBD
hbir.mullhs:
Type: int8, int16
Shape: [*]
rhs:
Same as lhs
output:
Same as lhs
hbir.matmullhs:
Type: int8, int16; lhs and rhs cannot both be int16
Shape: [*,M,C]
Dim: * ∈ [1, 4096], M,C ∈ [1, 8192]
rhs:
Type: int8, int16; lhs and rhs cannot both be int16
Shape: [*,C,N]
Dim: * ∈ [1, 4096]; C,N ∈ [1, 8192]
output:
Type: int8, int16, int32
Shape: [*,M,N]
Other constraints: same as lhs
hbir.tileinputs:
no limits
output:
same as inputs
hbir.addlhs:
Type: int8, int16, int32, if type is int32, this hbir.add op must be fusible to a Conv op
Shape: [*]
rhs:
Same as lhs
output:
Same as lhs
hbir.softmaxUnsupported
hbir.reduce_meaninput:
Type: int8, int16
Shape: [*]
Dim: reduce axis dim size ∈ [1, 16384]
output:
Same as input
torch.nn.functional.selu
torch.nn.SELU
torch.nn.SELUif qat:
func.func @forward(%arg0){
%0 = "qnt.quantize"(%arg0)
%1 = "hbir.constant"()
%2 = "b30.lut"(%0, %1)
%3 = "qnt.dequantize"(%2)
%4 = "qnt.const_fake_quant"(%3)
return %4
}
b30.lutinputs:
Type: int8, int16
outputs:
If input is int8, output is int8; if input is int16, output is int8/int16
torch.nn.functional.sigmoid
torch.nn.Sigmoid
torch.nn.Sigmoidif qat:
func.func @forward(%arg0){
%0 = "qnt.quantize"(%arg0)
%1 = "hbir.constant"()
%2 = "b30.lut"(%0, %1)
%3 = "qnt.dequantize"(%2)
%4 = "qnt.const_fake_quant"(%3)
return %4
}
b30.lutinputs:
Type: int8, int16
outputs:
If input is int8, output is int8; if input is int16, output is int8/int16
torch.nn.SoftplusNoneif qat:
func.func @forward(%arg0){
%0 = "qnt.quantize"(%arg0)
%1 = "hbir.constant"()
%2 = "b30.lut"(%0, %1)
%3 = "qnt.dequantize"(%2)
%4 = "qnt.const_fake_quant"(%3)
return %4
}
b30.lutinputs:
Type: int8, int16
outputs:
If input is int8, output is int8; if input is int16, output is int8/int16
torch.tanh
torch.nn.Tanh
torch.nn.Tanhif qat:
func.func @forward(%arg0){
%0 = "qnt.quantize"(%arg0)
%1 = "hbir.constant"()
%2 = "b30.lut"(%0, %1)
%3 = "qnt.dequantize"(%2)
%4 = "qnt.const_fake_quant"(%3)
return %4
}
b30.lutinputs:
Type: int8, int16
outputs:
If input is int8, output is int8; if input is int16, output is int8/int16
torch.quantization.DeQuantStub if float:
func.func @forward(%arg0){
return %arg0
}
TBDTBD
if qat:
func.func @forward(%arg0){
%0 = "qnt.barrier"(%arg0)
return %0
}
qnt.barrierTBD
torch.quantization.QuantStub iffloat:
func.func @forward(%arg0){
return %arg0
}
TBDTBD
if qat:
func.func @forward(%arg0){
%0 = "qnt.const_fake_quant"(%arg0)
return %0
}
qnt.const_fake_quantTBD
horizon.nn.AnchorGenerator func.func @forward(%arg0){
%0 = "hbir.constant"()
return %0
}
hbir.constantNone
horizon.nn.BaseGridGenerator func.func @forward(%arg0){
%0 = "hbir.constant"()
return %0
}
hbir.constantNone
horizon.nn.GridSampleNonefunc.func @forward(%arg0, %arg1){
%0 = "hbir.transpose"(%arg0)
%1 = "hbir.warp"(%0, %arg1)
%2 = "hbir.transpose"(%1)
return %2
}
hbir.warpinput:
Type: int8
Shape: [*,H,W,C]
Dim: H,W ∈ [1, 1024]; H\*W ≤ 720\*1024; other dims ∈ [1, 65536]
grid:
Type: int16
Shape: [*,H,W,2]
output:
Same as input except Dim constraints
hbir.transposeinputs:
no limits
output:
same as inputs
horizon.nn.SegmentLUT func.func @forward(%arg0){
%0 = "qnt.quantize"(%arg0)
%1 = "hbir.constant"()
%2 = "b30.lut"(%0, %1)
%3 = "qnt.dequantize"(%2)
%4 = "qnt.const_fake_quant"(%3)
return %4
b30.lutinputs:
Type: int8, int16
outputs:
If input is int8, output is int8; if input is int16, output is int8/int16
horizon.nn.functional.filter func.func @forward(%arg0){
%0 = "hbir.transpose"(%arg0)
%maxValue, %maxIndex, %filterCoord, %filterData = "hbir.filter"(%0)
return %maxValue, %maxIndex, %filterCoord, %filterData
}
hbir.transposeinputs:
no limits
output:
same as inputs
hbir.filterTBD
torch.Tensor.getitem if use as slice:
func.func @forward(%arg0){
%0 = "hbir.slice"(%arg0)
%1 = "hbir.select"(%0)
%2 = "hbir.reshape"(%1)
return %2
}
hbir.sliceinput:
Dim: all dims < 2097152
output:
Same as input
hbir.selectTBD
hbir.reshapeinputs:
no limits
output:
same as inputs
if use as index:
func.func @forward(%arg0){
%0 = "hbir.select"(%arg0)
%1 = "hbir.reshape"(%0)
return %1
}
hbir.selectTBD
hbir.reshapeinputs:
no limits
output:
same as inputs
torch.Tensor.setitemhorizon.nn.SetItemfunc.func @forward(%arg0, %arg1){
%0 = "hbir.constant"()
%1 = "hbir.reshape"(%arg1)
%2 = "hbir.scatter_nd"(%arg0, %0, %1)
return %2
}
hbir.scatter_ndTBD
hbir.reshapeinputs:
no limits
output:
same as inputs
torch.Tensor.clone
torch.Tensor.contiguous
torch.Tensor.detach
 func.func @forward(%arg0){
return %arg0
}
TBDTBD