Files
paddlepaddle--paddle/paddle/cinn/common/ir_util.h
T
2026-07-13 12:40:42 +08:00

202 lines
6.4 KiB
C++

// Copyright (c) 2021 CINN Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "paddle/cinn/common/bfloat16.h"
#include "paddle/cinn/common/float16.h"
#include "paddle/cinn/common/float8e4m3.h"
#include "paddle/cinn/common/integer_set.h"
#include "paddle/cinn/ir/ir.h"
#include "paddle/utils/flat_hash_map.h"
namespace cinn {
namespace common {
Expr IndiceToAbsOffset(const std::vector<Expr> &shape,
const std::vector<Expr> &indices);
Expr IndiceToAbsOffset(const std::vector<int> &shape,
const std::vector<Expr> &indices);
Expr PrecedingAxisToAbsOffset(const std::vector<Expr> &shape,
int preceding_n_axis);
Expr CastIfNeeded(Expr body, Type type);
//! Substitute vars to other expressions.
//! @param expr The expression to do modification.
//! @param var_map The map from variables to the target expressions.
void Substitute(Expr *expr, const std::map<const ir::_Var_ *, Expr> &var_map);
//! Get a stack of forloops(For and PolyFor nodes) to a Store node target to \p
//! tensor_name
std::vector<Expr *> GetForloopStackToStore(Expr *expr,
const std::string &tensor_name);
// make const
// @{
inline Expr make_const(int32_t x) { return Expr(static_cast<int32_t>(x)); }
inline Expr make_const(int64_t x) { return Expr(static_cast<int64_t>(x)); }
inline Expr make_const(bfloat16 x) { return Expr(static_cast<bfloat16>(x)); }
inline Expr make_const(float8e4m3 x) {
return Expr(static_cast<float8e4m3>(x));
}
inline Expr make_const(float16 x) { return Expr(static_cast<float16>(x)); }
inline Expr make_const(float x) { return Expr(static_cast<float>(x)); }
inline Expr make_const(double x) { return Expr(static_cast<double>(x)); }
inline Expr make_const(bool x) { return Expr(static_cast<bool>(x)); }
// @}
//! maker for some general consts.
// @{
template <typename T = int32_t>
inline Expr make_zero() {
return make_const(static_cast<T>(0));
}
template <typename T = int32_t>
inline Expr make_one() {
return make_const(static_cast<T>(1));
}
inline Expr make_bool(bool x) {
return cinn::common::make_shared<ir::UIntImm>(Bool(), x);
}
inline Expr make_bool(bool x, int lanes) {
return cinn::common::make_shared<ir::UIntImm>(Bool(lanes), x);
}
// @}
/**
* \brief Check all the tensors are unique in an expression.
*/
void CheckTensorUniqueInExpr(Expr expr);
std::vector<std::string> GatherItersToTensorProducer(
const std::string &target_tensor_name, Expr *expr);
bool is_zero(Expr v);
Expr NormalizeUpperBound(Expr upper_bound, bool minus_one = true);
bool MathEqual(const Expr &a, const Expr &b);
//! helper function to get a ir::Select node.
Expr select(Expr cond, Expr true_value, Expr false_value);
//! helper function to get the And of all the conditions.
Expr and_all(const std::vector<Expr> &conds);
//! helper function to get the Or of all the conditions.
Expr or_any(const std::vector<Expr> &conds);
//! Cast the expression \p e to type \type.
Expr cast(Expr e, Type type);
Expr max(Expr a, Expr b);
Expr min(Expr a, Expr b);
template <typename T>
Expr make_const(Type t, T v) {
if (t.is_vector()) {
if (t.is_int()) {
return ir::Broadcast::Make(
make_shared<ir::IntImm>(t.ElementOf(), static_cast<int64_t>(v)),
t.lanes());
} else if (t.is_uint()) {
return ir::Broadcast::Make(
make_shared<ir::UIntImm>(t.ElementOf(), static_cast<uint64_t>(v)),
t.lanes());
} else if (t.is_float()) {
return ir::Broadcast::Make(
make_shared<ir::FloatImm>(t.ElementOf(), static_cast<double>(v)),
t.lanes());
} else if (t.is_bool()) {
return ir::Broadcast::Make(
make_shared<ir::UIntImm>(t.ElementOf(), static_cast<bool>(v)),
t.lanes());
} else {
CINN_NOT_IMPLEMENTED
}
} else {
if (t.is_int()) {
return make_shared<ir::IntImm>(t, static_cast<int64_t>(v));
} else if (t.is_uint()) {
return make_shared<ir::UIntImm>(t, static_cast<uint64_t>(v));
} else if (t.is_float()) {
return make_shared<ir::FloatImm>(t, static_cast<double>(v));
} else if (t.is_bool()) {
return make_shared<ir::UIntImm>(t, static_cast<bool>(v));
} else {
CINN_NOT_IMPLEMENTED
}
}
return Expr();
}
template <typename FuncOp>
Expr FoldExpr(FuncOp func_op, const std::vector<Expr> &values) {
Expr init_value;
for (const Expr &val : values) {
if (!init_value.defined()) {
init_value = val;
} else {
init_value = func_op(val, init_value);
}
}
return init_value;
}
inline bool IsIterExpr(const Expr &a, const Expr &b) {
return a.As<ir::IterSplit>() || a.As<ir::IterSum>() ||
b.As<ir::IterSplit>() || b.As<ir::IterSum>();
}
inline bool IsOne(const Expr &expr) {
if (expr.is_constant() && expr.get_constant() == 1) {
return true;
}
return false;
}
inline bool IsZero(const Expr &expr) {
if (expr.is_constant() && expr.get_constant() == 0) {
return true;
}
return false;
}
// Promote int32 to int64 type if needed.
void OpDataTypePromote(ir::Expr *expr);
void OpDataTypePromote(ir::Module *module);
void OpDataTypePromote(ir::LoweredFunc *func);
// only process ir::Min and ir::Max where the operands 1. contains dynamic shape
// symbols. 2. the operands are both int types and both are 32/64 bits. Returns
// the number of bits for unifying operands (by casting). The bool flag
// indicates whether both sides has different dynamic shape symbols, since if
// true (like min(S0, S1))), we should not make a ir::Cast but a ir::Call
// (coercion)
std::pair<int, bool> UnifiedOperandTypeBits(
const std::unordered_map<std::string, common::Type> *search_map,
const ir::Min *op);
std::pair<int, bool> UnifiedOperandTypeBits(
const std::unordered_map<std::string, common::Type> *search_map,
const ir::Max *op);
} // namespace common
} // namespace cinn