https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124008

            Bug ID: 124008
           Summary: Improve RTL reassociation to eliminate terms in
                    expressions
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: rtl-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: law at gcc dot gnu.org
  Target Milestone: ---

In _ZN11xalanc_1_1019XalanDOMStringCache7releaseERNS_14XalanDOMStringE in xalan
when compiled with -O2 -march=rv64gcbv_zicond on riscv, we have this sequence
generated for an idiom created by one of the RTL passes:

       addi    a5,a5,-8
       srli    a5,a5,3
       addi    a5,a5,1

Which is ((a - 8) >> 3) + 1

We can left shift the + 1 by 3 positions and bring it into the innermost
expression resulting in:

((a - 8 + 8) >> 3)

Which naturally simplifies into (a >> 3).

Something like this in simplify-rtx.  Note this probably doesn't deal with
overflows properly, nor does it deal with large modes where we can't represent
the shifted constants in a HOST_WIDE_INT, etc.  But it does show the basic
structure for how we might solve this problem:

diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc
index 516d626e2f5..0727bd8f484 100644
--- a/gcc/simplify-rtx.cc
+++ b/gcc/simplify-rtx.cc
@@ -3156,6 +3156,27 @@ simplify_context::simplify_binary_operation_1 (rtx_code
code,
                                    simplify_gen_binary (XOR, mode, op1,
                                                         XEXP (op0, 1)));

+      /* (plus (lshiftrt (plus X C1) C2) C3) can be transformed into
+        (lshiftrt (plus X C1') C2) where C1' is C1 - (C3 << C2).  C1
+        may be zero allowing further simplification.  */
+      if (is_a <scalar_int_mode> (mode, &int_mode)
+         && GET_CODE (op0) == LSHIFTRT
+         && CONST_INT_P (XEXP (op0, 1))
+         && GET_CODE (XEXP (op0, 0)) == PLUS
+         && CONST_INT_P (XEXP (XEXP (op0, 0), 1))
+         && CONST_INT_P (op1))
+       {
+         rtx plus_expr = XEXP (op0, 0);
+         HOST_WIDE_INT c1 = INTVAL (XEXP (plus_expr, 1));
+         HOST_WIDE_INT c2 = INTVAL (XEXP (op0, 1));
+         HOST_WIDE_INT c3 = INTVAL (op1);
+         rtx x = simplify_gen_binary (PLUS, mode,
+                                      XEXP (plus_expr, 0),
+                                      GEN_INT (c1 + (c3 << c2)));
+         x = simplify_gen_binary (LSHIFTRT, mode, x, XEXP (op0, 1));
+         return x;
+       }
+
       /* Canonicalize (plus (mult (neg B) C) A) to (minus A (mult B C)).  */
       if (!HONOR_SIGN_DEPENDENT_ROUNDING (mode)
          && GET_CODE (op0) == MULT



That saves two dependent instructions.

Reply via email to