1b1994897Sopenharmony_ci/**
2b1994897Sopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3b1994897Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4b1994897Sopenharmony_ci * you may not use this file except in compliance with the License.
5b1994897Sopenharmony_ci * You may obtain a copy of the License at
6b1994897Sopenharmony_ci *
7b1994897Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
8b1994897Sopenharmony_ci *
9b1994897Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10b1994897Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11b1994897Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12b1994897Sopenharmony_ci * See the License for the specific language governing permissions and
13b1994897Sopenharmony_ci * limitations under the License.
14b1994897Sopenharmony_ci */
15b1994897Sopenharmony_ci
16b1994897Sopenharmony_ci#ifndef COMPILER_OPTIMIZER_OPTIMIZATIONS_VN_H
17b1994897Sopenharmony_ci#define COMPILER_OPTIMIZER_OPTIMIZATIONS_VN_H
18b1994897Sopenharmony_ci
19b1994897Sopenharmony_ci#include <unordered_map>
20b1994897Sopenharmony_ci#include <array>
21b1994897Sopenharmony_ci#include "utils/hash.h"
22b1994897Sopenharmony_ci#include "optimizer/pass.h"
23b1994897Sopenharmony_ci
24b1994897Sopenharmony_cinamespace panda::compiler {
25b1994897Sopenharmony_ciclass Inst;
26b1994897Sopenharmony_ciclass VnObject;
27b1994897Sopenharmony_ciclass Graph;
28b1994897Sopenharmony_ci
29b1994897Sopenharmony_ciclass VnObject {
30b1994897Sopenharmony_cipublic:
31b1994897Sopenharmony_ci    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
32b1994897Sopenharmony_ci    explicit VnObject()
33b1994897Sopenharmony_ci    {
34b1994897Sopenharmony_ci        for (uint8_t i = 0; i < MAX_ARRAY_SIZE; i++) {
35b1994897Sopenharmony_ci            objs_[i] = 0;
36b1994897Sopenharmony_ci        }
37b1994897Sopenharmony_ci    }
38b1994897Sopenharmony_ci    NO_MOVE_SEMANTIC(VnObject);
39b1994897Sopenharmony_ci    NO_COPY_SEMANTIC(VnObject);
40b1994897Sopenharmony_ci    ~VnObject() = default;
41b1994897Sopenharmony_ci
42b1994897Sopenharmony_ci    void Add(Inst *inst);
43b1994897Sopenharmony_ci    void Add(uint32_t obj);
44b1994897Sopenharmony_ci    void Add(uint64_t obj);
45b1994897Sopenharmony_ci    bool Compare(VnObject *obj);
46b1994897Sopenharmony_ci    uint32_t GetSize() const
47b1994897Sopenharmony_ci    {
48b1994897Sopenharmony_ci        return size_objs_;
49b1994897Sopenharmony_ci    }
50b1994897Sopenharmony_ci    uint64_t GetElement(uint32_t index) const
51b1994897Sopenharmony_ci    {
52b1994897Sopenharmony_ci        ASSERT(index < size_objs_);
53b1994897Sopenharmony_ci        return objs_[index];
54b1994897Sopenharmony_ci    }
55b1994897Sopenharmony_ci    uint32_t *GetArray()
56b1994897Sopenharmony_ci    {
57b1994897Sopenharmony_ci        return objs_.data();
58b1994897Sopenharmony_ci    }
59b1994897Sopenharmony_ci
60b1994897Sopenharmony_ciprivate:
61b1994897Sopenharmony_ci    uint8_t size_objs_ {0};
62b1994897Sopenharmony_ci    // opcode, type, 2 inputs, 2 advanced property
63b1994897Sopenharmony_ci    static constexpr uint8_t MAX_ARRAY_SIZE = 6;
64b1994897Sopenharmony_ci    std::array<uint32_t, MAX_ARRAY_SIZE> objs_;
65b1994897Sopenharmony_ci};
66b1994897Sopenharmony_ci
67b1994897Sopenharmony_cistruct VnObjEqual {
68b1994897Sopenharmony_ci    bool operator()(VnObject *obj1, VnObject *obj2) const
69b1994897Sopenharmony_ci    {
70b1994897Sopenharmony_ci        return obj1->Compare(obj2);
71b1994897Sopenharmony_ci    }
72b1994897Sopenharmony_ci};
73b1994897Sopenharmony_ci
74b1994897Sopenharmony_cistruct VnObjHash {
75b1994897Sopenharmony_ci    uint32_t operator()(VnObject *obj) const
76b1994897Sopenharmony_ci    {
77b1994897Sopenharmony_ci        return GetHash32(reinterpret_cast<const uint8_t *>(obj->GetArray()), obj->GetSize());
78b1994897Sopenharmony_ci    }
79b1994897Sopenharmony_ci};
80b1994897Sopenharmony_ci
81b1994897Sopenharmony_ci/*
82b1994897Sopenharmony_ci * Optimization assigns numbers(named vn) to all instructions.
83b1994897Sopenharmony_ci * Equivalent instructions have equivalent vn.
84b1994897Sopenharmony_ci * If instruction A dominates B and they have equivalent vn, users B are moved to A and DCE removes B at the end.
85b1994897Sopenharmony_ci * The instruction with the property NO_CSE has unique vn and they can't be removed.
86b1994897Sopenharmony_ci * The optimization creates VnObject for instruction without NO_CSE.
87b1994897Sopenharmony_ci * The VnObject is key for the instruction.
88b1994897Sopenharmony_ci * The unordered_map is used for searching equivalent instruction by the key(VnObject).
89b1994897Sopenharmony_ci */
90b1994897Sopenharmony_ciclass ValNum : public Optimization {
91b1994897Sopenharmony_cipublic:
92b1994897Sopenharmony_ci    explicit ValNum(Graph *graph);
93b1994897Sopenharmony_ci    NO_MOVE_SEMANTIC(ValNum);
94b1994897Sopenharmony_ci    NO_COPY_SEMANTIC(ValNum);
95b1994897Sopenharmony_ci    ~ValNum() override = default;
96b1994897Sopenharmony_ci
97b1994897Sopenharmony_ci    bool RunImpl() override;
98b1994897Sopenharmony_ci
99b1994897Sopenharmony_ci    const char *GetPassName() const override
100b1994897Sopenharmony_ci    {
101b1994897Sopenharmony_ci        return "GVN";
102b1994897Sopenharmony_ci    }
103b1994897Sopenharmony_ci
104b1994897Sopenharmony_ci    bool IsEnable() const override
105b1994897Sopenharmony_ci    {
106b1994897Sopenharmony_ci        return options.IsCompilerVn();
107b1994897Sopenharmony_ci    }
108b1994897Sopenharmony_ci
109b1994897Sopenharmony_ci    void InvalidateAnalyses() override;
110b1994897Sopenharmony_ci
111b1994897Sopenharmony_ci    void FindEqualVnOrCreateNew(Inst *inst);
112b1994897Sopenharmony_ci
113b1994897Sopenharmony_ciprivate:
114b1994897Sopenharmony_ci    using InstVector = ArenaVector<Inst *>;
115b1994897Sopenharmony_ci
116b1994897Sopenharmony_ci    // Sets vn for the inst
117b1994897Sopenharmony_ci    void SetInstValNum(Inst *inst);
118b1994897Sopenharmony_ci
119b1994897Sopenharmony_ci    bool TryToApplyCse(Inst *inst, InstVector *equiv_insts);
120b1994897Sopenharmony_ci
121b1994897Sopenharmony_ci    // !TODO add own allocator
122b1994897Sopenharmony_ci    ArenaUnorderedMap<VnObject *, InstVector, VnObjHash, VnObjEqual> map_insts_;
123b1994897Sopenharmony_ci
124b1994897Sopenharmony_ci    uint32_t curr_vn_ {0};
125b1994897Sopenharmony_ci    bool cse_is_appied_ {false};
126b1994897Sopenharmony_ci};
127b1994897Sopenharmony_ci}  // namespace panda::compiler
128b1994897Sopenharmony_ci
129b1994897Sopenharmony_ci#endif  // COMPILER_OPTIMIZER_OPTIMIZATIONS_VN_H
130