5 #include "src/compiler/backend/jump-threading.h" 6 #include "src/compiler/backend/code-generator-impl.h" 14 if (FLAG_trace_turbo_jt) PrintF(__VA_ARGS__); \ 19 struct JumpThreadingState {
21 ZoneVector<RpoNumber>& result;
22 ZoneStack<RpoNumber>& stack;
24 void Clear(
size_t count) { result.assign(count, unvisited()); }
25 void PushIfUnvisited(RpoNumber num) {
26 if (result[num.ToInt()] == unvisited()) {
28 result[num.ToInt()] = onstack();
31 void Forward(RpoNumber to) {
32 RpoNumber from = stack.top();
33 RpoNumber to_to = result[to.ToInt()];
36 TRACE(
" xx %d\n", from.ToInt());
37 result[from.ToInt()] = from;
38 }
else if (to_to == unvisited()) {
39 TRACE(
" fw %d -> %d (recurse)\n", from.ToInt(), to.ToInt());
41 result[to.ToInt()] = onstack();
43 }
else if (to_to == onstack()) {
44 TRACE(
" fw %d -> %d (cycle)\n", from.ToInt(), to.ToInt());
45 result[from.ToInt()] = to;
48 TRACE(
" fw %d -> %d (forward)\n", from.ToInt(), to.ToInt());
49 result[from.ToInt()] = to_to;
54 RpoNumber unvisited() {
return RpoNumber::FromInt(-1); }
55 RpoNumber onstack() {
return RpoNumber::FromInt(-2); }
58 bool IsBlockWithBranchPoisoning(InstructionSequence* code,
59 InstructionBlock* block) {
60 if (block->PredecessorCount() != 1)
return false;
61 RpoNumber pred_rpo = (block->predecessors())[0];
62 const InstructionBlock* pred = code->InstructionBlockAt(pred_rpo);
63 if (pred->code_start() == pred->code_end())
return false;
64 Instruction* instr = code->InstructionAt(pred->code_end() - 1);
65 FlagsMode mode = FlagsModeField::decode(instr->opcode());
66 return mode == kFlags_branch_and_poison;
71 bool JumpThreading::ComputeForwarding(Zone* local_zone,
72 ZoneVector<RpoNumber>& result,
73 InstructionSequence* code,
74 bool frame_at_start) {
75 ZoneStack<RpoNumber> stack(local_zone);
76 JumpThreadingState state = {
false, result, stack};
77 state.Clear(code->InstructionBlockCount());
80 for (
auto const block : code->instruction_blocks()) {
81 RpoNumber current = block->rpo_number();
82 state.PushIfUnvisited(current);
85 while (!state.stack.empty()) {
86 InstructionBlock* block = code->InstructionBlockAt(state.stack.top());
88 TRACE(
"jt [%d] B%d\n", static_cast<int>(stack.size()),
89 block->rpo_number().ToInt());
90 RpoNumber fw = block->rpo_number();
91 if (!IsBlockWithBranchPoisoning(code, block)) {
93 for (
int i = block->code_start();
i < block->code_end(); ++
i) {
94 Instruction* instr = code->InstructionAt(
i);
95 if (!instr->AreMovesRedundant()) {
97 TRACE(
" parallel move\n");
99 }
else if (FlagsModeField::decode(instr->opcode()) != kFlags_none) {
103 }
else if (instr->IsNop()) {
107 }
else if (instr->arch_opcode() == kArchJmp) {
115 if (frame_at_start || !(block->must_deconstruct_frame() ||
116 block->must_construct_frame())) {
117 fw = code->InputRpo(instr, 0);
128 int next = 1 + block->rpo_number().ToInt();
129 if (next < code->InstructionBlockCount())
130 fw = RpoNumber::FromInt(next);
138 for (RpoNumber num : result) {
139 DCHECK(num.IsValid());
143 if (FLAG_trace_turbo_jt) {
144 for (
int i = 0; i < static_cast<int>(result.size());
i++) {
146 int to = result[
i].ToInt();
148 TRACE(
"-> B%d\n", to);
155 return state.forwarded;
158 void JumpThreading::ApplyForwarding(Zone* local_zone,
159 ZoneVector<RpoNumber>& result,
160 InstructionSequence* code) {
161 if (!FLAG_turbo_jt)
return;
163 ZoneVector<bool> skip(static_cast<int>(result.size()),
false, local_zone);
166 bool prev_fallthru =
true;
167 for (
auto const block : code->instruction_blocks()) {
168 int block_num = block->rpo_number().ToInt();
169 skip[block_num] = !prev_fallthru && result[block_num].ToInt() != block_num;
171 bool fallthru =
true;
172 for (
int i = block->code_start();
i < block->code_end(); ++
i) {
173 Instruction* instr = code->InstructionAt(
i);
174 FlagsMode mode = FlagsModeField::decode(instr->opcode());
175 if (mode == kFlags_branch || mode == kFlags_branch_and_poison) {
177 }
else if (instr->arch_opcode() == kArchJmp) {
178 if (skip[block_num]) {
180 TRACE(
"jt-fw nop @%d\n",
i);
181 instr->OverwriteWithNop();
186 prev_fallthru = fallthru;
190 InstructionSequence::Immediates& immediates = code->immediates();
191 for (
size_t i = 0;
i < immediates.size();
i++) {
192 Constant constant = immediates[
i];
193 if (constant.type() == Constant::kRpoNumber) {
194 RpoNumber rpo = constant.ToRpoNumber();
195 RpoNumber fw = result[rpo.ToInt()];
196 if (!(fw == rpo)) immediates[
i] = Constant(fw);
203 for (
auto const block : code->ao_blocks()) {
204 block->set_ao_number(RpoNumber::FromInt(ao));
205 if (!skip[block->rpo_number().ToInt()]) ao++;