3 #include "jitcs_instructionstream.h"
4 #include "jitcs_dumper.h"
5 #include "jitcs_int_dfg_analysis.h"
6 #include "jitcs_int_adt_dynslice.h"
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
);
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
53 host::MOV_RI32U(ibuf
, v1
, 0);
54 host::MOV_RI32U(ibuf
, v3
, 4);
55 host::JMP_FT(ibuf
, bb2
);
59 host::MOV_RI32U(ibuf
, v2
, 1);
60 host::CMP_RI(ibuf
, v1
, 5);
61 host::JGE_BB_FT(ibuf
, bb4
, bb3
);
65 host::ADD_RR(ibuf
, v1
, v2
);
66 host::JMP_BB(ibuf
, bb5
);
70 host::MOV_RI32U(ibuf
, v4
, 2);
71 host::ADD_RR(ibuf
, v1
, v4
);
72 host::JMP_FT(ibuf
, bb5
);
76 host::ADD_RI(ibuf
, v1
, 1);
77 host::CMP_RI(ibuf
, v1
, 100);
78 host::JB_BB_FT(ibuf
, bb2
, bb6
);
82 host::MOV_RR(ibuf
, host::EAX
, v3
);
86 DynSlice
<u32
,8> touchedFixed(mi
->details()->getResClassCount());
88 a
.init(reinterpret_cast<FunctionImpl
&>(*fn
), DFGAnalysis::M_Global
,
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
);