14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License.
54514f5e3Sopenharmony_ci * You may obtain a copy of the License at
64514f5e3Sopenharmony_ci *
74514f5e3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
84514f5e3Sopenharmony_ci *
94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and
134514f5e3Sopenharmony_ci * limitations under the License.
144514f5e3Sopenharmony_ci */
154514f5e3Sopenharmony_ci
164514f5e3Sopenharmony_ci#ifndef ECMASCRIPT_COMPILER_ARRAY_BOUNDS_CHECK_ELIMINATION_H
174514f5e3Sopenharmony_ci#define ECMASCRIPT_COMPILER_ARRAY_BOUNDS_CHECK_ELIMINATION_H
184514f5e3Sopenharmony_ci
194514f5e3Sopenharmony_ci#include "ecmascript/compiler/circuit_builder.h"
204514f5e3Sopenharmony_ci#include "ecmascript/compiler/mcr_gate_meta_data.h"
214514f5e3Sopenharmony_ci#include "ecmascript/compiler/gate_accessor.h"
224514f5e3Sopenharmony_ci#include "ecmascript/compiler/graph_linearizer.h"
234514f5e3Sopenharmony_ci#include "ecmascript/compiler/pass_manager.h"
244514f5e3Sopenharmony_ci#include "ecmascript/mem/chunk_containers.h"
254514f5e3Sopenharmony_ci
264514f5e3Sopenharmony_cinamespace panda::ecmascript::kungfu {
274514f5e3Sopenharmony_ciclass ArrayBoundsCheckElimination {
284514f5e3Sopenharmony_cipublic:
294514f5e3Sopenharmony_ci    ArrayBoundsCheckElimination(Circuit *circuit, bool enableLog, const std::string& name, Chunk* chunk)
304514f5e3Sopenharmony_ci        : acc_(circuit), bounds_(chunk), circuit_(circuit), builder_(circuit), chunk_(chunk), enableLog_(enableLog),
314514f5e3Sopenharmony_ci        graphLinearizer_(circuit, enableLog, name, chunk, true, true), methodName_(name), indexCheckInfo_(chunk) {}
324514f5e3Sopenharmony_ci
334514f5e3Sopenharmony_ci    ~ArrayBoundsCheckElimination() = default;
344514f5e3Sopenharmony_ci    void Run();
354514f5e3Sopenharmony_ci
364514f5e3Sopenharmony_ciprivate:
374514f5e3Sopenharmony_ci    class Bound {
384514f5e3Sopenharmony_ci    public:
394514f5e3Sopenharmony_ci        Bound();
404514f5e3Sopenharmony_ci        explicit Bound(GateRef v);
414514f5e3Sopenharmony_ci        Bound(int lower, GateRef lowerGate, int upper, GateRef upperGate);
424514f5e3Sopenharmony_ci        Bound(TypedBinOp op, GateRef gate, int constant);
434514f5e3Sopenharmony_ci        ~Bound(){};
444514f5e3Sopenharmony_ci
454514f5e3Sopenharmony_ci        int Upper()
464514f5e3Sopenharmony_ci        {
474514f5e3Sopenharmony_ci            return upper_;
484514f5e3Sopenharmony_ci        }
494514f5e3Sopenharmony_ci
504514f5e3Sopenharmony_ci        GateRef UpperGate()
514514f5e3Sopenharmony_ci        {
524514f5e3Sopenharmony_ci            return upperGate_;
534514f5e3Sopenharmony_ci        }
544514f5e3Sopenharmony_ci
554514f5e3Sopenharmony_ci        int Lower()
564514f5e3Sopenharmony_ci        {
574514f5e3Sopenharmony_ci            return lower_;
584514f5e3Sopenharmony_ci        }
594514f5e3Sopenharmony_ci
604514f5e3Sopenharmony_ci        GateRef LowerGate()
614514f5e3Sopenharmony_ci        {
624514f5e3Sopenharmony_ci            return lowerGate_;
634514f5e3Sopenharmony_ci        }
644514f5e3Sopenharmony_ci
654514f5e3Sopenharmony_ci        bool HasUpper()
664514f5e3Sopenharmony_ci        {
674514f5e3Sopenharmony_ci            return upperGate_ != Circuit::NullGate() || upper_ < INT_MAX;
684514f5e3Sopenharmony_ci        }
694514f5e3Sopenharmony_ci
704514f5e3Sopenharmony_ci        bool HasLower()
714514f5e3Sopenharmony_ci        {
724514f5e3Sopenharmony_ci            return lowerGate_ != Circuit::NullGate() || lower_ > INT_MIN;
734514f5e3Sopenharmony_ci        }
744514f5e3Sopenharmony_ci
754514f5e3Sopenharmony_ci        void RemoveUpper()
764514f5e3Sopenharmony_ci        {
774514f5e3Sopenharmony_ci            upperGate_ = Circuit::NullGate();
784514f5e3Sopenharmony_ci            upper_ = INT_MAX;
794514f5e3Sopenharmony_ci        }
804514f5e3Sopenharmony_ci
814514f5e3Sopenharmony_ci        void RemoveLower()
824514f5e3Sopenharmony_ci        {
834514f5e3Sopenharmony_ci            lowerGate_ = Circuit::NullGate();
844514f5e3Sopenharmony_ci            lower_ = INT_MIN;
854514f5e3Sopenharmony_ci        }
864514f5e3Sopenharmony_ci
874514f5e3Sopenharmony_ci        bool IsSmaller(Bound *b)
884514f5e3Sopenharmony_ci        {
894514f5e3Sopenharmony_ci            if (b->LowerGate() != upperGate_) {
904514f5e3Sopenharmony_ci                return false;
914514f5e3Sopenharmony_ci            }
924514f5e3Sopenharmony_ci            return upper_ < b->Lower();
934514f5e3Sopenharmony_ci        }
944514f5e3Sopenharmony_ci
954514f5e3Sopenharmony_ci        Bound* Copy(Chunk *chunk)
964514f5e3Sopenharmony_ci        {
974514f5e3Sopenharmony_ci            return chunk->New<Bound>(lower_, lowerGate_, upper_, upperGate_);
984514f5e3Sopenharmony_ci        }
994514f5e3Sopenharmony_ci
1004514f5e3Sopenharmony_ci    private:
1014514f5e3Sopenharmony_ci        int upper_ = 0;
1024514f5e3Sopenharmony_ci        GateRef upperGate_ {Circuit::NullGate()};
1034514f5e3Sopenharmony_ci        int lower_ = 0;
1044514f5e3Sopenharmony_ci        GateRef lowerGate_ {Circuit::NullGate()};
1054514f5e3Sopenharmony_ci
1064514f5e3Sopenharmony_ci        friend ArrayBoundsCheckElimination;
1074514f5e3Sopenharmony_ci    };
1084514f5e3Sopenharmony_ci
1094514f5e3Sopenharmony_ci    bool IsLogEnabled() const
1104514f5e3Sopenharmony_ci    {
1114514f5e3Sopenharmony_ci        return enableLog_;
1124514f5e3Sopenharmony_ci    }
1134514f5e3Sopenharmony_ci
1144514f5e3Sopenharmony_ci    const std::string& GetMethodName() const
1154514f5e3Sopenharmony_ci    {
1164514f5e3Sopenharmony_ci        return methodName_;
1174514f5e3Sopenharmony_ci    }
1184514f5e3Sopenharmony_ci
1194514f5e3Sopenharmony_ci    typedef ChunkVector<Bound*> BoundStack;
1204514f5e3Sopenharmony_ci    typedef ChunkVector<BoundStack*> BoundMap;
1214514f5e3Sopenharmony_ci    typedef ChunkVector<int> IntegerStack;
1224514f5e3Sopenharmony_ci    typedef ChunkVector<GateRef> GateLists;
1234514f5e3Sopenharmony_ci
1244514f5e3Sopenharmony_ci    void AddAccessIndexedInfo(GateLists &indices, GateRef gate, int idx, GateRef indexCheck);
1254514f5e3Sopenharmony_ci    void AddIfCondition(IntegerStack &pushed, GateRef x, GateRef y, TypedBinOp op);
1264514f5e3Sopenharmony_ci    Bound *AndOp(Bound *bound, Bound *b);
1274514f5e3Sopenharmony_ci    Bound *OrOp(Bound *bound, Bound *b);
1284514f5e3Sopenharmony_ci    bool Contain(GateLists &gateLists, GateRef gate);
1294514f5e3Sopenharmony_ci    void CalcBounds(GateRegion *block, GateRegion *loopHeader);
1304514f5e3Sopenharmony_ci    bool CheckLoop(GateRef array, GateRef lowerGate, int lower, GateRef upperGate, int upper);
1314514f5e3Sopenharmony_ci    GateRef FindBoundGate(GateRef gate);
1324514f5e3Sopenharmony_ci    void InBlockMotion(GateLists &indexChecked, GateLists &arrays);
1334514f5e3Sopenharmony_ci    bool InLoop(GateRef loopHeader, GateRef gate);
1344514f5e3Sopenharmony_ci    bool IsArrayLength(GateRef gate);
1354514f5e3Sopenharmony_ci    bool LoopInvariant(GateRegion *loopHeader, GateRef gate);
1364514f5e3Sopenharmony_ci    void UpdateBound(IntegerStack &pushed, GateRef gate, Bound *bound);
1374514f5e3Sopenharmony_ci    void UpdateBound(IntegerStack &pushed, GateRef x, TypedBinOp op, GateRef y, int constValue);
1384514f5e3Sopenharmony_ci    void ProcessIndexCheck(GateRegion *loopHeader, GateRef gate);
1394514f5e3Sopenharmony_ci    void RemoveIndexCheck(GateRef gate);
1404514f5e3Sopenharmony_ci    void CopyStateInAndDependIn(GateRef &stateIn, GateRef &dependIn, GateRef insertAfter);
1414514f5e3Sopenharmony_ci    void LoopInvariantMotionForIndexCheck(GateRef array, GateRef length, GateRef lengthMetaData,
1424514f5e3Sopenharmony_ci        GateRef lowerGate, int lower, GateRef upperGate, int upper, bool isTypedArray);
1434514f5e3Sopenharmony_ci    bool GetInstrAndConstValueFromUnaryOp(GateRef gate, GateRef &other, int& value);
1444514f5e3Sopenharmony_ci    bool GetInstrAndConstValueFromBinaryOp(GateRef gate, GateRef &other, int& value);
1454514f5e3Sopenharmony_ci    void GetInstrAndConstValueFromOp(GateRef gate, GateRef &instrValue, int& constValue);
1464514f5e3Sopenharmony_ci    Bound *GetBound(GateRef gate);
1474514f5e3Sopenharmony_ci    Bound *DoConstant(GateRef gate);
1484514f5e3Sopenharmony_ci    Bound *DoBinaryArithmeticOp(GateRef gate);
1494514f5e3Sopenharmony_ci    Bound *DoUnaryArithmeticOp(GateRef gate);
1504514f5e3Sopenharmony_ci    Bound *DoPhi(GateRef gate);
1514514f5e3Sopenharmony_ci    void SetBound(GateRef gate, Bound *bound);
1524514f5e3Sopenharmony_ci    void ProcessIf(IntegerStack &pushed, GateRegion *parent, OpCode cond);
1534514f5e3Sopenharmony_ci    bool InArrayBound(Bound *bound, GateRef length, GateRef array);
1544514f5e3Sopenharmony_ci    Bound *VisitGate(GateRef gate);
1554514f5e3Sopenharmony_ci
1564514f5e3Sopenharmony_ci    void ReplaceIn(GateRef stateIn, GateRef dependIn, GateRef newGate);
1574514f5e3Sopenharmony_ci
1584514f5e3Sopenharmony_ci    GateRef Predicate(GateRef left, TypedBinOp cond, GateRef right);
1594514f5e3Sopenharmony_ci    GateRef PredicateCmpWithConst(GateRef left, TypedBinOp cond, int right);
1604514f5e3Sopenharmony_ci    GateRef PredicateAdd(GateRef left, int leftConst, TypedBinOp cond, GateRef right);
1614514f5e3Sopenharmony_ci    GateRef PredicateAddCmpWithConst(GateRef left, int leftConst, TypedBinOp cond, int right);
1624514f5e3Sopenharmony_ci
1634514f5e3Sopenharmony_ci    GateAccessor acc_;
1644514f5e3Sopenharmony_ci    BoundMap bounds_;
1654514f5e3Sopenharmony_ci    Circuit *circuit_ {nullptr};
1664514f5e3Sopenharmony_ci    CircuitBuilder builder_;
1674514f5e3Sopenharmony_ci    Chunk *chunk_ {nullptr};
1684514f5e3Sopenharmony_ci    bool enableLog_ {false};
1694514f5e3Sopenharmony_ci    GraphLinearizer graphLinearizer_;
1704514f5e3Sopenharmony_ci    std::string methodName_;
1714514f5e3Sopenharmony_ci
1724514f5e3Sopenharmony_ci    class IndexCheckInfo {
1734514f5e3Sopenharmony_ci    public:
1744514f5e3Sopenharmony_ci        IndexCheckInfo(Chunk* chunk): list_(chunk) {}
1754514f5e3Sopenharmony_ci        GateLists list_;
1764514f5e3Sopenharmony_ci        int min_ {0};
1774514f5e3Sopenharmony_ci        int max_ {0};
1784514f5e3Sopenharmony_ci    };
1794514f5e3Sopenharmony_ci    typedef ChunkVector<IndexCheckInfo*> IndexCheckInfoList;
1804514f5e3Sopenharmony_ci    IndexCheckInfoList indexCheckInfo_;
1814514f5e3Sopenharmony_ci};
1824514f5e3Sopenharmony_ci}
1834514f5e3Sopenharmony_ci#endif