2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #include "hphp/runtime/vm/jit/irlower.h"
18 #include "hphp/runtime/vm/jit/irlower-internal.h"
20 #include "hphp/runtime/base/perf-warning.h"
21 #include "hphp/runtime/base/runtime-option.h"
22 #include "hphp/runtime/base/tracing.h"
24 #include "hphp/runtime/vm/jit/types.h"
25 #include "hphp/runtime/vm/jit/abi.h"
26 #include "hphp/runtime/vm/jit/cfg.h"
27 #include "hphp/runtime/vm/jit/containers.h"
28 #include "hphp/runtime/vm/jit/ir-instruction.h"
29 #include "hphp/runtime/vm/jit/ir-unit.h"
30 #include "hphp/runtime/vm/jit/print.h"
31 #include "hphp/runtime/vm/jit/punt.h"
32 #include "hphp/runtime/vm/jit/timer.h"
33 #include "hphp/runtime/vm/jit/vasm-emit.h"
34 #include "hphp/runtime/vm/jit/vasm-gen.h"
35 #include "hphp/runtime/vm/jit/vasm-print.h"
36 #include "hphp/runtime/vm/jit/vasm-unit.h"
38 #include "hphp/util/arch.h"
39 #include "hphp/util/assertions.h"
40 #include "hphp/util/trace.h"
42 #include <folly/Format.h>
43 #include <folly/Range.h>
47 namespace HPHP
{ namespace jit
{ namespace irlower
{
49 ///////////////////////////////////////////////////////////////////////////////
55 ///////////////////////////////////////////////////////////////////////////////
57 void cgInst(IRLS
& env
, const IRInstruction
* inst
){
58 SCOPE_ASSERT_DETAIL("cgInst") { return inst
->toString(); };
61 #define O(name, dsts, srcs, flags) \
63 FTRACE(7, "cg" #name "\n"); \
65 cg##name(env, inst); \
66 } catch (const Exception& e) { \
67 always_assert_flog(0, "Exception escaped from cg" #name ": {}", \
69 } catch (const std::exception& e) { \
70 always_assert_flog(0, "std::exception escaped from cg" #name ": {}", \
73 always_assert_flog(0, "unknown exception escaped from cg" #name); \
83 if (inst
->isBlockEnd() && !v
.closed()) {
84 if (auto const next
= inst
->next()) {
85 v
<< jmp
{label(env
, next
)};
87 v
<< trap
{TRAP_REASON
}; // or end?
93 * Lower `block' from HHIR to vasm.
95 void genBlock(IRLS
& env
, Vout
& v
, Vout
& vc
, Block
& block
) {
96 FTRACE(6, "genBlock: {}\n", block
.id());
101 for (auto& inst
: block
) {
102 v
.unit().cur_voff
= 0;
109 void optimize(Vunit
& unit
, CodeKind kind
, bool regAlloc
) {
110 auto const abi
= jit::abi(kind
);
113 optimizeX64(unit
, abi
, regAlloc
);
116 optimizeARM(unit
, abi
, regAlloc
);
119 optimizePPC64(unit
, abi
, regAlloc
);
126 ///////////////////////////////////////////////////////////////////////////////
128 std::unique_ptr
<Vunit
> lowerUnit(const IRUnit
& unit
,
130 bool regAlloc
/* = true */) noexcept
{
131 Timer
timer(Timer::hhir_lower
, unit
.logEntry().get_pointer());
136 return traceProps(unit
)
137 .add("code_kind", codeKindAsString(kind
))
138 .add("reg_alloc", regAlloc
);
142 rqtrace::EventGuard trace
{"VLOWER"};
143 SCOPE_ASSERT_DETAIL("hhir unit") { return show(unit
); };
145 auto vunit
= std::make_unique
<Vunit
>();
146 vunit
->context
= unit
.context();
147 vunit
->log_entry
= unit
.logEntry().get_pointer();
148 vunit
->profiling
= true;
150 SCOPE_ASSERT_DETAIL("vasm unit") { return show(*vunit
); };
153 auto const blocks
= rpoSortCfg(unit
);
155 // Create the initial set of vasm blocks, numbered the same as the
156 // corresponding HHIR blocks.
157 // We initially create the blocks with 0 weight, and then set them below.
158 for (uint32_t i
= 0, n
= unit
.numBlocks(); i
< n
; ++i
) {
159 env
.labels
[i
] = vunit
->makeBlock(AreaIndex::Main
, 0);
161 vunit
->entry
= env
.labels
[unit
.entry()];
163 // Create Vregs for all relevant SSATmps.
164 assignRegs(unit
, *vunit
, env
, blocks
);
166 for (auto block
: blocks
) {
167 auto& v
= block
->hint() == Block::Hint::Unlikely
? vasm
.cold() :
168 block
->hint() == Block::Hint::Unused
? vasm
.frozen() :
170 FTRACE(6, "genBlock {} on {}\n", block
->id(),
171 area_names
[(unsigned)v
.area()]);
173 auto b
= env
.labels
[block
];
174 vunit
->blocks
[b
].area_idx
= v
.area();
175 vunit
->blocks
[b
].weight
= block
->profCount() * areaWeightFactor(v
.area());
179 block
->hint() == Block::Hint::Unused
? vasm
.frozen() : vasm
.cold();
181 if (block
== unit
.entry() && kind
== CodeKind::Trace
) {
182 v
<< recordbasenativesp
{};
184 genBlock(env
, v
, vcold
, *block
);
187 assertx(vasm
.main().empty() || vasm
.main().closed());
188 assertx(vasm
.cold().empty() || vasm
.cold().closed());
189 assertx(vasm
.frozen().empty() || vasm
.frozen().closed());
192 fixBlockWeights(*vunit
);
194 // This pass requires on some invariants about rvmfp() from HHIR, so we do it
195 // here rather than in optimize() as those optimizations may be called for non
197 fixupVmfpUses(*vunit
);
199 printUnit(kInitialVasmLevel
, "after initial vasm generation", *vunit
);
200 assertx(check(*vunit
));
205 optimize(*vunit
, kind
, regAlloc
);
206 } catch (const FailedTraceGen
& e
) {
207 // vasm-xls can fail if it tries to allocate too many spill slots.
208 tracing::addPoint("vasm-optimize punt");
209 logLowPriPerfWarning(
210 "vasm-optimize punt",
212 [&](StructuredLogEntry
& cols
) {
213 cols
.setStr("punt_type", e
.what());
214 cols
.setStr("vasm_unit", show(*vunit
));
217 FTRACE(1, "vasm-optimize failed with {}\n", e
.what());
224 Vcost
computeIRUnitCost(const IRUnit
& unit
) {
225 auto vunit
= lowerUnit(unit
, CodeKind::Trace
, false /* regAlloc */);
226 if (RuntimeOption::EvalHHIRInliningUseLayoutBlocks
) {
227 layoutBlocks(*vunit
);
229 return computeVunitCost(*vunit
);
233 ///////////////////////////////////////////////////////////////////////////////