2023-12-22 00:40:10 +08:00
|
|
|
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
# See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
# Also available under a BSD-style license. See LICENSE.
|
|
|
|
|
|
|
|
# RUN: %PYTHON %s | FileCheck %s
|
|
|
|
|
|
|
|
from typing import Optional
|
|
|
|
|
|
|
|
import torch
|
|
|
|
import torch.export
|
|
|
|
import torch.nn as nn
|
|
|
|
|
2024-02-07 11:07:59 +08:00
|
|
|
from torch_mlir import fx
|
2023-12-22 00:40:10 +08:00
|
|
|
|
|
|
|
|
|
|
|
def run(f):
|
|
|
|
print(f"{f.__name__}")
|
|
|
|
print("-" * len(f.__name__))
|
|
|
|
f()
|
|
|
|
print()
|
|
|
|
|
|
|
|
|
|
|
|
@run
|
|
|
|
# CHECK-LABEL: test_import_frozen_exported_program
|
|
|
|
# CHECK: func.func @main(%[[ARG0:[a-zA-Z0-9]+]]: !torch.vtensor<[3,4],f32>) -> !torch.vtensor<[3,4],f32>
|
|
|
|
# CHECK-DAG: %[[a:.+]] = torch.vtensor.literal(dense_resource<torch_tensor_1_4_torch.float32> : tensor<1x4xf32>) : !torch.vtensor<[1,4],f32>
|
|
|
|
# CHECK-DAG: %[[b:.+]] = torch.vtensor.literal(dense_resource<torch_tensor_3_1_torch.float32> : tensor<3x1xf32>) : !torch.vtensor<[3,1],f32>
|
2024-02-06 14:19:31 +08:00
|
|
|
# CHECK-DAG: %[[p:.+]] = torch.vtensor.literal(dense<{{.*>+}} : tensor<1x1xf32>) : !torch.vtensor<[1,1],f32>
|
2023-12-22 00:40:10 +08:00
|
|
|
# CHECK-DAG: %[[tanh:.+]] = torch.aten.tanh %[[ARG0]]
|
|
|
|
# CHECK-DAG: %[[mul_a:.+]] = torch.aten.mul.Tensor %[[tanh]], %[[a]]
|
|
|
|
# CHECK-DAG: %[[mul_b:.+]] = torch.aten.mul.Tensor %[[mul_a]], %[[b]]
|
|
|
|
# CHECK-DAG: %[[mul_p:.+]] = torch.aten.mul.Tensor %[[mul_b]], %[[p]]
|
|
|
|
# CHECK: return %[[mul_p]]
|
|
|
|
#
|
|
|
|
# Validate dialect resources exist.
|
|
|
|
# CHECK: dialect_resources:
|
|
|
|
# CHECK-DAG: torch_tensor_1_4_torch.float32
|
|
|
|
# CHECK-DAG: torch_tensor_3_1_torch.float32
|
|
|
|
def test_import_frozen_exported_program():
|
|
|
|
# Tests the basic structural premises of import_frozen_exported_program,
|
|
|
|
# namely that free tensors (buffers) and parameters are treated as
|
|
|
|
# literals and frozen.
|
|
|
|
@torch._dynamo.assume_constant_result
|
|
|
|
def get_a():
|
|
|
|
return torch.randn(1, 4)
|
|
|
|
|
|
|
|
class Basic(nn.Module):
|
|
|
|
def __init__(self):
|
|
|
|
super().__init__()
|
|
|
|
self.b = torch.randn(3, 1)
|
|
|
|
self.p = nn.Parameter(torch.randn(1, 1))
|
|
|
|
|
|
|
|
def forward(self, x):
|
|
|
|
return torch.tanh(x) * get_a() * self.b * self.p
|
|
|
|
|
2024-02-07 11:07:59 +08:00
|
|
|
m = fx.export_and_import(Basic(), torch.randn(3, 4))
|
2023-12-22 00:40:10 +08:00
|
|
|
print(m)
|
2024-02-27 02:08:14 +08:00
|
|
|
|
|
|
|
|
|
|
|
@run
|
|
|
|
# CHECK-LABEL: test_import_frozen_exported_program_with_func_name
|
|
|
|
# CHECK: func.func @test_net(%[[ARG0:[a-zA-Z0-9]+]]: !torch.vtensor<[3,4],f32>) -> !torch.vtensor<[3,4],f32>
|
|
|
|
def test_import_frozen_exported_program_with_func_name():
|
|
|
|
@torch._dynamo.assume_constant_result
|
|
|
|
def get_a():
|
|
|
|
return torch.randn(1, 4)
|
|
|
|
|
|
|
|
class Basic(nn.Module):
|
|
|
|
def __init__(self):
|
|
|
|
super().__init__()
|
|
|
|
self.b = torch.randn(3, 1)
|
|
|
|
self.p = nn.Parameter(torch.randn(1, 1))
|
|
|
|
|
|
|
|
def forward(self, x):
|
|
|
|
return torch.tanh(x) * get_a() * self.b * self.p
|
|
|
|
|
|
|
|
m = fx.export_and_import(Basic(), torch.randn(3, 4), func_name="test_net")
|
|
|
|
print(m)
|