in torch/csrc/jit/tensorexpr/lowerings.cpp [25:1608]
int nnc_lowerings_lazy_registration() {
RegisterNNCLoweringsFunction aten_dropout(
{"aten::dropout(Tensor input, float p, bool train) -> (Tensor)"},
computeNoop);
RegisterNNCLoweringsFunction aten_contiguous(
{"aten::contiguous(Tensor(a) self, *, MemoryFormat memory_format=contiguous_format) -> (Tensor(a))"},
computeNoop);
#ifdef USE_XNNPACK
// TODO: add a test
RegisterNNCLoweringsFunction prepacked_conv2d_clamp_run(
{"prepacked::conv2d_clamp_run(Tensor X, __torch__.torch.classes.xnnpack.Conv2dOpContext W_prepack) -> (Tensor Y)"},
computePrepackedConv2dClampRun);
// TODO: add a test
RegisterNNCLoweringsFunction prepacked_linear_clamp_run(
{"prepacked::linear_clamp_run(Tensor X, __torch__.torch.classes.xnnpack.LinearOpContext W_prepack) -> (Tensor Y)"},
computePrepackedLinearClampRun);
#endif
RegisterNNCLoweringsFunction aten_sub(
{"aten::sub.Scalar(Tensor self, Scalar other, Scalar alpha=1) -> (Tensor)",
"aten::sub.Tensor(Tensor self, Tensor other, *, Scalar alpha=1) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
auto sub_lambda = [](const ExprHandle& lhs, const ExprHandle& rhs) {
// NB: sub isn't supported on boolean, no need to promote to integer.
return lhs - rhs;
};
TORCH_INTERNAL_ASSERT(
inputs.size() == 2 || inputs.size() == 3,
buildErrorMessage("Invalid number of input operands"));
return (inputs.size() > 2)
? computeTwoOperandWithAlpha(
"aten_sub", inputs, outputShape, outputType, sub_lambda)
: computeTwoOperand(
"aten_sub", inputs, outputShape, outputType, sub_lambda);
});
RegisterNNCLoweringsFunction aten_mul(
{"aten::mul.Scalar(Tensor self, Scalar other) -> (Tensor)",
"aten::mul.Tensor(Tensor self, Tensor other) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeTwoOperand(
"aten_mul",
inputs,
outputShape,
outputType,
[](const ExprHandle& lhs, const ExprHandle& rhs) {
return boolToInteger(lhs) * boolToInteger(rhs);
});
});
RegisterNNCLoweringsFunction aten_div(
{"aten::div.Scalar(Tensor self, Scalar other) -> (Tensor)",
"aten::div.Tensor(Tensor self, Tensor other) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeTwoOperand(
"aten_div",
inputs,
outputShape,
outputType,
[](const ExprHandle& lhs, const ExprHandle& rhs) {
return promoteIntegerToDefaultType(lhs) /
promoteIntegerToDefaultType(rhs);
});
});
RegisterNNCLoweringsFunction aten___and__(
{"aten::__and__.Scalar(Tensor self, Scalar other) -> (Tensor)",
"aten::__and__.Tensor(Tensor self, Tensor other) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeTwoOperand(
"aten_and",
inputs,
outputShape,
outputType,
[](const ExprHandle& lhs, const ExprHandle& rhs) {
return boolToInteger(lhs) & boolToInteger(rhs);
});
});
RegisterNNCLoweringsFunction aten___or__(
{"aten::__or__.Scalar(Tensor self, Scalar other) -> (Tensor)",
"aten::__or__.Tensor(Tensor self, Tensor other) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeTwoOperand(
"aten_or",
inputs,
outputShape,
outputType,
[](const ExprHandle& lhs, const ExprHandle& rhs) {
return boolToInteger(lhs) | boolToInteger(rhs);
});
});
RegisterNNCLoweringsFunction aten___xor__(
{"aten::__xor__.Scalar(Tensor self, Scalar other) -> (Tensor)",
"aten::__xor__.Tensor(Tensor self, Tensor other) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeTwoOperand(
"aten_xor",
inputs,
outputShape,
outputType,
[](const ExprHandle& lhs, const ExprHandle& rhs) {
return boolToInteger(lhs) ^ boolToInteger(rhs);
});
});
RegisterNNCLoweringsFunction aten___lshift__(
{"aten::__lshift__.Scalar(Tensor self, Scalar other) -> (Tensor)",
"aten::__lshift__.Tensor(Tensor self, Tensor other) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeTwoOperand(
"aten_lshift",
inputs,
outputShape,
outputType,
[](const ExprHandle& lhs, const ExprHandle& rhs) {
return lhs << rhs;
});
});
RegisterNNCLoweringsFunction aten___rshift__(
{"aten::__rshift__.Scalar(Tensor self, Scalar other) -> (Tensor)",
"aten::__rshift__.Tensor(Tensor self, Tensor other) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeTwoOperand(
"aten_rshift",
inputs,
outputShape,
outputType,
[](const ExprHandle& lhs, const ExprHandle& rhs) {
return lhs >> rhs;
});
});
RegisterNNCLoweringsFunction aten_eq(
{"aten::eq.Scalar(Tensor self, Scalar other) -> (Tensor)",
"aten::eq.Tensor(Tensor self, Tensor other) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeTwoOperand(
"aten_eq",
inputs,
outputShape,
outputType,
[](const ExprHandle& lhs, const ExprHandle& rhs) {
return cast<bool>(lhs == rhs);
});
});
RegisterNNCLoweringsFunction aten_ne(
{"aten::ne.Scalar(Tensor self, Scalar other) -> (Tensor)",
"aten::ne.Tensor(Tensor self, Tensor other) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeTwoOperand(
"aten_ne",
inputs,
outputShape,
outputType,
[](const ExprHandle& lhs, const ExprHandle& rhs) {
return cast<bool>(lhs != rhs);
});
});
RegisterNNCLoweringsFunction aten_ge(
{"aten::ge.Scalar(Tensor self, Scalar other) -> (Tensor)",
"aten::ge.Tensor(Tensor self, Tensor other) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeTwoOperand(
"aten_ge",
inputs,
outputShape,
outputType,
[](const ExprHandle& lhs, const ExprHandle& rhs) {
return cast<bool>(lhs >= rhs);
});
});
RegisterNNCLoweringsFunction aten_gt(
{"aten::gt.Scalar(Tensor self, Scalar other) -> (Tensor)",
"aten::gt.Tensor(Tensor self, Tensor other) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeTwoOperand(
"aten_gt",
inputs,
outputShape,
outputType,
[](const ExprHandle& lhs, const ExprHandle& rhs) {
return cast<bool>(lhs > rhs);
});
});
RegisterNNCLoweringsFunction aten_le(
{"aten::le.Scalar(Tensor self, Scalar other) -> (Tensor)",
"aten::le.Tensor(Tensor self, Tensor other) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeTwoOperand(
"aten_le",
inputs,
outputShape,
outputType,
[](const ExprHandle& lhs, const ExprHandle& rhs) {
return cast<bool>(lhs <= rhs);
});
});
RegisterNNCLoweringsFunction aten_lt(
{"aten::lt.Scalar(Tensor self, Scalar other) -> (Tensor)",
"aten::lt.Tensor(Tensor self, Tensor other) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeTwoOperand(
"aten_lt",
inputs,
outputShape,
outputType,
[](const ExprHandle& lhs, const ExprHandle& rhs) {
return cast<bool>(lhs < rhs);
});
});
RegisterNNCLoweringsFunction aten_min_pointwise(
{"aten::min.other(Tensor self, Tensor other) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeTwoOperand(
"aten_min",
inputs,
outputShape,
outputType,
[](const ExprHandle& lhs, const ExprHandle& rhs) {
return Min::make(boolToInteger(lhs), boolToInteger(rhs), false);
});
});
RegisterNNCLoweringsFunction aten_max_pointwise(
{"aten::max.other(Tensor self, Tensor other) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeTwoOperand(
"aten_max",
inputs,
outputShape,
outputType,
[](const ExprHandle& lhs, const ExprHandle& rhs) {
return Max::make(boolToInteger(lhs), boolToInteger(rhs), false);
});
});
RegisterNNCLoweringsFunction aten_masked_fill(
{"aten::masked_fill.Scalar(Tensor self, Tensor mask, Scalar value) -> (Tensor)",
"aten::masked_fill.Tensor(Tensor self, Tensor mask, Tensor value) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeThreeOperand(
"aten_masked_fill",
inputs,
outputShape,
outputType,
[](const ExprHandle& input,
const ExprHandle& mask,
const ExprHandle& value) {
// value needs to promote to input, not vice versa
auto val = promoteToDtype(value, input.dtype().scalar_type());
return ifThenElse(mask, val, input);
},
/*promote_inputs*/ false);
});
RegisterNNCLoweringsFunction aten_clamp(
{"aten::clamp(Tensor self, Scalar? min=None, Scalar? max=None) -> (Tensor)",
"aten::clamp.Tensor(Tensor self, Tensor? min=None, Tensor? max=None) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
bool noMin = false;
bool noMax = false;
if (c10::get_if<ArgNone>(&inputs[1])) {
noMin = true;
}
if (c10::get_if<ArgNone>(&inputs[2])) {
noMax = true;
}
return computeThreeOperand(
"aten_clamp",
inputs,
outputShape,
outputType,
[noMin, noMax](
const ExprHandle& in,
const ExprHandle& min,
const ExprHandle& max) {
auto cast = [&](const ExprHandle& e) {
return Cast::make(in.dtype(), e);
};
if (noMin && noMax) {
return in;
} else if (noMin) {
auto cmax = cast(max);
return CompareSelect::make(in, cmax, cmax, in, kGT);
} else if (noMax) {
auto cmin = cast(min);
return CompareSelect::make(in, cmin, cmin, in, kLT);
} else {
auto cmax = cast(max);
auto cmin = cast(min);
return clamp(cmin, cmax, in);
}
},
false /* promote_inputs */);
});
RegisterNNCLoweringsFunction aten_addcmul(
{"aten::addcmul(Tensor self, Tensor tensor1, Tensor tensor2, *, Scalar value=1) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeFourOperand(
"aten_addcmul",
inputs,
outputShape,
outputType,
[](const ExprHandle& a0,
const ExprHandle& a1,
const ExprHandle& a2,
const ExprHandle& a3) { return a0 + a3 * a1 * a2; });
});
RegisterNNCLoweringsFunction aten_sigmoid(
{"aten::sigmoid(Tensor self) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
// check if the activation is quantized
const BufHandle& x = c10::get<BufHandle>(inputs[0]);
if (x.node()->qscale()) {
return computeQuantizedSigmoidExternalCall(
inputs, outputShape, outputType, device);
}
return computeOneOperand(
"aten_sigmoid",
inputs,
outputShape,
outputType,
[](const ExprHandle& a) {
return sigmoid(promoteIntegerToDefaultType(a));
});
});
RegisterNNCLoweringsFunction aten_reciprocal(
{"aten::reciprocal(Tensor self) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeOneOperand(
"aten_reciprocal",
inputs,
outputShape,
outputType,
[](const ExprHandle& a) { return ExprHandle(1.0f) / a; });
});
RegisterNNCLoweringsFunction aten_neg(
{"aten::neg(Tensor self) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeOneOperand(
"aten_neg",
inputs,
outputShape,
outputType,
[](const ExprHandle& a) { return ExprHandle(-0) - a; });
});
RegisterNNCLoweringsFunction aten_isnan(
{"aten::isnan(Tensor self) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeOneOperand(
"aten_isnan",
inputs,
outputShape,
outputType,
[](const ExprHandle& a) {
if (!a.dtype().is_floating_point()) {
return IntImm::make(0);
}
return isnan(a);
});
});
RegisterNNCLoweringsFunction aten_relu(
{"aten::relu(Tensor self) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
auto A = c10::get<BufHandle>(inputs[0]);
if (A.node()->qscale()) {
return computeQuantizedRelu(inputs, outputShape, outputType, device);
}
return computeOneOperand(
"aten_relu",
inputs,
outputShape,
outputType,
[](const ExprHandle& a) {
auto zero = Cast::make(a.dtype(), 0);
return CompareSelect::make(a, zero, zero, a, kLT);
});
});
RegisterNNCLoweringsFunction aten_leaky_relu(
{"aten::leaky_relu(Tensor self, Scalar negative_slope=0.01) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeTwoOperand(
"aten_leaky_relu",
inputs,
outputShape,
outputType,
[](const ExprHandle& a, const ExprHandle& negative_slope) {
auto neg_slope = Cast::make(a.dtype(), negative_slope);
auto zero = Cast::make(a.dtype(), 0);
auto one = Cast::make(a.dtype(), 1);
auto cs = CompareSelect::make(a, zero, one, neg_slope, kGT);
return a * cs;
});
});
RegisterNNCLoweringsFunction aten_relu6(
{"aten::relu6(Tensor self) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeOneOperand(
"aten_relu6",
inputs,
outputShape,
outputType,
[](const ExprHandle& a) {
auto zero = Cast::make(a.dtype(), 0);
auto six = Cast::make(a.dtype(), 6.);
return clamp(zero, six, a);
});
});
RegisterNNCLoweringsFunction aten_gelu(
{"aten::gelu(Tensor self) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeOneOperand(
"aten_gelu",
inputs,
outputShape,
outputType,
[](const ExprHandle& a) {
auto m_sqrt1_2 = Cast::make(a.dtype(), M_SQRT1_2);
auto one = Cast::make(a.dtype(), 1.);
auto point_five = Cast::make(a.dtype(), .5);
return a * point_five * (one + erf(a * m_sqrt1_2));
});
});
RegisterNNCLoweringsFunction aten_batch_norm(
{"aten::batch_norm(Tensor input, Tensor? weight, Tensor? bias, Tensor? running_mean, Tensor? running_var, bool training, float momentum, float eps, bool cudnn_enabled) -> (Tensor)"},
computeBatchNorm);
RegisterNNCLoweringsFunction aten_log(
{"aten::log(Tensor self) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeOneOperand(
"aten_log",
inputs,
outputShape,
outputType,
[](const ExprHandle& a) {
return log(promoteIntegerToDefaultType(a));
});
});
RegisterNNCLoweringsFunction aten_log10(
{"aten::log10(Tensor self) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeOneOperand(
"aten_log10",
inputs,
outputShape,
outputType,
[](const ExprHandle& a) {
return log10(promoteIntegerToDefaultType(a));
});
});
RegisterNNCLoweringsFunction aten_log1p(
{"aten::log1p(Tensor self) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeOneOperand(
"aten_log1p",
inputs,
outputShape,
outputType,
[](const ExprHandle& a) {
return log1p(promoteIntegerToDefaultType(a));
});
});
RegisterNNCLoweringsFunction aten_log2(
{"aten::log2(Tensor self) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeOneOperand(
"aten_log2",
inputs,
outputShape,
outputType,
[](const ExprHandle& a) {
return log2(promoteIntegerToDefaultType(a));
});
});
RegisterNNCLoweringsFunction aten_exp(
{"aten::exp(Tensor self) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeOneOperand(
"aten_exp",
inputs,
outputShape,
outputType,
[](const ExprHandle& a) {
return exp(promoteIntegerToDefaultType(a));
});
});
RegisterNNCLoweringsFunction aten_expm1(
{"aten::expm1(Tensor self) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeOneOperand(
"aten_expm1",
inputs,
outputShape,
outputType,
[](const ExprHandle& a) {
return expm1(promoteIntegerToDefaultType(a));
});
});
RegisterNNCLoweringsFunction aten_erf(
{"aten::erf(Tensor self) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeOneOperand(
"aten_erf",
inputs,
outputShape,
outputType,
[](const ExprHandle& a) {
return erf(promoteIntegerToDefaultType(a));
});
});
RegisterNNCLoweringsFunction aten_erfc(
{"aten::erfc(Tensor self) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeOneOperand(
"aten_erfc",
inputs,
outputShape,
outputType,
[](const ExprHandle& a) {
return erfc(promoteIntegerToDefaultType(a));
});
});
RegisterNNCLoweringsFunction aten_cos(
{"aten::cos(Tensor self) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeOneOperand(
"aten_cos",
inputs,
outputShape,
outputType,
[](const ExprHandle& a) {
return cos(promoteIntegerToDefaultType(a));
});
});
RegisterNNCLoweringsFunction aten_sin(
{"aten::sin(Tensor self) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeOneOperand(
"aten_sin",
inputs,
outputShape,
outputType,
[](const ExprHandle& a) {
return sin(promoteIntegerToDefaultType(a));
});
});
RegisterNNCLoweringsFunction aten_tan(
{"aten::tan(Tensor self) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeOneOperand(
"aten_tan",
inputs,
outputShape,
outputType,
[](const ExprHandle& a) {
return tan(promoteIntegerToDefaultType(a));
});
});
RegisterNNCLoweringsFunction aten_type_as(
{"aten::type_as(Tensor self, Tensor other) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
const BufHandle& rhs = c10::get<BufHandle>(inputs[1]);
auto dtype = rhs.dtype();
return computeOneOperand(
"aten_type_as",
inputs,
outputShape,
outputType,
[dtype](const ExprHandle& lhs) { return Cast::make(dtype, lhs); });
});
RegisterNNCLoweringsFunction aten_pow(
{"aten::pow.Tensor_Scalar(Tensor self, Scalar exponent) -> (Tensor)",
"aten::pow.Tensor_Tensor(Tensor self, Tensor exponent) -> (Tensor)",
"aten::pow.Scalar(Scalar self, Tensor exponent) -> Tensor"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeTwoOperand(
"aten_pow",
inputs,
outputShape,
outputType,
[](const ExprHandle& lhs, const ExprHandle& rhs) {
if (!rhs.node()->isConstant()) {
return pow(lhs, rhs);
}
double val =
immediateAs<double>(IRSimplifier::simplify(rhs.node()));
if (val == 1.0f) {
return lhs;
} else if (val == 2.0f) { // NOLINT
return lhs * lhs;
} else if (val == 3.0f) { // NOLINT
return (lhs * lhs) * lhs;
} else if (val == 4.0f) { // NOLINT
ExprHandle tmp = lhs * lhs;
return tmp * tmp;
} else if (val == 0.5f) { // NOLINT
return sqrt(lhs);
} else if (val == 0.0f) {
return ExprHandle(1.0f);
} else if (val == -0.5f) { // NOLINT
return rsqrt(lhs);
} else if (val == -1.0f) {
return ExprHandle(1.0f) / lhs;
} else if (val == -2.0f) { // NOLINT
return ExprHandle(1.0f) / (lhs * lhs);
}
return pow(lhs, rhs);
});
});
RegisterNNCLoweringsFunction aten_fmod(
{"aten::fmod.Scalar(Tensor self, Scalar other) -> (Tensor)",
"aten::fmod.Tensor(Tensor self, Tensor other) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeTwoOperand(
"aten_fmod",
inputs,
outputShape,
outputType,
[](const ExprHandle& lhs, const ExprHandle& rhs) {
return fmod(promoteHalfToFloat(lhs), promoteHalfToFloat(rhs));
});
});
RegisterNNCLoweringsFunction aten_lerp(
{"aten::lerp.Scalar(Tensor self, Tensor end, Scalar weight) -> (Tensor)",
"aten::lerp.Tensor(Tensor self, Tensor end, Tensor weight) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeThreeOperand(
"aten_lerp",
inputs,
outputShape,
outputType,
[](const ExprHandle& a,
const ExprHandle& end,
const ExprHandle& weight) { return a + weight * (end - a); });
});
RegisterNNCLoweringsFunction aten_remainder(
{"aten::remainder.Scalar(Tensor self, Scalar other) -> (Tensor)",
"aten::remainder.Scalar_Tensor(Scalar self, Tensor other) -> (Tensor)",
"aten::remainder.Tensor(Tensor self, Tensor other) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
auto imodImpl = [](const ExprHandle& lhs, const ExprHandle& rhs) {
return Mod::make(lhs, rhs);
};
auto fmodImpl = [](const ExprHandle& lhs, const ExprHandle& rhs) {
auto lhs_t = promoteHalfToFloat(lhs);
auto rhs_t = promoteHalfToFloat(rhs);
return fmod((rhs_t + fmod(lhs_t, rhs_t)), rhs_t);
};
{
auto const& shape =
broadcastShapes(valueShape(inputs[0]), valueShape(inputs[1]));
return Compute(
"aten_remainder",
c10::fmap<DimArg>(shape),
[&](const std::vector<VarHandle>& axes) {
std::vector<ExprHandle> indices(axes.begin(), axes.end());
std::vector<ExprHandle> exprInputs = {
tensorOrConstant(inputs[0], indices),
tensorOrConstant(inputs[1], indices),
};
promoteInputs(exprInputs);
bool allInt = true;
for (auto& e : exprInputs) {
if (e.dtype().is_floating_point()) {
allInt = false;
break;
}
}
if (allInt) {
return demoteOutput(
imodImpl(exprInputs[0], exprInputs[1]), outputType);
} else {
return demoteOutput(
fmodImpl(exprInputs[0], exprInputs[1]), outputType);
}
});
}
});
RegisterNNCLoweringsFunction prim_ConstantChunk(
{"prim::ConstantChunk(...) -> (...)"}, computeChunk);
RegisterNNCLoweringsFunction aten_acos(
{"aten::acos(Tensor self) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeOneOperand(
"aten_acos",
inputs,
outputShape,
outputType,
[](const ExprHandle& a) {
return acos(promoteIntegerToDefaultType(a));
});
});
RegisterNNCLoweringsFunction aten_asin(
{"aten::asin(Tensor self) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeOneOperand(
"aten_asin",
inputs,
outputShape,
outputType,
[](const ExprHandle& a) {
return asin(promoteIntegerToDefaultType(a));
});
});
RegisterNNCLoweringsFunction aten_cosh(
{"aten::cosh(Tensor self) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeOneOperand(
"aten_cosh",
inputs,
outputShape,
outputType,
[](const ExprHandle& a) {
return cosh(promoteIntegerToDefaultType(a));
});
});
RegisterNNCLoweringsFunction aten_sinh(
{"aten::sinh(Tensor self) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeOneOperand(
"aten_sinh",
inputs,
outputShape,
outputType,
[](const ExprHandle& a) {
return sinh(promoteIntegerToDefaultType(a));
});
});
RegisterNNCLoweringsFunction aten_atan(
{"aten::atan(Tensor self) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeOneOperand(
"aten_atan",
inputs,
outputShape,
outputType,
[](const ExprHandle& a) {
return atan(promoteIntegerToDefaultType(a));
});
});
RegisterNNCLoweringsFunction aten_atan2(
{"aten::atan2(Tensor self, Tensor other) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeTwoOperand(
"aten_atan2",
inputs,
outputShape,
outputType,
[](const ExprHandle& lhs, const ExprHandle& rhs) {
return atan2(
promoteIntegerToDefaultType(lhs),
promoteIntegerToDefaultType(rhs));
});
});
RegisterNNCLoweringsFunction aten_tanh(
{"aten::tanh(Tensor self) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeOneOperand(
"aten_tanh",
inputs,
outputShape,
outputType,
[](const ExprHandle& a) {
return tanh(promoteIntegerToDefaultType(a));
});
});
RegisterNNCLoweringsFunction aten_hardtanh(
{"aten::hardtanh(Tensor self, Scalar min_val=-1, Scalar max_val=1) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeThreeOperand(
"aten_hardtanh",
inputs,
outputShape,
outputType,
[](const ExprHandle& a,
const ExprHandle& min_val,
const ExprHandle& max_val) {
auto mm = CompareSelect::make(a, min_val, min_val, a, kLT);
return CompareSelect::make(mm, max_val, max_val, mm, kGT);
});
});
RegisterNNCLoweringsFunction aten_softplus(
{"aten::softplus(Tensor self, Scalar beta=1, Scalar threshold=20) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeThreeOperand(
"aten_softplus",
inputs,
outputShape,
outputType,
[](const ExprHandle& a,
const ExprHandle& beta,
const ExprHandle& threshold) {
auto beta_promoted = Cast::make(a.dtype(), beta);
auto threshold_promoted = Cast::make(a.dtype(), threshold);
auto beta_a = beta_promoted * a;
return CompareSelect::make(
beta_a,
threshold_promoted,
a,
log1p(exp(beta_a)) / beta_promoted,
kGT);
});
});
RegisterNNCLoweringsFunction aten_hardsigmoid(
{"aten::hardsigmoid(Tensor self) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeOneOperand(
"aten_hardsigmoid",
inputs,
outputShape,
outputType,
[](const ExprHandle& a) {
auto zero = Cast::make(a.dtype(), 0.0);
auto three = Cast::make(a.dtype(), 3.0);
auto six = Cast::make(a.dtype(), 6.0);
return clamp(zero, six, a + three) / six;
});
});
RegisterNNCLoweringsFunction aten_hardswish(
{"aten::hardswish(Tensor self) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeOneOperand(
"aten_hardswish",
inputs,
outputShape,
outputType,
[](const ExprHandle& a) {
// x * torch.clamp(x + 3.0, 0.0, 6.0) / 6.0
auto zero = Cast::make(a.dtype(), 0.);
auto three = Cast::make(a.dtype(), 3.);
auto six = Cast::make(a.dtype(), 6.);
return a * clamp(zero, six, a + three) / six;
});
});
RegisterNNCLoweringsFunction aten_hardshrink(
{"aten::hardshrink(Tensor self, Scalar lambd=0.5) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeTwoOperand(
"aten_hardshrink",
inputs,
outputShape,
outputType,
[](const ExprHandle& a, const ExprHandle& lambd) {
auto pos_clambd = Cast::make(a.dtype(), lambd);
auto neg_clambd =
Cast::make(a.dtype(), ExprHandle(-0)) - pos_clambd;
auto zero = Cast::make(a.dtype(), 0);
auto mm = CompareSelect::make(a, neg_clambd, a, zero, kLT);
return CompareSelect::make(a, pos_clambd, a, mm, kGT);
});
});
RegisterNNCLoweringsFunction aten_sqrt(
{"aten::sqrt(Tensor self) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeOneOperand(
"aten_sqrt",
inputs,
outputShape,
outputType,
[](const ExprHandle& a) {
return tensorexpr::sqrt(promoteIntegerToDefaultType(a));
});
});
RegisterNNCLoweringsFunction aten_rsqrt(
{"aten::rsqrt(Tensor self) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeOneOperand(
"aten_rsqrt",
inputs,
outputShape,
outputType,
[](const ExprHandle& a) {
return rsqrt(promoteIntegerToDefaultType(a));
});
});
RegisterNNCLoweringsFunction aten_abs(
{"aten::abs(Tensor self) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeOneOperand(
"aten_abs",
inputs,
outputShape,
outputType,
[](const ExprHandle& a) {
return tensorexpr::abs(promoteHalfToFloat(a));
},
kIntegralTypes | kFloatingPointTypes | kBoolType);
});
RegisterNNCLoweringsFunction aten_sign(
{"aten::sign(Tensor self) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) { return computeSign(inputs, outputShape); });
RegisterNNCLoweringsFunction aten_ceil(
{"aten::ceil(Tensor self) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeOneOperand(
"aten_ceil",
inputs,
outputShape,
outputType,
[](const ExprHandle& a) { return ceil(a); });
});
RegisterNNCLoweringsFunction aten_floor(
{"aten::floor(Tensor self) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeOneOperand(
"aten_floor",
inputs,
outputShape,
outputType,
[](const ExprHandle& a) { return floor(a); });
});
RegisterNNCLoweringsFunction aten_round(
{"aten::round(Tensor self) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeOneOperand(
"aten_round",
inputs,
outputShape,
outputType,
[](const ExprHandle& a) { return round(a); });
});
RegisterNNCLoweringsFunction aten_trunc(
{"aten::trunc(Tensor self) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeOneOperand(
"aten_trunc",
inputs,
outputShape,
outputType,
[](const ExprHandle& a) { return trunc(a); });
});
RegisterNNCLoweringsFunction aten__cast_Float(
{"aten::_cast_Float(Tensor self, bool non_blocking=False) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeOneOperand(
"aten_cast_float",
inputs,
outputShape,
outputType,
[](const ExprHandle& a) { return cast<float>(a); });
});
RegisterNNCLoweringsFunction aten_to(
{"aten::to.dtype(Tensor(a) self, int dtype, bool non_blocking=False, bool copy=False, int? memory_format=None) -> (Tensor(a))",
"aten::to.dtype_layout(Tensor(a) self, *, int? dtype=None, int? layout=None, Device? device=None, bool? pin_memory=None, bool non_blocking=False, bool copy=False, int? memory_format=None) -> (Tensor(a))",
"aten::to.device(Tensor(a) self, Device device, int dtype, bool non_blocking=False, bool copy=False, int? memory_format=None) -> (Tensor(a))",
"aten::to.prim_Device(Tensor(a) self, Device? device, int? dtype=None, bool non_blocking=False, bool copy=False) -> Tensor(a|b)",
"aten::to.prim_dtype(Tensor(a) self, int? dtype=None, bool non_blocking=False, bool copy=False) -> Tensor(a|b)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
// see handling of aten::to in tensorexpr_fuser.cpp for why we only
// need to handle the first input
return computeOneOperand(
"aten_to",
{inputs[0]},
outputShape,
outputType,
[outputType](const ExprHandle& a) {
TORCH_INTERNAL_ASSERT(
outputType, buildErrorMessage("Output type is null."));
return Cast::make(ToDtype(*outputType), a);
});
});
RegisterNNCLoweringsFunction aten_threshold(
{"aten::threshold(Tensor self, Scalar threshold, Scalar value) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeThreeOperand(
"aten_threshold",
inputs,
outputShape,
outputType,
[](const ExprHandle& a,
const ExprHandle& threshold,
const ExprHandle& value) {
return ifThenElse(
CompareSelect::make(a, threshold, kLE), value, a);
});
});
RegisterNNCLoweringsFunction aten_where(
{"aten::where.ScalarOther(Tensor condition, Tensor self, Scalar other) -> (Tensor)",
"aten::where.ScalarSelf(Tensor condition, Scalar self, Tensor other) -> (Tensor)",
"aten::where.self(Tensor condition, Tensor self, Tensor other) -> (Tensor)",
"aten::where.Scalar(Tensor condition, Scalar self, Scalar other) -> Tensor"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeConditionWithTwoOperand(
"aten_where",
inputs,
outputShape,
outputType,
[](const ExprHandle& a0,
const ExprHandle& a1,
const ExprHandle& a2) { return ifThenElse(a0, a1, a2); });
});
RegisterNNCLoweringsFunction aten_frac(
{"aten::frac(Tensor self) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeOneOperand(
"aten_frac",
inputs,
outputShape,
outputType,
[](const ExprHandle& a) {
auto aa = promoteHalfToFloat(a);
return aa - floor(aa);
},
kFloatingPointTypes);
});
RegisterNNCLoweringsFunction aten_lgamma(
{"aten::lgamma(Tensor self) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeOneOperand(
"aten_lgamma",
inputs,
outputShape,
outputType,
[](const ExprHandle& a) {
return lgamma(promoteIntegerToDefaultType(a));
});
});
// TODO: convert to schema, add a test
// RegisterNNCLoweringsFunction aten_rand_like(
// {"aten::rand_like"},
// [](const std::vector<ArgValue>& inputs,
// const std::vector<ExprHandle>& outputShape,
// const c10::optional<ScalarType>& outputType,
// at::Device device) {
// return computeOneOperand(
// "aten_rand_like",
// inputs,
// outputShape,
// outputType,
// [](const ExprHandle& a) {
// return Intrinsics::make(IntrinsicsOp::kRand, a.dtype());
// });
// });
// TODO: convert to schema, add a test
// RegisterNNCLoweringsFunction aten_slice(
// {"aten::slice"},
// [](const std::vector<ArgValue>& inputs,
// const std::vector<ExprHandle>& outputShape,
// const c10::optional<ScalarType>& outputType,
// at::Device device) {
// return Compute(
// "aten_slice",
// c10::fmap<DimArg>(outputShape),
// [&](const std::vector<VarHandle>& axes) {
// int64_t dim =
// at::maybe_wrap_dim(c10::get<int64_t>(inputs[1]),
// axes.size());
// ExprHandle start = constant(inputs[2]);
// ExprHandle stride = constant(inputs[4]);
// std::vector<ExprHandle> newAxes(axes.begin(), axes.end());
// newAxes[dim] = stride * newAxes[dim] + start;
// return tensorOrConstant(inputs[0], newAxes);
// });
// });
RegisterNNCLoweringsFunction aten_unsqueeze(
{"aten::unsqueeze(Tensor(a) self, int dim) -> (Tensor(a))"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return Compute(
"aten_unsqueeze",
c10::fmap<DimArg>(outputShape),
[&](const std::vector<VarHandle>& axes) {
int64_t dim = c10::get<int64_t>(inputs[1]);
if (dim < 0) {
if (axes.size() == 0) {
throw malformed_input("axes are zero handling unsqueeze");
}
dim += axes.size();
}
// To construct an expression for an 'unsqueezed' tensor we need
// to drop the DIM-th axis, i.e.
// unsqueezed_v[i,j,k,l] = v[i,j,l] # dim = 2 - drop index 'k'
// 0 1 2 3
std::vector<ExprHandle> indices;
int64_t i = 0;
for (const auto& a : axes) {
if (i++ != dim) {
indices.emplace_back(ExprHandle(a.node()));
}
}
return broadcast(c10::get<BufHandle>(inputs[0]), indices);
});
});
RegisterNNCLoweringsFunction aten_t(
{"aten::t(Tensor(a) self) -> (Tensor(a))"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeTranspose(
{inputs[0], (int64_t)1, (int64_t)0},
outputShape,
outputType,
device);
});
RegisterNNCLoweringsFunction aten_transpose(
{"aten::transpose.int(Tensor(a) self, int dim0, int dim1) -> (Tensor(a))"},
computeTranspose);
RegisterNNCLoweringsFunction aten_permute(
{"aten::permute(Tensor(a) self, int[] dims) -> (Tensor(a))"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
auto A = c10::get<BufHandle>(inputs[0]);
// Trivial case of 0-dim tensors: just a copy of the input
if (A.ndim() == 0) {
auto tensor = Compute(
"aten_permute",
c10::fmap<DimArg>(outputShape),
[&](const std::vector<VarHandle>& axes) {
std::vector<ExprHandle> empty_indices;
return A.load(empty_indices);
});
if (A.node()->qscale()) {
tensor.buf()->set_qscale(A.node()->qscale());
tensor.buf()->set_qzero(A.node()->qzero());
}
return tensor;
}
auto permute_dims = c10::get<IntList>(inputs[1]);
auto tensor = Compute(
"aten_permute",
c10::fmap<DimArg>(outputShape),
[&](const std::vector<VarHandle>& axes) {
std::vector<VarHandle> new_axes;
new_axes.resize(axes.size());
assert(permute_dims.size() == axes.size());
for (unsigned i = 0; i < axes.size(); i++) {
auto new_dim = at::maybe_wrap_dim(permute_dims[i], A.ndim());
new_axes[new_dim] = axes[i];
}
return A.load(new_axes);
});
if (A.node()->qscale()) {
tensor.buf()->set_qscale(A.node()->qscale());
tensor.buf()->set_qzero(A.node()->qzero());
}
return tensor;
});
RegisterNNCLoweringsFunction aten_expand(
{"aten::expand(Tensor(a) self, int[] size, *, bool implicit=False) -> (Tensor(a))",
"aten::expand_as(Tensor(a) self, Tensor other) -> (Tensor(a))"},
computeExpand);
// TODO: add a test
RegisterNNCLoweringsFunction aten_flatten(
{"aten::flatten.using_ints(Tensor(a) self, int start_dim=0, int end_dim=-1) -> (Tensor(a))"},
computeFlatten);
RegisterNNCLoweringsFunction aten_view(
{"aten::reshape(Tensor(a) self, int[] shape) -> (Tensor(a))",
"aten::reshape_as(Tensor(a) self, Tensor other) -> (Tensor(a))",
"aten::view(Tensor(a) self, int[] size) -> (Tensor(a))",
"aten::view_as(Tensor(a) self, Tensor other) -> (Tensor(a))"},
computeReshape);
// aten::mm is a subset of aten::matmul where both inputs are rank 2
RegisterNNCLoweringsFunction aten_matmul(
{"aten::mm(Tensor self, Tensor mat2) -> (Tensor)",
"aten::matmul(Tensor self, Tensor other) -> (Tensor)"},
computeMatmul);
RegisterNNCLoweringsFunction aten_cat(
{"aten::cat(Tensor[] tensors, int dim=0) -> (Tensor)"}, computeCat);
RegisterNNCLoweringsFunction aten_sum(
{"aten::sum(Tensor self, *, int? dtype=None) -> (Tensor)",
"aten::sum.dim_IntList(Tensor self, int[1] dim, bool keepdim=False, *, int? dtype=None) -> (Tensor)"},
computeSum);
RegisterNNCLoweringsFunction aten_softmax(
{"aten::softmax.int(Tensor self, int dim, int? dtype=None) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeSoftmax(inputs, outputShape, false);
});
RegisterNNCLoweringsFunction aten_log_softmax(
{"aten::log_softmax.int(Tensor self, int dim, int? dtype=None) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
return computeSoftmax(inputs, outputShape, true);
});
RegisterNNCLoweringsFunction aten_conv1d(
{"aten::conv1d(Tensor input, Tensor weight, Tensor? bias=None, int[1] stride=1, int[1] padding=0, int[1] dilation=1, int groups=1) -> (Tensor)"},
computeConv1d);
RegisterNNCLoweringsFunction aten_conv2d(
{"aten::conv2d(Tensor input, Tensor weight, Tensor? bias=None, int[2] stride=[1, 1], int[2] padding=[0, 0], int[2] dilation=[1, 1], int groups=1) -> (Tensor)"},
computeConv2d);
RegisterNNCLoweringsFunction aten_addmm(
{"aten::addmm(Tensor self, Tensor mat1, Tensor mat2, *, Scalar beta=1, Scalar alpha=1) -> (Tensor)"},
computeAddMM);
RegisterNNCLoweringsFunction aten_mean(
{"aten::mean(Tensor self, *, int? dtype=None) -> (Tensor)",
"aten::mean.dim(Tensor self, int[1] dim, bool keepdim=False, *, int? dtype=None) -> (Tensor)"},
computeMean);
RegisterNNCLoweringsFunction aten_max_reduction(
{"aten::max.dim(Tensor self, int dim, bool keepdim=False) -> (Tensor values, Tensor indices)"},
computeMax);
RegisterNNCLoweringsFunction aten_adaptive_avg_pool2d(
{"aten::adaptive_avg_pool2d(Tensor self, int[2] output_size) -> (Tensor)"},
computeAdaptiveAvgPool2d);
RegisterNNCLoweringsFunction aten_add(
{"aten::add.Scalar(Tensor self, Scalar other, Scalar alpha=1) -> (Tensor)",
"aten::add.Tensor(Tensor self, Tensor other, *, Scalar alpha=1) -> (Tensor)"},
[](const std::vector<ArgValue>& inputs,
const std::vector<ExprHandle>& outputShape,
const c10::optional<ScalarType>& outputType,
at::Device device) {
auto add_lambda = [](const ExprHandle& lhs, const ExprHandle& rhs) {
return boolToInteger(lhs) + boolToInteger(rhs);
};
TORCH_INTERNAL_ASSERT(
inputs.size() == 2 || inputs.size() == 3,
buildErrorMessage("Invalid number of input operands"));
return (inputs.size() > 2)
? computeTwoOperandWithAlpha(
"aten_add", inputs, outputShape, outputType, add_lambda)
: computeTwoOperand(
"aten_add", inputs, outputShape, outputType, add_lambda);
});
RegisterNNCLoweringsFunction aten_embedding(
{"aten::embedding(Tensor weight, Tensor indices, int padding_idx=-1, bool scale_grad_by_freq=False, bool sparse=False) -> Tensor"},
computeEmbedding);
#define NNC_QUANTIZATION_EXPR_QUANT 0
#define NNC_QUANTIZATION_EXPR_DEQUANT 0
RegisterNNCLoweringsFunction aten_quantize_per_tensor(
{"aten::quantize_per_tensor(Tensor self, float scale, int zero_point, int dtype) -> (Tensor)",
"aten::quantize_per_tensor.tensor_qparams(Tensor self, Tensor scale, Tensor zero_point, int dtype) -> (Tensor)",
"aten::quantize_per_tensor.tensors(Tensor[] tensors, Tensor scales, Tensor zero_points, int dtype) -> (Tensor[])"},
#if NNC_QUANTIZATION_EXPR_QUANT == 1
computeQuantizePerTensor
#else
computeQuantizePerTensorExternalCall
#endif
);
RegisterNNCLoweringsFunction aten_dequantize(
{"aten::dequantize.self(Tensor self) -> (Tensor)"},
#if NNC_QUANTIZATION_EXPR_DEQUANT == 1
computeDequantize
#else
computeDequantizeExternalCall
#endif
);
RegisterNNCLoweringsFunction quantized_conv1d(
{"quantized::conv1d(Tensor qx, __torch__.torch.classes.quantized.Conv2dPackedParamsBase packed_weight, float output_scale, int output_zero_point) -> (Tensor)"},
computeQuantizedConv1d);
RegisterNNCLoweringsFunction quantized_conv2d(
{"quantized::conv2d.new(Tensor qx, __torch__.torch.classes.quantized.Conv2dPackedParamsBase packed_weight, float output_scale, int output_zero_point) -> (Tensor)"},
computeQuantizedConv2d);
RegisterNNCLoweringsFunction quantized_conv2d_relu(
{"quantized::conv2d_relu.new(Tensor qx, __torch__.torch.classes.quantized.Conv2dPackedParamsBase packed_weight, float output_scale, int output_zero_point) -> (Tensor)"},
computeQuantizedConv2dRelu);
RegisterNNCLoweringsFunction quantized_linear(
{"quantized::linear(Tensor X, __torch__.torch.classes.quantized.LinearPackedParamsBase W_prepack, float Y_scale_i, int Y_zero_point_i) -> (Tensor Y)"},
computeQuantizedLinear);
RegisterNNCLoweringsFunction quantized_linear_relu(
{"quantized::linear_relu(Tensor X, __torch__.torch.classes.quantized.LinearPackedParamsBase W_prepack, float Y_scale_i, int Y_zero_point_i) -> (Tensor Y)"},
computeQuantizedLinear);
RegisterNNCLoweringsFunction quantized_add(
{"quantized::add(Tensor qa, Tensor qb, float scale, int zero_point) -> (Tensor qc)"},
computeQuantizedAdd);
RegisterNNCLoweringsFunction quantized_mul(
{"quantized::mul(Tensor qa, Tensor qb, float scale, int zero_point) -> (Tensor qc)"},
computeQuantizedMul);
RegisterNNCLoweringsFunction quantized_mul_scalar(
{"quantized::mul.Scalar(Tensor qa, Scalar b) -> (Tensor qc)"},
computeQuantizedMulScalar);
RegisterNNCLoweringsFunction quantized_conv2d_prepack(
{"quantized::conv2d_prepack(Tensor weight, Tensor? bias, int[] stride, int[] padding, int[] dilation, int groups) -> (__torch__.torch.classes.quantized.Conv2dPackedParamsBase)"},
computeQuantizedConv2dPrepack);
RegisterNNCLoweringsFunction quantized_cat(
{"quantized::cat(Tensor[] qx, int dim, float? scale, int? zero_point) -> (Tensor)"},
computeQuantizedCat);
RegisterNNCLoweringsFunction aten_upsample_nearest2d(
{"aten::upsample_nearest2d.vec(Tensor input, int[]? output_size, float[]? scale_factors) -> (Tensor)"},
computeUpsampleNearest2d);
return 0;
}