Blender  V3.3
multi_function_procedure_optimization.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
4 
6 
7 void move_destructs_up(MFProcedure &procedure, MFInstruction &block_end_instr)
8 {
9  /* A mapping from a variable to its destruct instruction. */
10  Map<MFVariable *, MFDestructInstruction *> destruct_instructions;
11  MFInstruction *current_instr = &block_end_instr;
12  while (true) {
13  MFInstructionType instr_type = current_instr->type();
14  switch (instr_type) {
16  MFDestructInstruction &destruct_instr = static_cast<MFDestructInstruction &>(
17  *current_instr);
18  MFVariable *variable = destruct_instr.variable();
19  if (variable == nullptr) {
20  continue;
21  }
22  /* Remember this destruct instruction so that it can be moved up later on when the last use
23  * of the variable is found. */
24  destruct_instructions.add(variable, &destruct_instr);
25  break;
26  }
28  MFCallInstruction &call_instr = static_cast<MFCallInstruction &>(*current_instr);
29  /* For each variable, place the corresponding remembered destruct instruction right after
30  * this call instruction. */
31  for (MFVariable *variable : call_instr.params()) {
32  if (variable == nullptr) {
33  continue;
34  }
35  MFDestructInstruction *destruct_instr = destruct_instructions.pop_default(variable,
36  nullptr);
37  if (destruct_instr == nullptr) {
38  continue;
39  }
40 
41  /* Unlink destruct instruction from previous position. */
42  MFInstruction *after_destruct_instr = destruct_instr->next();
43  while (!destruct_instr->prev().is_empty()) {
44  /* Do a copy of the cursor here, because `destruct_instr->prev()` changes when
45  * #set_next is called below. */
46  const MFInstructionCursor cursor = destruct_instr->prev()[0];
47  cursor.set_next(procedure, after_destruct_instr);
48  }
49 
50  /* Insert destruct instruction in new position. */
51  MFInstruction *next_instr = call_instr.next();
52  call_instr.set_next(destruct_instr);
53  destruct_instr->set_next(next_instr);
54  }
55  break;
56  }
57  default: {
58  break;
59  }
60  }
61 
62  const Span<MFInstructionCursor> prev_cursors = current_instr->prev();
63  if (prev_cursors.size() != 1) {
64  /* Stop when there is some branching before this instruction. */
65  break;
66  }
67  const MFInstructionCursor &prev_cursor = prev_cursors[0];
68  current_instr = prev_cursor.instruction();
69  if (current_instr == nullptr) {
70  /* Stop when there is no previous instruction. E.g. when this is the first instruction. */
71  break;
72  }
73  }
74 }
75 
76 } // namespace blender::fn::procedure_optimization
bool add(const Key &key, const Value &value)
Definition: BLI_map.hh:250
Value pop_default(const Key &key, const Value &default_value)
Definition: BLI_map.hh:394
constexpr int64_t size() const
Definition: BLI_span.hh:240
void set_next(MFInstruction *instruction)
void set_next(MFInstruction *instruction)
void set_next(MFProcedure &procedure, MFInstruction *new_instruction) const
Span< MFInstructionCursor > prev() const
void move_destructs_up(MFProcedure &procedure, MFInstruction &block_end_instr)