// Copyright (c) 2025 Huawei Technologies Co., Ltd.
// This program is free software, you can redistribute it and/or modify it under the terms and conditions of
// CANN Open Software License Agreement Version 2.0 (the "License").
// Please refer to the License for details. You may not use this file except in compliance with the License.
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
// See LICENSE in the root of the software repository for the full text of the License.
// RUN: ascir-translate -mlir-to-ascendc %s | FileCheck %s
// CHECK:void emit_binary_ops(int32_t v1, int32_t v2) {
// CHECK-NEXT: int32_t v3 = v1 + v2;
// CHECK-NEXT: int32_t v4 = v1 - v2;
// CHECK-NEXT: int32_t v5 = v1 * v2;
// CHECK-NEXT: int32_t v6 = v1 / v2;
// CHECK-NEXT: int32_t v7 = v1 % v2;
// CHECK-NEXT: int32_t v8 = (v1 + v2 - 1) / v2;
// CHECK-NEXT: int32_t v9 = v1 << v2;
// CHECK-NEXT: int32_t v10 = v1 >> v2;
// CHECK-NEXT: int32_t v11 = v1 >> v2;
// CHECK-NEXT: int32_t v12 = v1 & v2;
// CHECK-NEXT: int32_t v13 = v1 | v2;
// CHECK-NEXT: int32_t v14 = v1 ^ v2;
// CHECK-NEXT: int32_t v15 = v1 / v2;
// CHECK-NEXT: return;
// CHECK-NEXT:}
func.func @emit_binary_ops(%0 : i32, %1 : i32) {
%2 = arith.addi %0, %1 : i32
%3 = arith.subi %0, %1 : i32
%4 = arith.muli %0, %1 : i32
%5 = arith.divsi %0, %1 : i32
%6 = arith.remsi %0, %1 : i32
%7 = arith.ceildivsi %0, %1 : i32
%8 = arith.shli %0, %1 : i32
%9 = arith.shrsi %0, %1 : i32
%10 = arith.shrui %0, %1 : i32
%11 = arith.andi %0, %1 : i32
%12 = arith.ori %0, %1 : i32
%13 = arith.xori %0, %1 : i32
%14 = arith.divui %0, %1 : i32
return
}
// CHECK:void emit_cmpi_op(int32_t v1, int32_t v2) {
// CHECK-NEXT: bool v3 = v1 == v2;
// CHECK-NEXT: bool v4 = v1 != v2;
// CHECK-NEXT: bool v5 = v1 >= v2;
// CHECK-NEXT: bool v6 = v1 > v2;
// CHECK-NEXT: bool v7 = v1 >= v2;
// CHECK-NEXT: bool v8 = v1 > v2;
// CHECK-NEXT: bool v9 = v1 <= v2;
// CHECK-NEXT: bool v10 = v1 < v2;
// CHECK-NEXT: bool v11 = v1 <= v2;
// CHECK-NEXT: bool v12 = v1 < v2;
// CHECK-NEXT: return;
// CHECK-NEXT:}
func.func @emit_cmpi_op(%arg0: i32, %arg1: i32) {
%0 = arith.cmpi eq, %arg0, %arg1 : i32
%1 = arith.cmpi ne, %arg0, %arg1 : i32
%2 = arith.cmpi sge, %arg0, %arg1 : i32
%3 = arith.cmpi sgt, %arg0, %arg1 : i32
%4 = arith.cmpi uge, %arg0, %arg1 : i32
%5 = arith.cmpi ugt, %arg0, %arg1 : i32
%6 = arith.cmpi sle, %arg0, %arg1 : i32
%7 = arith.cmpi slt, %arg0, %arg1 : i32
%8 = arith.cmpi ule, %arg0, %arg1 : i32
%9 = arith.cmpi ult, %arg0, %arg1 : i32
return
}
// CHECK:void emit_cmpf_op(float v1, float v2) {
// CHECK-NEXT: bool v3 = v1 == v2;
// CHECK-NEXT: bool v4 = v1 == v2;
// CHECK-NEXT: bool v5 = v1 != v2;
// CHECK-NEXT: bool v6 = v1 != v2;
// CHECK-NEXT: bool v7 = v1 <= v2;
// CHECK-NEXT: bool v8 = v1 <= v2;
// CHECK-NEXT: bool v9 = v1 < v2;
// CHECK-NEXT: bool v10 = v1 < v2;
// CHECK-NEXT: bool v11 = v1 >= v2;
// CHECK-NEXT: bool v12 = v1 >= v2;
// CHECK-NEXT: bool v13 = v1 > v2;
// CHECK-NEXT: bool v14 = v1 > v2;
// CHECK-NEXT: return;
// CHECK-NEXT:}
func.func @emit_cmpf_op(%arg0: f32, %arg1: f32) {
%0 = arith.cmpf oeq, %arg0, %arg1 : f32
%1 = arith.cmpf ueq, %arg0, %arg1 : f32
%2 = arith.cmpf one, %arg0, %arg1 : f32
%3 = arith.cmpf une, %arg0, %arg1 : f32
%4 = arith.cmpf ole, %arg0, %arg1 : f32
%5 = arith.cmpf ule, %arg0, %arg1 : f32
%6 = arith.cmpf olt, %arg0, %arg1 : f32
%7 = arith.cmpf ult, %arg0, %arg1 : f32
%8 = arith.cmpf oge, %arg0, %arg1 : f32
%9 = arith.cmpf uge, %arg0, %arg1 : f32
%10 = arith.cmpf ogt, %arg0, %arg1 : f32
%11 = arith.cmpf ugt, %arg0, %arg1 : f32
return
}
// CHECK:void emit_select_op(bool v1, int32_t v2, int32_t v3) {
// CHECK-NEXT: int32_t v4 = v1 ? v2 : v3;
// CHECK-NEXT: return;
// CHECK-NEXT:}
func.func @emit_select_op(%arg0: i1, %arg1: i32, %arg2: i32) {
%0 = arith.select %arg0, %arg1, %arg2 : i1, i32
return
}
// CHECK:void emit_casts(int16_t v1, float v2, uint32_t v3) {
// CHECK-NEXT: int32_t v4 = static_cast<int32_t>(v1);
// CHECK-NEXT: int64_t v5 = static_cast<int64_t>(v1);
// CHECK-NEXT: int8_t v6 = static_cast<int8_t>(v1);
// CHECK-NEXT: half v7 = static_cast<half>(v1);
// CHECK-NEXT: double v8 = static_cast<double>(v2);
// CHECK-NEXT: half v9 = static_cast<half>(v2);
// CHECK-NEXT: int32_t v10 = static_cast<int32_t>(v2);
// CHECK-NEXT: half v11 = *reinterpret_cast<half*>(&v1);
// CHECK-NEXT: int32_t v12 = static_cast<int32_t>(v3);
// CHECK-NEXT: uint32_t v13 = static_cast<uint32_t>(v1);
// CHECK-NEXT: half v14 = static_cast<half>(v1);
// CHECK-NEXT: return;
// CHECK-NEXT:}
func.func @emit_casts(%arg0: i16, %arg1: f32, %arg2: index) {
%0 = arith.extsi %arg0 : i16 to i32
%1 = arith.extui %arg0 : i16 to i64
%2 = arith.trunci %arg0 : i16 to i8
%3 = arith.sitofp %arg0 : i16 to f16
%4 = arith.extf %arg1 : f32 to f64
%5 = arith.truncf %arg1 : f32 to f16
%6 = arith.fptosi %arg1 : f32 to i32
%7 = arith.bitcast %arg0 : i16 to f16
%8 = arith.index_cast %arg2 : index to i32
%9 = arith.index_cast %arg0 : i16 to index
%10 = arith.uitofp %arg0 : i16 to f16
return
}
// CHECK:void emit_maxf(float v1, float v2) {
// CHECK-NEXT: float v3 = ((v1 > v2) ? (v1) : (v2));
// CHECK-NEXT: float v4 = ((v1 > v2) ? (v1) : (v2));
// CHECK-NEXT: return;
// CHECK-NEXT:}
func.func @emit_maxf(%arg0 : f32, %arg1 : f32) {
%0 = arith.maxnumf %arg0, %arg1 : f32
%1 = arith.maximumf %arg0, %arg1 : f32
return
}
// CHECK:void emit_minf(float v1, float v2) {
// CHECK-NEXT: float v3 = ((v1 < v2) ? (v1) : (v2));
// CHECK-NEXT: float v4 = ((v1 < v2) ? (v1) : (v2));
// CHECK-NEXT: return;
// CHECK-NEXT:}
func.func @emit_minf(%arg0 : f32, %arg1 : f32) {
%0 = arith.minnumf %arg0, %arg1 : f32
%1 = arith.minimumf %arg0, %arg1 : f32
return
}
// CHECK:void emit_constants(float v1, float v2) {
// CHECK-NEXT: constexpr int32_t c0_i32 = 0;
// CHECK-NEXT: constexpr uint32_t c0_idx = 0;
// CHECK-NEXT: constexpr int64_t c1024_i64 = 1024;
// CHECK-NEXT: constexpr float cpInf_f32 = __builtin_inff();
// CHECK-NEXT: constexpr float cmInf_f32 = -__builtin_inff();
// CHECK-NEXT: return;
// CHECK-NEXT:}
func.func @emit_constants(%arg0 : f32, %arg1 : f32) {
%c0_i32 = arith.constant 0 : i32
%c0 = arith.constant 0 : index
%c1024_i64 = arith.constant 1024 : i64
%cstInf = arith.constant 0x7F800000 : f32
%cstmInf = arith.constant 0xFF800000 : f32
return
}
// CHECK:void emit_mului_extended(int32_t v1, int32_t v2, int16_t v3, int16_t v4) {
// CHECK-NEXT: int32_t v5 = v1 * v2;
// CHECK-NEXT: int32_t v6 = (static_cast<uint64_t>(v1) * static_cast<uint64_t>(v2)) >> 32;
// CHECK-NEXT: int16_t v7 = v3 * v4;
// CHECK-NEXT: int16_t v8 = (static_cast<uint32_t>(v3) * static_cast<uint32_t>(v4)) >> 16;
// CHECK-NEXT: return;
// CHECK-NEXT:}
func.func @emit_mului_extended(%arg0 : i32, %arg1 : i32, %arg2 : i16, %arg3 : i16) {
%0, %1 = arith.mului_extended %arg0, %arg1 : i32
%2, %3 = arith.mului_extended %arg2, %arg3 : i16
return
}