From: Richard Henderson <[email protected]>

Zero operands produce a zero high and low product. One operands produce
a copy of the other operand and a zero or sign extension in the high
half.

Fold those cases during TCG optimization so wide-multiply idioms used by
target translators can collapse before code generation.

Signed-off-by: Richard Henderson <[email protected]>
Signed-off-by: James Hilliard <[email protected]>
Signed-off-by: Philippe Mathieu-Daudé <[email protected]>
---
 tcg/optimize.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/tcg/optimize.c b/tcg/optimize.c
index ef5eb2cf175..fcdef25beed 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -2212,6 +2212,34 @@ static bool fold_multiply2(OptContext *ctx, TCGOp *op)
             tcg_opt_gen_movi(ctx, op2, rh, h);
             return true;
         }
+
+        if (b == 0) {
+            op2 = opt_insert_before(ctx, op, 0, 2);
+            tcg_opt_gen_movi(ctx, op2, rl, 0);
+            tcg_opt_gen_movi(ctx, op, rh, 0);
+            return true;
+        }
+        if (b == 1) {
+            op2 = opt_insert_before(ctx, op, 0, 2);
+            tcg_opt_gen_mov(ctx, op2, rl, op->args[2]);
+
+            switch (op->opc) {
+            case INDEX_op_mulu2:
+                tcg_opt_gen_movi(ctx, op, rh, 0);
+                break;
+            case INDEX_op_muls2:
+                op->opc = INDEX_op_sar;
+                op->args[0] = rh;
+                op->args[1] = rl;
+                op->args[2] =
+                    arg_new_constant(ctx, tcg_type_size(ctx->type) * 8 - 1);
+                break;
+            default:
+                g_assert_not_reached();
+            }
+
+            return true;
+        }
     }
     return finish_folding(ctx, op);
 }
-- 
2.53.0


Reply via email to