Skip to content

Commit 82db0e1

Browse files
rsudermanclaudesjain-stanford
authored
[fusilli] Add abs pointwise op support (#294)
Adds ABS mode to pointwise operations, mapping to torch.aten.abs. Includes lit ASM emitter test and sample test coverage. --------- Signed-off-by: Rob Suderman <rob.suderman@gmail.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Sambhav Jain <sambhav.eee@gmail.com>
1 parent fd55351 commit 82db0e1

5 files changed

Lines changed: 72 additions & 2 deletions

File tree

include/fusilli/attributes/pointwise_attributes.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
namespace fusilli {
2626

2727
#define FUSILLI_POINTWISE_OPS(OP) \
28+
OP(ABS) \
2829
OP(ADD) \
2930
/* OP(ADD_SQUARE) */ \
3031
/* OP(BINARY_SELECT) */ \
@@ -127,6 +128,7 @@ inline const std::unordered_map<PointwiseAttr::Mode, std::string>
127128

128129
inline const std::unordered_map<PointwiseAttr::Mode, int>
129130
PointwiseAttr::kModeToRequiredInputCount = {
131+
{PointwiseAttr::Mode::ABS, 1},
130132
{PointwiseAttr::Mode::ADD, 2},
131133
{PointwiseAttr::Mode::CEIL, 1},
132134
{PointwiseAttr::Mode::CMP_EQ, 2},

include/fusilli/support/asm_emitter.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1731,6 +1731,7 @@ inline ErrorOr<std::string> PointwiseNode::emitNodePreAsm() const {
17311731
FUSILLI_DECLARE_BINARY_POINTWISE_EMITTER(PWOP, kSubAddSchema, OPIR)
17321732

17331733
switch (pointwiseAttr.getMode()) {
1734+
FUSILLI_DECLARE_UNARY_TORCH_EMITTER(ABS, torch.aten.abs)
17341735
FUSILLI_DECLARE_UNARY_TORCH_EMITTER(CEIL, torch.aten.ceil)
17351736
FUSILLI_DECLARE_BINARY_TORCH_EMITTER(CMP_EQ, torch.aten.eq.Tensor)
17361737
FUSILLI_DECLARE_BINARY_TORCH_EMITTER(CMP_LT, torch.aten.lt.Tensor)

samples/pointwise/pointwise_unary_ops.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,9 @@ TEST_CASE("Pointwise unary ops", "[pointwise][graph]") {
4040
const auto dim = std::vector<int64_t>{2, 16, 64, 64};
4141

4242
const auto mode =
43-
GENERATE(PointwiseAttr::Mode::CEIL, PointwiseAttr::Mode::RELU_FWD,
44-
PointwiseAttr::Mode::SIGMOID_FWD, PointwiseAttr::Mode::TANH_FWD);
43+
GENERATE(PointwiseAttr::Mode::ABS, PointwiseAttr::Mode::CEIL,
44+
PointwiseAttr::Mode::RELU_FWD, PointwiseAttr::Mode::SIGMOID_FWD,
45+
PointwiseAttr::Mode::TANH_FWD);
4546

4647
auto execute = [&]<typename T>(Handle &handle, DataType dt, T x) {
4748
auto buildNewGraph = [&](Handle &handleArg) {
@@ -96,6 +97,11 @@ TEST_CASE("Pointwise unary ops", "[pointwise][graph]") {
9697
// Calculate reference value
9798
T y = 0;
9899
switch (mode) {
100+
case PointwiseAttr::Mode::ABS: {
101+
double xD = static_cast<double>(x);
102+
y = std::abs(xD);
103+
break;
104+
}
99105
case PointwiseAttr::Mode::RELU_FWD: {
100106
y = std::max(x, T(0));
101107
break;

tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ add_fusilli_lit_tests(
141141
lit/test_conv_asm_emitter_ndhwc_kdrsc.cpp
142142
lit/test_conv_asm_emitter_ndhwc_kdrsc_grouped.cpp
143143
lit/test_conv_asm_emitter_nhwc_krsc_grouped.cpp
144+
lit/test_pointwise_asm_emitter_abs.cpp
144145
lit/test_pointwise_asm_emitter_relu.cpp
145146
lit/test_pointwise_asm_emitter_add.cpp
146147
lit/test_pointwise_asm_emitter_add_transposed.cpp
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// Copyright 2026 Advanced Micro Devices, Inc.
2+
//
3+
// Licensed under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
7+
// RUN: %{TEST_EXE} | iree-opt --verify-roundtrip
8+
// RUN: %{TEST_EXE} | FileCheck %s --check-prefix=TORCH-CHECK
9+
// RUN: %{TEST_EXE} stats | FileCheck %s --check-prefix=%{BACKEND}-STATS-CHECK
10+
11+
// clang-format off
12+
//
13+
// TORCH-CHECK: module @module {
14+
// TORCH-CHECK: func.func @main(%result_: !torch.tensor<[16,256,64,32],f32>, %arg0: !torch.vtensor<[16,256,64,32],f32>) attributes {torch.assume_strict_symbolic_shapes} {
15+
// TORCH-CHECK: %permute_IN_0_val_0_pointwise_abs = torch.constant.int 0
16+
// TORCH-CHECK: %permute_IN_0_val_1_pointwise_abs = torch.constant.int 1
17+
// TORCH-CHECK: %permute_IN_0_val_2_pointwise_abs = torch.constant.int 2
18+
// TORCH-CHECK: %permute_IN_0_val_3_pointwise_abs = torch.constant.int 3
19+
// TORCH-CHECK: %permute_IN_0_pointwise_abs = torch.prim.ListConstruct %permute_IN_0_val_0_pointwise_abs, %permute_IN_0_val_1_pointwise_abs, %permute_IN_0_val_2_pointwise_abs, %permute_IN_0_val_3_pointwise_abs : (!torch.int, !torch.int, !torch.int, !torch.int) -> !torch.list<int>
20+
// TORCH-CHECK: %arg0_pointwise_abs_perm = torch.aten.permute %arg0, %permute_IN_0_pointwise_abs : !torch.vtensor<[16,256,64,32],f32>, !torch.list<int> -> !torch.vtensor<[16,256,64,32],f32>
21+
// TORCH-CHECK: %result_pointwise_abs_perm = torch.aten.abs %arg0_pointwise_abs_perm : !torch.vtensor<[16,256,64,32],f32> -> !torch.vtensor<[16,256,64,32],f32>
22+
// TORCH-CHECK: %permute_OUT_0_val_0_pointwise_abs = torch.constant.int 0
23+
// TORCH-CHECK: %permute_OUT_0_val_1_pointwise_abs = torch.constant.int 1
24+
// TORCH-CHECK: %permute_OUT_0_val_2_pointwise_abs = torch.constant.int 2
25+
// TORCH-CHECK: %permute_OUT_0_val_3_pointwise_abs = torch.constant.int 3
26+
// TORCH-CHECK: %permute_OUT_0_pointwise_abs = torch.prim.ListConstruct %permute_OUT_0_val_0_pointwise_abs, %permute_OUT_0_val_1_pointwise_abs, %permute_OUT_0_val_2_pointwise_abs, %permute_OUT_0_val_3_pointwise_abs : (!torch.int, !torch.int, !torch.int, !torch.int) -> !torch.list<int>
27+
// TORCH-CHECK: %result = torch.aten.permute %result_pointwise_abs_perm, %permute_OUT_0_pointwise_abs : !torch.vtensor<[16,256,64,32],f32>, !torch.list<int> -> !torch.vtensor<[16,256,64,32],f32>
28+
// TORCH-CHECK: torch.overwrite.tensor.contents %result overwrites %result_ : !torch.vtensor<[16,256,64,32],f32>, !torch.tensor<[16,256,64,32],f32>
29+
// TORCH-CHECK: return
30+
// TORCH-CHECK: }
31+
// TORCH-CHECK: }
32+
//
33+
// AMDGPU-STATS-CHECK: "transient-memory-size": 0
34+
// AMDGPU-STATS-CHECK: "dispatch-count": 1
35+
// CPU-STATS-CHECK: "transient-memory-size": 0
36+
// CPU-STATS-CHECK: "dispatch-count": 1
37+
//
38+
// clang-format on
39+
40+
#include <fusilli.h>
41+
42+
#include "utils.h"
43+
44+
#include <iostream>
45+
#include <string>
46+
47+
using namespace fusilli;
48+
49+
int main(int argc, char **argv) {
50+
std::string mode = (argc > 1) ? argv[1] : "default";
51+
52+
auto status = testUnaryPointwiseAsmEmitter(
53+
"pointwise_asm_emitter_abs", "pointwise_abs", mode,
54+
PointwiseAttr::Mode::ABS, {16, 256, 64, 32});
55+
if (isError(status)) {
56+
std::cerr << "Test failed: " << status << std::endl;
57+
return 1;
58+
}
59+
return 0;
60+
}

0 commit comments

Comments
 (0)