Fixed SOME wrong DF-annotations (e.g. ADD_WW had only "def" for the dest
[jitcs.git] / tests / test_dfg_analysis.cpp
blob6fa096ef020d5e3cce5ff4de25ddffb70a5f7b3c
1 #include "jitcs_int.h"
2 #include "unittest.h"
3 #include "jitcs_instructionstream.h"
4 #include "jitcs_dumper.h"
5 #include "jitcs_int_dfg_analysis.h"
6 #include "jitcs_int_adt_dynslice.h"
8 using namespace jitcs;
10 static void test(UnitTest& t) {
11 typedef void (__cdecl *FT0_c)();
12 RefCounter<IMachineInfo> mi = host::GetMachineInfo();
13 RefCounter<TempAllocator> alloc(new TempAllocator);
15 std::unique_ptr<Function> fn = mi->createFnc<FT0_c>(alloc);
16 InstructionStreamBuffer<256> ibuf;
18 Ref<BasicBlock> bb1 = fn->getStartBlock();
19 Ref<BasicBlock> bb2 = fn->createBasicBlock();
20 Ref<BasicBlock> bb3 = fn->createBasicBlock();
21 Ref<BasicBlock> bb4 = fn->createBasicBlock();
22 Ref<BasicBlock> bb5 = fn->createBasicBlock();
23 Ref<BasicBlock> bb6 = fn->createBasicBlock();
24 Ref<const VirtualRegister> v1 = fn->createRegister(host::RCL_GR);
25 Ref<const VirtualRegister> v2 = fn->createRegister(host::RCL_GR);
26 Ref<const VirtualRegister> v3 = fn->createRegister(host::RCL_GR);
27 Ref<const VirtualRegister> v4 = fn->createRegister(host::RCL_GR);
29 // BB1(entry)
30 // |
31 // v
32 // BB2 <------.
33 // |---. |
34 // v v |
35 // BB3 BB4 |
36 // |---. |
37 // v |
38 // BB5 |
39 // |---------.
40 // v
41 // BB6
42 // |
43 // v
44 // BB7 (exit)
46 // v1: induction variable, defined in BB1, used in BB5,
47 // live thru-out the loop
48 // v2: defined in BB2, used in BB3, not live in any other BB
49 // v3: defined in BB1, used in BB6, live thru-out the loop
50 // v3: defined and used in BB4, not live anywhere else
52 ibuf.start(bb1);
53 host::MOV_RI32U(ibuf, v1, 0);
54 host::MOV_RI32U(ibuf, v3, 4);
55 host::JMP_FT(ibuf, bb2);
56 ibuf.end();
58 ibuf.start(bb2);
59 host::MOV_RI32U(ibuf, v2, 1);
60 host::CMP_RI(ibuf, v1, 5);
61 host::JGE_BB_FT(ibuf, bb4, bb3);
62 ibuf.end();
64 ibuf.start(bb3);
65 host::ADD_RR(ibuf, v1, v2);
66 host::JMP_BB(ibuf, bb5);
67 ibuf.end();
69 ibuf.start(bb4);
70 host::MOV_RI32U(ibuf, v4, 2);
71 host::ADD_RR(ibuf, v1, v4);
72 host::JMP_FT(ibuf, bb5);
73 ibuf.end();
75 ibuf.start(bb5);
76 host::ADD_RI(ibuf, v1, 1);
77 host::CMP_RI(ibuf, v1, 100);
78 host::JB_BB_FT(ibuf, bb2, bb6);
79 ibuf.end();
81 ibuf.start(bb6);
82 host::MOV_RR(ibuf, host::EAX, v3);
83 host::RET(ibuf);
84 ibuf.end();
86 DynSlice<u32,8> touchedFixed(mi->details()->getResClassCount());
87 DFGAnalysis a;
88 a.init(reinterpret_cast<FunctionImpl&>(*fn), DFGAnalysis::M_Global,
89 touchedFixed);
91 t.check("v1/bb1/use", !a.isUsed(bb1, v1));
92 t.check("v1/bb1/def", a.isDefined(bb1, v1));
93 t.check("v1/bb1/live-in", !a.isLiveIn(bb1, v1));
94 t.check("v1/bb1/live-out", a.isLiveOut(bb1, v1));
96 t.check("v1/bb2/use", a.isUsed(bb2, v1));
97 t.check("v1/bb2/def", !a.isDefined(bb2, v1));
98 t.check("v1/bb2/live-in", a.isLiveIn(bb2, v1));
99 t.check("v1/bb2/live-out", a.isLiveOut(bb2, v1));
101 t.check("v1/bb3/use", a.isUsed(bb3, v1));
102 t.check("v1/bb3/def", a.isDefined(bb3, v1));
103 t.check("v1/bb3/live-in", a.isLiveIn(bb3, v1));
104 t.check("v1/bb3/live-out", a.isLiveOut(bb3, v1));
106 t.check("v1/bb4/use", a.isUsed(bb4, v1));
107 t.check("v1/bb4/def", a.isDefined(bb4, v1));
108 t.check("v1/bb4/live-in", a.isLiveIn(bb4, v1));
109 t.check("v1/bb4/live-out", a.isLiveOut(bb4, v1));
111 t.check("v1/bb5/use", a.isUsed(bb5, v1));
112 t.check("v1/bb5/def", a.isDefined(bb5, v1));
113 t.check("v1/bb5/live-in", a.isLiveIn(bb5, v1));
114 t.check("v1/bb5/live-out", a.isLiveOut(bb5, v1));
116 t.check("v1/bb6/use", !a.isUsed(bb6, v1));
117 t.check("v1/bb6/def", !a.isDefined(bb6, v1));
118 t.check("v1/bb6/live-in", !a.isLiveIn(bb6, v1));
119 t.check("v1/bb6/live-out", !a.isLiveOut(bb6, v1));
121 t.check("v2/bb2/use", !a.isUsed(bb2, v2));
122 t.check("v2/bb2/def", a.isDefined(bb2, v2));
123 t.check("v2/bb2/live-in", !a.isLiveIn(bb2, v2));
124 t.check("v2/bb2/live-out", a.isLiveOut(bb2, v2));
126 t.check("v2/bb3/use", a.isUsed(bb3, v2));
127 t.check("v2/bb3/def", !a.isDefined(bb3, v2));
128 t.check("v2/bb3/live-in", a.isLiveIn(bb3, v2));
129 t.check("v2/bb3/live-out", !a.isLiveOut(bb3, v2));
131 t.check("v2/bb4/use", !a.isUsed(bb4, v2));
132 t.check("v2/bb4/def", !a.isDefined(bb4, v2));
133 t.check("v2/bb4/live-in", !a.isLiveIn(bb4, v2));
134 t.check("v2/bb4/live-out", !a.isLiveOut(bb4, v2));
136 t.check("v2/bb5/use", !a.isUsed(bb5, v2));
137 t.check("v2/bb5/def", !a.isDefined(bb5, v2));
138 t.check("v2/bb5/live-in", !a.isLiveIn(bb5, v2));
139 t.check("v2/bb5/live-out", !a.isLiveOut(bb5, v2));
141 t.check("v3/bb1/use", !a.isUsed(bb1, v3));
142 t.check("v3/bb1/def", a.isDefined(bb1, v3));
143 t.check("v3/bb1/live-in", !a.isLiveIn(bb1, v3));
144 t.check("v3/bb1/live-out", a.isLiveOut(bb1, v3));
146 t.check("v3/bb2/use", !a.isUsed(bb2, v3));
147 t.check("v3/bb2/def", !a.isDefined(bb2, v3));
148 t.check("v3/bb2/live-in", a.isLiveIn(bb2, v3));
149 t.check("v3/bb2/live-out", a.isLiveOut(bb2, v3));
151 t.check("v3/bb5/use", !a.isUsed(bb5, v3));
152 t.check("v3/bb5/def", !a.isDefined(bb5, v3));
153 t.check("v3/bb5/live-in", a.isLiveIn(bb5, v3));
154 t.check("v3/bb5/live-out", a.isLiveOut(bb5, v3));
156 t.check("v3/bb6/use", a.isUsed(bb6, v3));
157 t.check("v3/bb6/def", !a.isDefined(bb6, v3));
158 t.check("v3/bb6/live-in", a.isLiveIn(bb6, v3));
159 t.check("v3/bb6/live-out", !a.isLiveOut(bb6, v3));
161 t.check("v4/bb4/use", !a.isUsed(bb4, v4));
162 t.check("v4/bb4/def", a.isDefined(bb4, v4));
163 t.check("v4/bb4/live-in", !a.isLiveIn(bb4, v4));
164 t.check("v4/bb4/live-out", !a.isLiveOut(bb4, v4));
166 u32 d = host::ResClassInfoCT<host::RESCL_GRRSC>::RES_Idx;
167 u32 tf_gr = touchedFixed[host::RESCL_GRRSC];
168 t.check("fixed/eax", (tf_gr & (1 << (host::RegInfoCT<host::R_EAX>::RES_Id - d))) != 0);
169 t.check("fixed/edx", (tf_gr & (1 << (host::RegInfoCT<host::R_EDX>::RES_Id - d))) == 0);
173 static UnitTestRun _("DFG Analysis", test);