[PATCH] expand_expr:MINUS_EXPR and constants

Ulrich Weigand Ulrich.Weigand@de.ibm.com
Thu Aug 15 03:17:00 GMT 2002


Hello,

this patch re-enables conversion of A - const to A + (-const)
in the MINUS_EXPR case of expand_expr.

Until 2.95, expand_expr tried to perform this optimization on
the tree level.  However, this implementation was buggy in
certain cases; this bug was fixed by Jason Merrill by performing
the optimization only on signed data types:
http://gcc.gnu.org/ml/gcc-patches/1999-10n/msg00071.html

However, this makes the whole optimization rather pointless:
expand_binop performs the conversion of A - const to A + (-const)
on the RTX level anyway, so there would be no point for
expand_expr to do it, *except* for one case: if the expression
is part of an address, and the EXPAND_SUM (or EXPAND_INITIALIZER)
flag is passed to expand_expr.  In the latter case, this
conversion allows expand_expr to make use of address arithmetic
instead of generating an add insn.

However, in this only interesting case, we are handling pointer
types, which are usually unsigned, so the fixed MINUS_EXPR case
won't do anything anymore ...

This patch re-enables the optimization, (hopefully) avoiding
the original bug by performing the negation of the constant
at the RTX level (which expand_binop would be doing anyway!)
instead of at the tree level.

Bootstrapped/regtested on s390-ibm-linux and s390x-ibm-linux.
OK to apply?

Bye,
Ulrich

ChangeLog:

      * expr.c (expand_expr) [MINUS_EXPR]: Convert A - const to
      A + (-const) on RTX level, even for unsigned types.

Index: gcc/expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.477
diff -c -p -r1.477 expr.c
*** gcc/expr.c    12 Aug 2002 00:57:55 -0000    1.477
--- gcc/expr.c    15 Aug 2002 09:47:19 -0000
*************** expand_expr (exp, target, tmode, modifie
*** 7616,7624 ****
        return op0;

      case PLUS_EXPR:
-       /* We come here from MINUS_EXPR when the second operand is a
-          constant.  */
-     plus_expr:
        this_optab = ! unsignedp && flag_trapv
                     && (GET_MODE_CLASS (mode) == MODE_INT)
                     ? addv_optab : add_optab;
--- 7616,7621 ----
*************** expand_expr (exp, target, tmode, modifie
*** 7728,7733 ****
--- 7725,7732 ----
        op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode,
modifier);
        op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode,
modifier);

+       /* We come here from MINUS_EXPR when the second operand is a
+          constant.  */
      both_summands:
        /* Make sure any term that's a sum with a constant comes last.  */
        if (GET_CODE (op0) == PLUS
*************** expand_expr (exp, target, tmode, modifie
*** 7797,7823 ****
        else
          return gen_rtx_MINUS (mode, op0, op1);
      }
-       /* Convert A - const to A + (-const).  */
-       if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
-     {
-       tree negated = fold (build1 (NEGATE_EXPR, type,
-                              TREE_OPERAND (exp, 1)));

-       if (TREE_UNSIGNED (type) || TREE_OVERFLOW (negated))
-         /* If we can't negate the constant in TYPE, leave it alone and
-            expand_binop will negate it for us.  We used to try to do it
-            here in the signed version of TYPE, but that doesn't work
-            on POINTER_TYPEs.  */;
-       else
-         {
-           exp = build (PLUS_EXPR, type, TREE_OPERAND (exp, 0), negated);
-           goto plus_expr;
-         }
-     }
        this_optab = ! unsignedp && flag_trapv
                     && (GET_MODE_CLASS(mode) == MODE_INT)
                     ? subv_optab : sub_optab;
!       goto binop;

      case MULT_EXPR:
        /* If first operand is constant, swap them.
--- 7796,7828 ----
        else
          return gen_rtx_MINUS (mode, op0, op1);
      }

        this_optab = ! unsignedp && flag_trapv
                     && (GET_MODE_CLASS(mode) == MODE_INT)
                     ? subv_optab : sub_optab;
!
!       /* No sense saving up arithmetic to be done
!      if it's all in the wrong mode to form part of an address.
!      And force_operand won't know whether to sign-extend or
!      zero-extend.  */
!       if ((modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER)
!       || mode != ptr_mode)
!     goto binop;
!
!       if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1))
!     subtarget = 0;
!
!       op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode,
modifier);
!       op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode,
modifier);
!
!       /* Convert A - const to A + (-const).  */
!       if (GET_CODE (op1) == CONST_INT)
!     {
!       op1 = negate_rtx (mode, op1);
!       goto both_summands;
!     }
!
!       goto binop2;

      case MULT_EXPR:
        /* If first operand is constant, swap them.


Mit freundlichen Gruessen / Best Regards

Ulrich Weigand

--
  Dr. Ulrich Weigand
  Linux for S/390 Design & Development
  IBM Deutschland Entwicklung GmbH, Schoenaicher Str. 220, 71032 Boeblingen
  Phone: +49-7031/16-3727   ---   Email: Ulrich.Weigand@de.ibm.com



More information about the Gcc-patches mailing list