• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import { expect } from 'chai';
17import 'mocha';
18import * as ts from "typescript";
19import {
20    CallRange,
21    EcmaCallirangedyn,
22    EcmaReturnundefined,
23    EcmaStlettoglobalrecord,
24    EcmaTryldglobalbyname,
25    Imm,
26    IRNode,
27    LdaiDyn,
28    ResultType,
29    StaDyn,
30    VReg
31} from "../src/irnodes";
32import { PandaGen } from "../src/pandagen";
33import { CacheExpander } from "../src/pass/cacheExpander";
34import { RegAlloc } from "../src/regAllocator";
35import { basicChecker, checkInstructions, compileAllSnippet } from "./utils/base";
36
37
38function checkRegisterNumber(left: IRNode, right: IRNode): boolean {
39    if (!basicChecker(left, right)) {
40        return false;
41    }
42    let lo = left.operands;
43    let ro = right.operands;
44    if (lo.length !== ro.length) {
45        return false;
46    }
47    for (let i = 0; i < lo.length; ++i) {
48        let l = lo[i];
49        let r = ro[i];
50        if (l instanceof VReg && r instanceof VReg) {
51            if (!((<VReg>l).num == (<VReg>r).num)) {
52                return false;
53            }
54        }
55    }
56    return true;
57}
58describe("RegAllocator", function () {
59    it("make spill for Src register", function () {
60        let string: string = "";
61        for (let i = 0; i < 256; ++i) {
62            string += "let a" + i + " = " + i + ";";
63        }
64        string += "a255;";
65
66        let pgs = compileAllSnippet(string, [new CacheExpander(), new RegAlloc()]);
67        let insns = pgs[0].getInsns();
68
69        let expected: IRNode[] = [
70            new LdaiDyn(new Imm(252)),
71            new EcmaStlettoglobalrecord('a252'),
72            new LdaiDyn(new Imm(253)),
73            new EcmaStlettoglobalrecord('a253'),
74            new LdaiDyn(new Imm(254)),
75            new EcmaStlettoglobalrecord('a254'),
76            new LdaiDyn(new Imm(255)),
77            new EcmaStlettoglobalrecord('a255'),
78            new EcmaTryldglobalbyname('a255'),
79            new EcmaReturnundefined()
80        ]
81
82        expect(checkInstructions(insns.slice(insns.length - 10), expected, checkRegisterNumber)).to.be.true;
83    });
84
85    it("make spill for SrcDst register", function () {
86        /* the only possible instruction whose operand register type could be SrcDstVReg is INCI,
87         * but we do not use it at all by now
88         */
89        expect(true).to.be.true;
90    });
91
92    it("make spill for CalliDynRange", function () {
93        /* since the bitwidth for CalliDynRange source register is 16 now, we do not need to make spill at all.
94           but later 16 might be changed to 8, then spill operation will be needed in some cases. this testcase is designed
95           for 8bits constraints.
96        */
97        let string = "";
98        for (let i = 0; i < 256; ++i) {
99            string += "let a" + i + " = " + i + ";";
100        }
101        string += "call(a252, a253, a254, a255);";
102        let pgs = compileAllSnippet(string, [new CacheExpander(), new RegAlloc()]);
103        let insns = pgs[0].getInsns();
104        let v = [];
105        for (let i = 0; i < 8; ++i) {
106            v[i] = new VReg();
107            v[i].num = i;
108        }
109        let expected = [
110            new LdaiDyn(new Imm(252)),
111            new EcmaStlettoglobalrecord('a252'),
112            new LdaiDyn(new Imm(253)),
113            new EcmaStlettoglobalrecord('a253'),
114            new LdaiDyn(new Imm(254)),
115            new EcmaStlettoglobalrecord('a254'),
116            new LdaiDyn(new Imm(255)),
117            new EcmaStlettoglobalrecord('a255'),
118            new EcmaTryldglobalbyname('call'),
119            new StaDyn(v[3]),
120            new EcmaTryldglobalbyname('a252'),
121            new StaDyn(v[4]),
122            new EcmaTryldglobalbyname('a253'),
123            new StaDyn(v[5]),
124            new EcmaTryldglobalbyname('a254'),
125            new StaDyn(v[6]),
126            new EcmaTryldglobalbyname('a255'),
127            new StaDyn(v[7]),
128            new EcmaCallirangedyn(new Imm(4), [v[3],v[4],v[5],v[6],v[7]]),
129            new EcmaReturnundefined(),
130        ];
131        expect(checkInstructions(insns.slice(insns.length - 20), expected, checkRegisterNumber)).to.be.true;
132    });
133
134    it("VReg sequence of CalliDynRange is not continuous", function () {
135        let pandaGen = new PandaGen('', 0);
136
137        let para1 = pandaGen.getTemp();
138        let para2 = pandaGen.getTemp();
139        let para3 = pandaGen.getTemp();
140        let para4 = pandaGen.getTemp();
141        let para5 = pandaGen.getTemp();
142        let para6 = pandaGen.getTemp();
143
144        pandaGen.call(ts.createNode(0), [para1, para2, para3, para4, para5, para6], false);
145
146        pandaGen.freeTemps(para1, para3, para2);
147
148        try {
149            new RegAlloc().run(pandaGen);
150        } catch (err) {
151            expect(true).to.be.true;
152            return;
153        }
154        expect(true).to.be.false;
155    });
156
157    it("VReg sequence of DynRange is not continuous", function () {
158        let pandaGen = new PandaGen('', 0);
159
160        let para1 = pandaGen.getTemp();
161        let para2 = pandaGen.getTemp();
162        let para3 = pandaGen.getTemp();
163
164        pandaGen.getInsns().push(new CallRange('test', [para1, para2, para3]))
165
166        pandaGen.freeTemps(para1, para3, para2);
167
168        try {
169            new RegAlloc().run(pandaGen);
170        } catch (err) {
171            expect(true).to.be.true;
172            return;
173        }
174        expect(true).to.be.false;
175    });
176});
177