From 5670fce5bd4c5592f34e0dfc6c42beafe1684cbd Mon Sep 17 00:00:00 2001 From: water111 Date: Mon, 13 Apr 2026 17:20:08 -0400 Subject: [PATCH] more fixes --- decompiler/IR2/FormExpressionAnalysis.cpp | 20 ++++++++++++++++++ decompiler/IR2/GenericElementMatcher.cpp | 7 +++++++ decompiler/analysis/insert_lets.cpp | 25 +++++++++++++++-------- 3 files changed, 44 insertions(+), 8 deletions(-) diff --git a/decompiler/IR2/FormExpressionAnalysis.cpp b/decompiler/IR2/FormExpressionAnalysis.cpp index d146e2d677..f9ceaf9e14 100644 --- a/decompiler/IR2/FormExpressionAnalysis.cpp +++ b/decompiler/IR2/FormExpressionAnalysis.cpp @@ -1089,6 +1089,26 @@ void SimpleExpressionElement::update_from_stack_float_2_nestable(const Env& env, bool allow_side_effects) { if (is_float_type(env, m_my_idx, m_expr.get_arg(0).var()) && is_float_type(env, m_my_idx, m_expr.get_arg(1).var())) { + if (m_expr.get_arg(0).var() == m_expr.get_arg(1).var()) { + auto arg = + pop_to_forms({m_expr.get_arg(0).var()}, env, pool, stack, allow_side_effects, {}, {2}) + .at(0); + if (kind == FixedOperatorKind::MULTIPLICATION) { + result->push_back(pool.alloc_element( + GenericOperator::make_function(pool.form("square")), arg)); + return; + } + + auto atom = form_as_atom(arg); + if (atom) { + auto arg_copy = pool.form(*atom); + auto new_form = + make_and_compact_math_op(arg, arg_copy, {}, {}, pool, env, kind, true, false); + result->push_back(new_form); + return; + } + } + auto args = pop_to_forms({m_expr.get_arg(0).var(), m_expr.get_arg(1).var()}, env, pool, stack, allow_side_effects); auto new_form = diff --git a/decompiler/IR2/GenericElementMatcher.cpp b/decompiler/IR2/GenericElementMatcher.cpp index 9d254d5f1b..685d4e1d0a 100644 --- a/decompiler/IR2/GenericElementMatcher.cpp +++ b/decompiler/IR2/GenericElementMatcher.cpp @@ -305,6 +305,13 @@ bool Matcher::do_match(Form* input, MatchResult::Maps* maps_out, const Env* cons } } + auto as_stack_spill = + dynamic_cast(input->try_as_single_active_element()); + if (as_stack_spill) { + got = true; + result = make_stack_slot_access(as_stack_spill->stack_offset()); + } + if (got) { if (m_kind == Kind::REG) { return result.reg() == *m_reg; diff --git a/decompiler/analysis/insert_lets.cpp b/decompiler/analysis/insert_lets.cpp index 136d4fe475..97e0813360 100644 --- a/decompiler/analysis/insert_lets.cpp +++ b/decompiler/analysis/insert_lets.cpp @@ -45,6 +45,7 @@ If the previous let variables appear in the definition of new one, make the let namespace { FormElement* rewrite_let(LetElement* in, const Env& env, FormPool& pool, LetRewriteStats& stats); +FormElement* rewrite_multi_let_as_vector_dot(LetElement* in, const Env& env, FormPool& pool); bool let_uses_stack_slot_access(const LetElement* in); std::vector path_up_tree(Form* in, const Env&) { @@ -2410,6 +2411,14 @@ FormElement* rewrite_set_font_single(LetElement* in, FormElement* rewrite_let(LetElement* in, const Env& env, FormPool& pool, LetRewriteStats& stats) { // ordered based on frequency. for best performance, you check the most likely rewrites first! + if (in->entries().size() >= 6) { + auto as_vector_dot = rewrite_multi_let_as_vector_dot(in, env, pool); + if (as_vector_dot) { + stats.vector_dot++; + return as_vector_dot; + } + } + if (let_uses_stack_slot_access(in)) { return nullptr; } @@ -3078,6 +3087,14 @@ FormElement* rewrite_multi_let(LetElement* in, const Env& env, FormPool& pool, LetRewriteStats& stats) { + if (in->entries().size() >= 6) { + auto as_vector_dot = rewrite_multi_let_as_vector_dot(in, env, pool); + if (as_vector_dot) { + stats.vector_dot++; + return as_vector_dot; + } + } + if (let_uses_stack_slot_access(in)) { return in; } @@ -3110,14 +3127,6 @@ FormElement* rewrite_multi_let(LetElement* in, } } - if (in->entries().size() >= 6) { - auto as_vector_dot = rewrite_multi_let_as_vector_dot(in, env, pool); - if (as_vector_dot) { - stats.vector_dot++; - return as_vector_dot; - } - } - auto as_font_set_origin = rewrite_set_font_origin(in, env, pool); if (as_font_set_origin) { stats.font_method++;