Files
2026-07-13 12:40:42 +08:00

689 lines
27 KiB
C++

// Copyright (c) 2024 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.
#include <glog/logging.h>
#include <gtest/gtest.h>
#include "paddle/cinn/common/integer_set.h"
#include "paddle/cinn/common/simplify_special_pattern.h"
#include "paddle/cinn/ir/ir.h"
#include "paddle/cinn/ir/ir_base.h"
#include "paddle/cinn/ir/ir_mutator.h"
#include "paddle/cinn/ir/op/ir_operators.h"
#include "paddle/cinn/optim/simplify_util.h"
namespace cinn {
namespace common {
using optim::ChangeSeqOfDivMod;
using optim::CheckPattern;
using optim::ConstructIndexExprByNodeType;
using optim::MatchPattern;
using optim::ParseExpressionFromString;
class TestIndexExpr : public ::testing::Test {
public:
void SetUp() override {
S4 = ir::Var(ir::Expr(static_cast<int64_t>(1)), ir::Expr(INT32_MAX), "S4")
.set_index(true);
S5 = ir::Var(ir::Expr(static_cast<int64_t>(1)), ir::Expr(INT32_MAX), "S5")
.set_index(true);
S6 = ir::Var(ir::Expr(static_cast<int64_t>(1)), ir::Expr(INT32_MAX), "S6")
.set_index(true);
S7 = ir::Var(ir::Expr(static_cast<int64_t>(1)), ir::Expr(INT32_MAX), "S7")
.set_index(true);
S8 = ir::Var(ir::Expr(static_cast<int64_t>(1)), ir::Expr(INT32_MAX), "S8")
.set_index(true);
S9 = ir::Var(ir::Expr(static_cast<int64_t>(1)), ir::Expr(INT32_MAX), "S9")
.set_index(true);
f = ir::Var(ir::Expr(static_cast<int64_t>(1)), ir::Expr(INT32_MAX), "f");
};
ir::Var S4, S5, S6, S7, S8, S9, f;
};
TEST_F(TestIndexExpr, IndexExpr_0) {
ir::IndexExpr a(14);
ir::IndexExpr b(7);
Expr d(6);
ir::Expr c0 = a + b;
ir::Expr c1 = a - b;
ir::Expr c2 = a * b;
ir::Expr c3 = a / b;
ir::Expr c4 = a % b;
ir::Expr c5 = a / d.as_index();
ir::Expr c6 = a % d.as_index();
EXPECT_EQ(c0, Expr(21));
EXPECT_EQ(c1, Expr(7));
EXPECT_EQ(c2, Expr(98));
EXPECT_EQ(c3, Expr(2));
EXPECT_EQ(c4, Expr(0));
EXPECT_EQ(c5, Expr(2));
EXPECT_EQ(c6, Expr(2));
}
TEST_F(TestIndexExpr, IndexExpr_1) {
auto test = S6 * S7;
ir::IndexExpr e1 = (S5 * ((S4 * (S5 * (S6 * S7))) / S5));
ir::IndexExpr e2 = (S4 * (S5 * (S6 * S7))) / S5;
ir::IndexExpr e3 = (S4 * S5) / S5;
ir::IndexExpr e4 = (S4 * (S5 * (S6 * S7)) + S5) / S5;
ir::IndexExpr e5 = (S4 * (S5 * (S6 * S7)) + 2 * S5) / S5;
ir::IndexExpr e6 = (S4 * (S5 * (S6 * S7)) + S5 / S6) / S5;
ir::IndexExpr e7 = (S4 * (S5 * (S6 * S7)) + 2 * S5 / S6) / S5;
EXPECT_EQ(e1.Normalize(), ir::IndexExpr((S6 * S7) * S4 * S5));
EXPECT_EQ(e2.Normalize(), ir::IndexExpr((S6 * S7) * S4));
EXPECT_EQ(e3.Normalize(), ir::IndexExpr(S4));
EXPECT_EQ(e4.Normalize(), ir::IndexExpr(((S6 * S7) * S4) + 1));
EXPECT_EQ(e5.Normalize(), ir::IndexExpr(((S6 * S7) * S4) + 2));
EXPECT_EQ(e6.Normalize(), ir::IndexExpr(((S6 * S7) * S4) + (1 / S6)));
EXPECT_EQ(e7.Normalize(), ir::IndexExpr(((S6 * S7) * S4) + (2 / S6)));
}
TEST_F(TestIndexExpr, IndexExpr_2) {
ir::Expr q1 = S4;
ir::Expr q2 = S4;
ir::Expr q3 = S4 + S5;
ir::Expr q4 = S5 + S4;
ir::Expr q5 = S4 * 2 + S5 / 4;
ir::Expr q6 = S5 / 4 + S4 * 2;
ir::Expr q7 = S4 + S5 + S6;
ir::Expr q8 = S5 + (S4 + S6);
ir::Expr q9 = S4 + (S5 + S7 / 4 + S6 * 2);
ir::Expr q10 = S5 + (S4 + S6 * 2 + S7 / 4);
ir::Expr q11 = (S7 + S5) + (S4 + S6);
ir::Expr q12 = (S4 + S5) + (S6 + S7);
ir::Expr q13 = (S4 + S5) * 3 + (S6 / 2 + S7) * 2;
ir::Expr q14 = (S6 / 2 + S7) * 2 + (S4 + S5) * 3;
ir::Expr q15 = (S4 + S5 * 2) * 3 + (S6 / 2 + S7) * 2;
ir::Expr q16 = (S6 / 2 + S7) * 2 + (S4 + S5 * 2) * 3;
ir::Expr q17 = (S4 + S5 * 2) * 3 + (S6 / 2 + S7) * 2 + S4;
ir::Expr q18 = (S6 / 2 + S7) * 2 + (S4 + S5 * 2) * 3 + S4;
ir::Expr q19 = (S4 + S5 * 2) * 3 + (S6 / 2 + S7) * 2 + S4;
ir::Expr q20 = (S6 / 2 + S7) * 2 + (S4 + S5 * 2) * 3 + S5;
EXPECT_EQ(q1.as_index().Normalize(), q2.as_index().Normalize());
EXPECT_EQ(q3.as_index().Normalize(), q4.as_index().Normalize());
EXPECT_EQ(q5.as_index().Normalize(), q6.as_index().Normalize());
EXPECT_EQ(q7.as_index().Normalize(), q8.as_index().Normalize());
EXPECT_EQ(q9.as_index().Normalize(), q10.as_index().Normalize());
EXPECT_EQ(q11.as_index().Normalize(), q12.as_index().Normalize());
EXPECT_EQ(q13.as_index().Normalize(), q14.as_index().Normalize());
EXPECT_EQ(q15.as_index().Normalize(), q16.as_index().Normalize());
EXPECT_EQ(q17.as_index().Normalize(), q18.as_index().Normalize());
EXPECT_NE(q19.as_index().Normalize(), q20.as_index().Normalize());
}
TEST_F(TestIndexExpr, IndexExpr_3) {
// `Add` corner cases
ir::Expr q1 = S4 / S5 * S5 + S4 % S5;
ir::Expr q2 = (S4 + S5) / S6 * S6 + (S4 + S5) % S6;
ir::Expr q3 = S4 / (S5 + S6) * (S5 + S6) + S4 % (S5 + S6);
ir::Expr q4 = (S4 + S5) / (S6 + S7) * (S6 + S7) + (S4 + S5) % (S6 + S7);
ir::Expr q5 = (S4 + S5) / 5 * 5 + (S4 + S5) * 11 % 5;
ir::Expr q14 = (S4 + S5) / (S6 * S7) * S6 * S7 + (S4 + S5) % (S6 * S7);
ir::Expr q15 =
(S4 * 256 + S5 + S6 * 1024) % 25088 / 512 * 512 + (S4 * 256 + S5) % 512;
ir::Expr q16 =
((S4 * 256 + S5) / S6 / S7 * S7 + (S4 * 256 + S5) / S6 % S7) * S6 +
(S4 * 256 + S5) % S6;
ir::Expr q17 = S4 / (S5 * S6) * S6 + S4 % (S5 * S6) / S5;
ir::Expr q18 = (S4 * 1024 + S5 * 256 + S6) / 2097152 * 32 +
(S4 * 1024 + S5 * 256 + S6) % 2097152 / 65536;
// `Div` corner cases
ir::Expr q6 = (S4 % S5 - S4) / S5;
ir::Expr q7 = (S4 - S4 % S5) / S5;
ir::Expr q8 = ((S4 + S5) % S6 - S4 - S5) / S6;
ir::Expr q9 = (S4 + S5 - (S4 + S5) % S6) / S6;
// `Mod` corner cases
ir::Expr q10 = (S4 % S5 - S4) % S5;
ir::Expr q11 = (S4 - S4 % S5) % S5;
ir::Expr q12 = ((S4 + S5) % S6 - S4 - S5) % S6;
ir::Expr q13 = (S4 + S5 - (S4 + S5) % S6) % S6;
EXPECT_EQ(q1.as_index().Normalize(), ir::IndexExpr(S4));
EXPECT_EQ(q2.as_index().Normalize(), ir::IndexExpr(S4 + S5));
EXPECT_EQ(q3.as_index().Normalize(), ir::IndexExpr(S4));
EXPECT_EQ(q4.as_index().Normalize(), ir::IndexExpr(S4 + S5));
EXPECT_EQ(q5.as_index().Normalize(), ir::IndexExpr(S4 + S5));
EXPECT_EQ(q6.as_index().Normalize(), ir::IndexExpr((S4 / S5) * (-1)));
EXPECT_EQ(q7.as_index().Normalize(), ir::IndexExpr(S4 / S5));
EXPECT_EQ(q8.as_index().Normalize(), ir::IndexExpr(((S4 + S5) / S6) * (-1)));
EXPECT_EQ(q9.as_index().Normalize(), ir::IndexExpr((S4 + S5) / S6));
EXPECT_EQ(q10.as_index().Normalize(), ir::IndexExpr(0));
EXPECT_EQ(q11.as_index().Normalize(), ir::IndexExpr(0));
EXPECT_EQ(q12.as_index().Normalize(), ir::IndexExpr(0));
EXPECT_EQ(q13.as_index().Normalize(), ir::IndexExpr(0));
EXPECT_EQ(q14.as_index().Normalize(), ir::IndexExpr(S4 + S5));
EXPECT_EQ(q15.as_index().Normalize(),
ir::IndexExpr((S4 * 256 + S5 + S6 * 1024)) % 25088);
EXPECT_EQ(q16.as_index().Normalize(ir::IndexExpr::OptLevel::kLevel2),
ir::IndexExpr(S4 * 256 + S5));
EXPECT_EQ(q17.as_index().Normalize(), ir::IndexExpr(S4 / S5));
EXPECT_EQ(q18.as_index().Normalize(),
ir::IndexExpr((S4 * 1024 + S5 * 256 + S6) / 65536));
}
TEST_F(TestIndexExpr, Change_Seq_Of_Div_Mod) {
ir::Expr q1 = S4 / S5;
ir::Expr q2 = S4 % S5;
ir::Expr q3 = S4 / S5 % S6;
ir::Expr q4 = S4 / S5 % S6;
EXPECT_EQ(ChangeSeqOfDivMod(q1.as_index()), q1);
EXPECT_EQ(ChangeSeqOfDivMod(q2.as_index()), q2);
EXPECT_EQ(ChangeSeqOfDivMod(q3.as_index()), S4 % (S5 * S6) / S5);
}
TEST_F(TestIndexExpr, Test_ConstructIndexExprByNodeType) {
ir::Expr result_add = ConstructIndexExprByNodeType(
ir::IrNodeTy::Add, S4.as_index(), S5.as_index(), true);
ir::Expr result_sub = ConstructIndexExprByNodeType(
ir::IrNodeTy::Sub, S4.as_index(), S5.as_index(), false);
ir::Expr result_mul = ConstructIndexExprByNodeType(
ir::IrNodeTy::Mul, S4.as_index(), S5.as_index(), true);
ir::Expr result_div = ConstructIndexExprByNodeType(
ir::IrNodeTy::Div, S4.as_index(), S5.as_index(), true);
ir::Expr result_mod = ConstructIndexExprByNodeType(
ir::IrNodeTy::Mod, S4.as_index(), S5.as_index(), true);
ir::Expr result_min = ConstructIndexExprByNodeType(
ir::IrNodeTy::Min, S4.as_index(), S5.as_index(), false);
ir::Expr result_max = ConstructIndexExprByNodeType(
ir::IrNodeTy::Max, S4.as_index(), S5.as_index(), false);
EXPECT_EQ(result_add, S4 + S5);
EXPECT_EQ(result_sub, S4 - S5);
EXPECT_EQ(result_mul, S4 * S5);
EXPECT_EQ(result_div, S4 / S5);
EXPECT_EQ(result_mod, S4 % S5);
EXPECT_EQ(result_min, ir::Min::Make(S4, S5));
EXPECT_EQ(result_max, ir::Max::Make(S4, S5));
}
TEST_F(TestIndexExpr, Test_dynamic) {
ir::Expr q =
((((((((((((((((S7 * 1024) + S8) + (S9 * 4096)) / S6) % S5) * S6) +
((((S7 * 1024) + S8) + (S9 * 4096)) % S6)) +
(((((((((S7 * 1024) + S8) + (S9 * 4096)) / S6) / S5) % 640) %
S4) *
S6) *
S5)) +
(((((((((S7 * 1024) + S8) + (S9 * 4096)) / S6) / S5) / 640) *
S5) *
S6) *
S4)) /
((S5 * S6) * S4)) *
S4) +
(((((((((((S7 * 1024) + S8) + (S9 * 4096)) / S6) % S5) * S6) +
((((S7 * 1024) + S8) + (S9 * 4096)) % S6)) +
(((((((((S7 * 1024) + S8) + (S9 * 4096)) / S6) / S5) % 640) %
S4) *
S6) *
S5)) +
(((((((((S7 * 1024) + S8) + (S9 * 4096)) / S6) / S5) / 640) *
S5) *
S6) *
S4)) /
(S5 * S6)) %
S4)) *
S5) +
(((((((((((S7 * 1024) + S8) + (S9 * 4096)) / S6) % S5) * S6) +
((((S7 * 1024) + S8) + (S9 * 4096)) % S6)) +
(((((((((S7 * 1024) + S8) + (S9 * 4096)) / S6) / S5) % 640) % S4) *
S6) *
S5)) +
(((((((((S7 * 1024) + S8) + (S9 * 4096)) / S6) / S5) / 640) * S5) *
S6) *
S4)) /
S6) %
S5)) *
S6) +
((((((((((S7 * 1024) + S8) + (S9 * 4096)) / S6) % S5) * S6) +
((((S7 * 1024) + S8) + (S9 * 4096)) % S6)) +
(((((((((S7 * 1024) + S8) + (S9 * 4096)) / S6) / S5) % 640) % S4) *
S6) *
S5)) +
(((((((((S7 * 1024) + S8) + (S9 * 4096)) / S6) / S5) / 640) * S5) *
S6) *
S4)) %
S6));
ir::Expr q1 =
((((((f % ((S5 * S6) * 640)) % ((S5 * S6) * S4)) / (S5 * S6)) * S6) *
S5) +
(f % (S5 * S6)));
ir::Expr q2 = ((f % ((S5 * S6) * 640)) % ((S5 * S6) * S4)) % (S5 * S6);
ir::Expr q3 = (S5 * S6) * S4 / (S5 * S6);
ir::Expr q4 = (S5 * S6) * S4 % (S5 * S6);
ir::Expr q5 =
(((((((((((((f % ((S5 * S6) * 640)) % ((S5 * S6) * S4)) / (S5 * S6)) +
((f / ((S5 * S6) * 640)) * S4)) *
S5) *
S6) +
(f % (S5 * S6))) %
((S5 * S6) * S4)) /
(S5 * S6)) +
(((((((((f % ((S5 * S6) * 640)) % ((S5 * S6) * S4)) / (S5 * S6)) +
((f / ((S5 * S6) * 640)) * S4)) *
S5) *
S6) +
(f % (S5 * S6))) /
((S5 * S6) * S4)) *
S4)) *
S5) *
S6) +
(f % (S5 * S6)));
EXPECT_EQ(
q.as_index().Normalize(ir::IndexExpr::OptLevel::kLevel2),
((((((((S7 * 1024) + S8) + (S9 * 4096)) / ((S5 * S6) * 640)) * S5) * S6) *
S4) +
(((((S7 * 1024) + S8) + (S9 * 4096)) % ((S5 * S6) * 640)) %
((S5 * S6) * S4))));
EXPECT_EQ(q1.as_index().Normalize(ir::IndexExpr::OptLevel::kLevel2),
((f % ((S5 * S6) * 640)) % ((S5 * S6) * S4)));
EXPECT_EQ(q2.as_index().Normalize(ir::IndexExpr::OptLevel::kLevel2),
f % (S5 * S6));
EXPECT_EQ(q3.as_index().Normalize(ir::IndexExpr::OptLevel::kLevel2),
Expr(S4));
EXPECT_EQ(q4.as_index().Normalize(ir::IndexExpr::OptLevel::kLevel2), Expr(0));
EXPECT_EQ(q5.as_index().Normalize(ir::IndexExpr::OptLevel::kLevel2),
(((((f / ((S5 * S6) * 640)) * S4) * S5) * S6) +
((f % ((S5 * S6) * 640)) % ((S5 * S6) * S4))));
}
TEST_F(TestIndexExpr, CommonFactor) {
ir::Var S0 = ir::Var("S0");
ir::Var S1 = ir::Var("S1");
ir::Var S2 = ir::Var("S2");
ir::Var S3 = ir::Var("S3");
ir::Var S4 = ir::Var("S4");
ir::Var S5 = ir::Var("S5");
ir::Var S6 = ir::Var("S6");
ir::Var S7 = ir::Var("S7");
ir::Var S8 = ir::Var("S8");
ir::Var S9 = ir::Var("S9");
ir::Var S13 = ir::Var("S13");
ir::Var S17 = ir::Var("S17");
ir::Var S21 = ir::Var("S21");
ir::Var tx = ir::Var("tx");
ir::Var bx = ir::Var("bx");
ir::Expr q = ((((((((S1 + S13) + S17) + S21) + S5) + S9)) * S2) * S3);
ir::Expr q1 = (((((((S3 * S5) * S2) + ((S3 * S9) * S2)) + ((S3 * S21) * S2)) +
((S2 * S3) * S17)) +
((S2 * S3) * S13)) +
((S2 * S3) * S1));
ir::Expr q2 =
(((((((((f * 1024) + tx) + (bx * 4096)) %
((((((((((((((((((((((((((S3 * S5) * S2) * S0) +
(((S3 * S9) * S2) * S0)) +
(((S3 * S21) * S2) * S0)) +
(((S2 * S3) * S17) * S0)) +
(((S2 * S3) * S13) * S0)) +
(((S2 * S3) * S1) * S0)) /
4096) *
4096) +
((S3 * S5) * S2)) +
((S3 * S9) * S2)) +
((S3 * S21) * S2)) +
((S2 * S3) * S17)) +
((S2 * S3) * S13)) +
((S2 * S3) * S1)) +
4095) /
(((((((S3 * S5) * S2) + ((S3 * S9) * S2)) +
((S3 * S21) * S2)) +
((S2 * S3) * S17)) +
((S2 * S3) * S13)) +
((S2 * S3) * S1))) *
S3) *
S5) *
S2) +
(((((((((((((((((((((S3 * S5) * S2) * S0) +
(((S3 * S9) * S2) * S0)) +
(((S3 * S21) * S2) * S0)) +
(((S2 * S3) * S17) * S0)) +
(((S2 * S3) * S13) * S0)) +
(((S2 * S3) * S1) * S0)) /
4096) *
4096) +
((S3 * S5) * S2)) +
((S3 * S9) * S2)) +
((S3 * S21) * S2)) +
((S2 * S3) * S17)) +
((S2 * S3) * S13)) +
((S2 * S3) * S1)) +
4095) /
(((((((S3 * S5) * S2) + ((S3 * S9) * S2)) +
((S3 * S21) * S2)) +
((S2 * S3) * S17)) +
((S2 * S3) * S13)) +
((S2 * S3) * S1))) *
S3) *
S9) *
S2)) +
(((((((((((((((((((((S3 * S5) * S2) * S0) +
(((S3 * S9) * S2) * S0)) +
(((S3 * S21) * S2) * S0)) +
(((S2 * S3) * S17) * S0)) +
(((S2 * S3) * S13) * S0)) +
(((S2 * S3) * S1) * S0)) /
4096) *
4096) +
((S3 * S5) * S2)) +
((S3 * S9) * S2)) +
((S3 * S21) * S2)) +
((S2 * S3) * S17)) +
((S2 * S3) * S13)) +
((S2 * S3) * S1)) +
4095) /
(((((((S3 * S5) * S2) + ((S3 * S9) * S2)) +
((S3 * S21) * S2)) +
((S2 * S3) * S17)) +
((S2 * S3) * S13)) +
((S2 * S3) * S1))) *
S3) *
S21) *
S2)) +
(((((((((((((((((((((S3 * S5) * S2) * S0) +
(((S3 * S9) * S2) * S0)) +
(((S3 * S21) * S2) * S0)) +
(((S2 * S3) * S17) * S0)) +
(((S2 * S3) * S13) * S0)) +
(((S2 * S3) * S1) * S0)) /
4096) *
4096) +
((S3 * S5) * S2)) +
((S3 * S9) * S2)) +
((S3 * S21) * S2)) +
((S2 * S3) * S17)) +
((S2 * S3) * S13)) +
((S2 * S3) * S1)) +
4095) /
(((((((S3 * S5) * S2) + ((S3 * S9) * S2)) +
((S3 * S21) * S2)) +
((S2 * S3) * S17)) +
((S2 * S3) * S13)) +
((S2 * S3) * S1))) *
S2) *
S3) *
S17)) +
(((((((((((((((((((((S3 * S5) * S2) * S0) +
(((S3 * S9) * S2) * S0)) +
(((S3 * S21) * S2) * S0)) +
(((S2 * S3) * S17) * S0)) +
(((S2 * S3) * S13) * S0)) +
(((S2 * S3) * S1) * S0)) /
4096) *
4096) +
((S3 * S5) * S2)) +
((S3 * S9) * S2)) +
((S3 * S21) * S2)) +
((S2 * S3) * S17)) +
((S2 * S3) * S13)) +
((S2 * S3) * S1)) +
4095) /
(((((((S3 * S5) * S2) + ((S3 * S9) * S2)) +
((S3 * S21) * S2)) +
((S2 * S3) * S17)) +
((S2 * S3) * S13)) +
((S2 * S3) * S1))) *
S2) *
S3) *
S13)) +
(((((((((((((((((((((S3 * S5) * S2) * S0) +
(((S3 * S9) * S2) * S0)) +
(((S3 * S21) * S2) * S0)) +
(((S2 * S3) * S17) * S0)) +
(((S2 * S3) * S13) * S0)) +
(((S2 * S3) * S1) * S0)) /
4096) *
4096) +
((S3 * S5) * S2)) +
((S3 * S9) * S2)) +
((S3 * S21) * S2)) +
((S2 * S3) * S17)) +
((S2 * S3) * S13)) +
((S2 * S3) * S1)) +
4095) /
(((((((S3 * S5) * S2) + ((S3 * S9) * S2)) +
((S3 * S21) * S2)) +
((S2 * S3) * S17)) +
((S2 * S3) * S13)) +
((S2 * S3) * S1))) *
S2) *
S3) *
S1))) /
(((((((S3 * S5) * S2) + ((S3 * S9) * S2)) + ((S3 * S21) * S2)) +
((S2 * S3) * S17)) +
((S2 * S3) * S13)) +
((S2 * S3) * S1))) *
(((((S1 + S13) + S17) + S21) + S5) + S9)) *
S2) *
S3) +
((((f * 1024) + tx) + (bx * 4096)) %
(((((((S3 * S5) * S2) + ((S3 * S9) * S2)) + ((S3 * S21) * S2)) +
((S2 * S3) * S17)) +
((S2 * S3) * S13)) +
((S2 * S3) * S1))));
EXPECT_EQ(q.as_index().Normalize(ir::IndexExpr::OptLevel::kLevel2),
(((((((S1 + S13) + S17) + S21) + S5) + S9) * S2) * S3));
EXPECT_EQ(q1.as_index().Normalize(ir::IndexExpr::OptLevel::kLevel2),
(((((((S5 + S9) + S21) + S17) + S13) + S1) * S2) * S3));
EXPECT_EQ(
q2.as_index().Normalize(ir::IndexExpr::OptLevel::kLevel2),
((((f * 1024) + tx) + (bx * 4096)) %
((((((((((((((((S5 + S9) + S21) + S17) + S13) + S1) * S2) * S3) * S0) /
4096) *
4096) +
(((((((S5 + S9) + S21) + S17) + S13) + S1) * S2) * S3)) +
4095) /
(((((((S5 + S9) + S21) + S17) + S13) + S1) * S2) * S3)) *
S3) *
S2) *
(((((S5 + S9) + S21) + S17) + S13) + S1))));
}
TEST_F(TestIndexExpr, TestCheckPattern) {
ir::Var a = ir::Var("a");
ir::Var b = ir::Var("b");
ir::Var f = ir::Var("f");
ir::Var S0 = ir::Var("S0");
ir::Var S1 = ir::Var("S1");
ir::Var S2 = ir::Var("S2");
ir::Var S3 = ir::Var("S3");
ir::Var S4 = ir::Var("S4");
ir::Var S5 = ir::Var("S5");
ir::Var S6 = ir::Var("S6");
ir::Var S7 = ir::Var("S7");
ir::Var S8 = ir::Var("S8");
ir::Var S9 = ir::Var("S9");
ir::IndexExpr pattern = f / (a * b) * b + f % (a * b) / a;
ir::IndexExpr pattern1 = f / (a * b) * a + f % (a * b) / b;
ir::IndexExpr e = (S0 * (S1 + S2) + S1 * S2 + S2) / (S4 * S5) * S5 +
(S0 * (S1 + S2) + S1 * S2 + S2) % (S4 * S5) / S4;
ir::IndexExpr e1 = (S0 * (S1 + S2) + S1 * S2 + S2) / (S4 * S5) * S4 +
(S0 * (S1 + S2) + S1 * S2 + S2) % (S4 * S5) / S5;
std::unordered_map<std::string, ir::IndexExpr> map;
EXPECT_TRUE(CheckPattern(e, pattern, &map));
map.clear();
EXPECT_FALSE(CheckPattern(e, pattern1, &map));
map.clear();
EXPECT_FALSE(CheckPattern(e1, pattern, &map));
map.clear();
EXPECT_TRUE(CheckPattern(e1, pattern1, &map));
}
TEST_F(TestIndexExpr, ParseExpression) {
ir::Var a = ir::Var("a");
ir::Var b = ir::Var("b");
ir::Var a1 = ir::Var("a_1");
ir::Var b2 = ir::Var("b2");
ir::Expr e1 = a + b;
ir::Expr e2 = a - b;
ir::Expr e3 = a * b;
ir::Expr e4 = a / b;
ir::Expr e5 = a % b;
ir::Expr e6 = a + ir::Expr(20);
ir::Expr e7 = a - ir::Expr(10);
ir::Expr e8 = ir::Expr(5) * b;
ir::Expr e9 = ir::Expr(20) / b;
ir::Expr e10 = a % ir::Expr(3) + b;
ir::Expr e11 = (a + b) * (a - b);
ir::Expr e12 = (a + (b * a)) - (b / a);
ir::Expr e13 = (a + b) * (a - b) + (a / b) - (b % a);
ir::Expr e14 = a1 + b2;
ir::Expr e15 = a + b;
EXPECT_EQ(e1, ParseExpressionFromString("a + b"));
EXPECT_EQ(e2, ParseExpressionFromString("a - b"));
EXPECT_EQ(e3, ParseExpressionFromString("a * b"));
EXPECT_EQ(e4, ParseExpressionFromString("a / b"));
EXPECT_EQ(e5, ParseExpressionFromString("a % b"));
EXPECT_EQ(e6, ParseExpressionFromString("a + 20"));
EXPECT_EQ(e7, ParseExpressionFromString("a - 10"));
EXPECT_EQ(e8, ParseExpressionFromString("5 * b"));
EXPECT_EQ(e9, ParseExpressionFromString("20 / b"));
EXPECT_EQ(e10, ParseExpressionFromString("a % 3 + b"));
EXPECT_EQ(e11, ParseExpressionFromString("(a + b) * (a - b)"));
EXPECT_EQ(e12, ParseExpressionFromString("(a + (b * a)) - (b / a)"));
EXPECT_EQ(e13,
ParseExpressionFromString("(a + b) * (a - b) + (a / b) - (b % a)"));
EXPECT_EQ(e14, ParseExpressionFromString("a_1 + b2"));
EXPECT_EQ(e15, ParseExpressionFromString(" a + b "));
EXPECT_ANY_THROW(ParseExpressionFromString("a + #"));
EXPECT_ANY_THROW(ParseExpressionFromString("(a + b"));
EXPECT_ANY_THROW(ParseExpressionFromString(""));
}
TEST_F(TestIndexExpr, MatchPattern) {
ir::Var a = ir::Var("a");
ir::Var b = ir::Var("b");
ir::Var x = ir::Var("x");
ir::Var y = ir::Var("y");
ir::IndexExpr expr1 = a + b;
ir::IndexExpr expr2 = a * b;
ir::IndexExpr expr3 = a + (b * 10);
ir::IndexExpr expr4 = (a + b) * 10;
ir::IndexExpr expr5 = x + y;
ir::IndexExpr expr6 = x * y;
auto result1 = MatchPattern(expr1, "a + b", nullptr);
EXPECT_TRUE(result1.has_value());
EXPECT_EQ(result1->at("a"), a);
EXPECT_EQ(result1->at("b"), b);
auto result2 = MatchPattern(expr3, "a + (b * 10)", nullptr);
EXPECT_TRUE(result2.has_value());
EXPECT_EQ(result2->at("a"), a);
EXPECT_EQ(result2->at("b"), b);
auto result3 = MatchPattern(expr1, "a * b", nullptr);
EXPECT_FALSE(result3.has_value());
auto result4 = MatchPattern(expr3, "a + (b * 20)", nullptr);
EXPECT_FALSE(result4.has_value());
auto condition =
[](const std::unordered_map<std::string, ir::IndexExpr> &map) {
return map.at("a") == Expr(ir::Var("a")) &&
map.at("b") == Expr(ir::Var("b"));
};
auto result5 = MatchPattern(expr1, "a + b", condition);
EXPECT_TRUE(result5.has_value());
auto condition2 =
[](const std::unordered_map<std::string, ir::IndexExpr> &map) {
return map.at("a") == ir::Var("x") && map.at("b") == ir::Var("y");
};
auto result6 = MatchPattern(expr1, "a + b", condition2);
EXPECT_FALSE(result6.has_value());
auto result7 = MatchPattern(expr4, "(a + b) * 10", nullptr);
EXPECT_TRUE(result7.has_value());
EXPECT_EQ(result7->at("a"), a);
EXPECT_EQ(result7->at("b"), b);
auto result8 = MatchPattern(expr1, "x + y", nullptr);
EXPECT_TRUE(result8.has_value());
EXPECT_EQ(result8->at("x"), a);
EXPECT_EQ(result8->at("y"), b);
auto result9 = MatchPattern(expr6, "x * y", nullptr);
EXPECT_TRUE(result9.has_value());
EXPECT_EQ(result9->at("x"), x);
EXPECT_EQ(result9->at("y"), y);
}
TEST_F(TestIndexExpr, BoundSimplify) {
ir::Var S0 = ir::Var("S0");
ir::Var i = ir::Var(ir::Expr(0), ir::Expr(5), "i"); // i ∈ [0, 5)
ir::Var j = ir::Var(ir::Expr(0), S0, "j"); // j ∈ [0, S0)
ir::Expr q0 = i / Expr(5);
ir::Expr q1 = i / Expr(4);
ir::Expr q2 = i / Expr(6);
ir::Expr q3 = j / S0;
ir::Expr q4 = j / (S0 - 1);
ir::Expr q5 = j / (S0 + 1);
ir::Expr q6 = i % Expr(5);
ir::Expr q7 = i % Expr(4);
ir::Expr q8 = i % Expr(6);
ir::Expr q9 = j % S0;
ir::Expr q10 = j % (S0 - 1);
ir::Expr q11 = j % (S0 + 1);
EXPECT_EQ(q0.as_index().Normalize(ir::IndexExpr::OptLevel::kLevel3),
ir::Expr(0));
EXPECT_EQ(q1.as_index().Normalize(ir::IndexExpr::OptLevel::kLevel3),
i / Expr(4));
EXPECT_EQ(q2.as_index().Normalize(ir::IndexExpr::OptLevel::kLevel3),
ir::Expr(0));
EXPECT_EQ(q3.as_index().Normalize(ir::IndexExpr::OptLevel::kLevel3),
ir::Expr(0));
EXPECT_EQ(q4.as_index().Normalize(ir::IndexExpr::OptLevel::kLevel3),
j / (S0 + ir::Expr(-1)));
EXPECT_EQ(q5.as_index().Normalize(ir::IndexExpr::OptLevel::kLevel3),
ir::Expr(0));
EXPECT_EQ(q6.as_index().Normalize(ir::IndexExpr::OptLevel::kLevel3), i);
EXPECT_EQ(q7.as_index().Normalize(ir::IndexExpr::OptLevel::kLevel3),
i % Expr(4));
EXPECT_EQ(q8.as_index().Normalize(ir::IndexExpr::OptLevel::kLevel3), i);
EXPECT_EQ(q9.as_index().Normalize(ir::IndexExpr::OptLevel::kLevel3), j);
EXPECT_EQ(q10.as_index().Normalize(ir::IndexExpr::OptLevel::kLevel3),
j % (S0 + ir::Expr(-1)));
EXPECT_EQ(q11.as_index().Normalize(ir::IndexExpr::OptLevel::kLevel3), j);
}
} // namespace common
} // namespace cinn