40 const auto& in_stacks = const_result.const_stack_in;
43 const auto& cfg_blocks = block_result.cfg_blocks;
45 std::map<std::string, int> array_alloc_count;
46 for (
const auto& token : tokens) {
49 const auto& payload = std::get<TokenPayloadArrayOp>(token.payload);
50 array_alloc_count[payload.name]++;
54 std::map<int, int> dyn_to_static;
56 for (
size_t block_idx = 0; block_idx < cfg_blocks.size(); ++block_idx) {
57 const auto& block = cfg_blocks[block_idx];
59 auto current_stack = in_stacks[block_idx];
61 for (
int token_idx = block.start_token_idx;
62 token_idx < block.end_token_idx; ++token_idx) {
63 const auto& token = tokens[token_idx];
66 while (current_stack.size() <
static_cast<size_t>(behavior.arity)) {
67 current_stack.insert(current_stack.begin(), std::nullopt);
70 std::vector<std::optional<double>> args;
71 for (
int k = 0; k < behavior.arity; ++k) {
72 args.push_back(current_stack.back());
73 current_stack.pop_back();
75 std::ranges::reverse(args);
79 std::get<TokenPayloadArrayOp>(token.payload);
84 if (args[0].has_value() &&
85 array_alloc_count[payload.name] == 1) {
86 int size =
static_cast<int>(args[0].value());
87 if (size > 0 && size <= SINGLEEXPR_STACK_ALLOC_THRESHOLD) {
88 dyn_to_static[token_idx] = size;
93 for (
int k = 0; k < behavior.arity + behavior.stack_effect; ++k) {
94 current_stack.emplace_back(std::nullopt);
99 std::vector<std::pair<int, Token>> insertions;
101 for (
auto& it : std::ranges::reverse_view(dyn_to_static)) {
102 int token_idx = it.first;
103 int size = it.second;
105 auto& token = tokens[token_idx];
106 auto& payload = std::get<TokenPayloadArrayOp>(token.payload);
109 token.text = payload.name +
"{}^" + std::to_string(size);
110 payload.static_size = size;
116 insertions.emplace_back(token_idx, drop_token);
119 for (
const auto& [pos, drop_token] : insertions) {
120 tokens.insert(tokens.begin() + pos, drop_token);
123 if (!dyn_to_static.empty()) {