OSDN Git Service

PR bootstrap/40027
[pf3gnuchains/gcc-fork.git] / gcc / expr.c
index cf81842..c2524f2 100644 (file)
@@ -2249,6 +2249,26 @@ use_group_regs (rtx *call_fusage, rtx regs)
        use_reg (call_fusage, reg);
     }
 }
+
+/* Return the defining gimple statement for SSA_NAME NAME if it is an
+   assigment and the code of the expresion on the RHS is CODE.  Return
+   NULL otherwise.  */
+
+static gimple
+get_def_for_expr (tree name, enum tree_code code)
+{
+  gimple def_stmt;
+
+  if (TREE_CODE (name) != SSA_NAME)
+    return NULL;
+
+  def_stmt = get_gimple_for_ssa_name (name);
+  if (!def_stmt
+      || gimple_assign_rhs_code (def_stmt) != code)
+    return NULL;
+
+  return def_stmt;
+}
 \f
 
 /* Determine whether the LEN bytes generated by CONSTFUN can be
@@ -5776,22 +5796,25 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
          && compare_tree_int (TYPE_SIZE (TREE_TYPE (exp)), bitsize) != 0))
     {
       rtx temp;
+      gimple nop_def;
 
       /* If EXP is a NOP_EXPR of precision less than its mode, then that
         implies a mask operation.  If the precision is the same size as
         the field we're storing into, that mask is redundant.  This is
         particularly common with bit field assignments generated by the
         C front end.  */
-      if (TREE_CODE (exp) == NOP_EXPR)
+      nop_def = get_def_for_expr (exp, NOP_EXPR);
+      if (nop_def)
        {
          tree type = TREE_TYPE (exp);
          if (INTEGRAL_TYPE_P (type)
              && TYPE_PRECISION (type) < GET_MODE_BITSIZE (TYPE_MODE (type))
              && bitsize == TYPE_PRECISION (type))
            {
-             type = TREE_TYPE (TREE_OPERAND (exp, 0));
+             tree op = gimple_assign_rhs1 (nop_def);
+             type = TREE_TYPE (op);
              if (INTEGRAL_TYPE_P (type) && TYPE_PRECISION (type) >= bitsize)
-               exp = TREE_OPERAND (exp, 0);
+               exp = op;
            }
        }
 
@@ -7130,6 +7153,8 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
   int ignore;
   tree context, subexp0, subexp1;
   bool reduce_bit_field;
+  gimple subexp0_def, subexp1_def;
+  tree top0, top1;
 #define REDUCE_BIT_FIELD(expr) (reduce_bit_field                         \
                                 ? reduce_to_bit_field_precision ((expr), \
                                                                  target, \
@@ -8033,14 +8058,14 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
            && (attr = lookup_attribute ("error",
                                         DECL_ATTRIBUTES (fndecl))) != NULL)
          error ("%Kcall to %qs declared with attribute error: %s",
-                exp, lang_hooks.decl_printable_name (fndecl, 1),
+                exp, identifier_to_locale (lang_hooks.decl_printable_name (fndecl, 1)),
                 TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr))));
        if (fndecl
            && (attr = lookup_attribute ("warning",
                                         DECL_ATTRIBUTES (fndecl))) != NULL)
          warning_at (tree_nonartificial_location (exp),
                      0, "%Kcall to %qs declared with attribute warning: %s",
-                     exp, lang_hooks.decl_printable_name (fndecl, 1),
+                     exp, identifier_to_locale (lang_hooks.decl_printable_name (fndecl, 1)),
                      TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr))));
 
        /* Check for a built-in function.  */
@@ -8322,27 +8347,30 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
       /* Check if this is a case for multiplication and addition.  */
       if ((TREE_CODE (type) == INTEGER_TYPE
           || TREE_CODE (type) == FIXED_POINT_TYPE)
-         && TREE_CODE (TREE_OPERAND (exp, 0)) == MULT_EXPR)
+         && (subexp0_def = get_def_for_expr (TREE_OPERAND (exp, 0),
+                                             MULT_EXPR)))
        {
          tree subsubexp0, subsubexp1;
-         enum tree_code code0, code1, this_code;
+         gimple subsubexp0_def, subsubexp1_def;
+         enum tree_code this_code;
 
-         subexp0 = TREE_OPERAND (exp, 0);
-         subsubexp0 = TREE_OPERAND (subexp0, 0);
-         subsubexp1 = TREE_OPERAND (subexp0, 1);
-         code0 = TREE_CODE (subsubexp0);
-         code1 = TREE_CODE (subsubexp1);
          this_code = TREE_CODE (type) == INTEGER_TYPE ? NOP_EXPR
                                                       : FIXED_CONVERT_EXPR;
-         if (code0 == this_code && code1 == this_code
-             && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subsubexp0, 0)))
+         subsubexp0 = gimple_assign_rhs1 (subexp0_def);
+         subsubexp0_def = get_def_for_expr (subsubexp0, this_code);
+         subsubexp1 = gimple_assign_rhs2 (subexp0_def);
+         subsubexp1_def = get_def_for_expr (subsubexp1, this_code);
+         if (subsubexp0_def && subsubexp1_def
+             && (top0 = gimple_assign_rhs1 (subsubexp0_def))
+             && (top1 = gimple_assign_rhs1 (subsubexp1_def))
+             && (TYPE_PRECISION (TREE_TYPE (top0))
                  < TYPE_PRECISION (TREE_TYPE (subsubexp0)))
-             && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subsubexp0, 0)))
-                 == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subsubexp1, 0))))
-             && (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (subsubexp0, 0)))
-                 == TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (subsubexp1, 0)))))
+             && (TYPE_PRECISION (TREE_TYPE (top0))
+                 == TYPE_PRECISION (TREE_TYPE (top1)))
+             && (TYPE_UNSIGNED (TREE_TYPE (top0))
+                 == TYPE_UNSIGNED (TREE_TYPE (top1))))
            {
-             tree op0type = TREE_TYPE (TREE_OPERAND (subsubexp0, 0));
+             tree op0type = TREE_TYPE (top0);
              enum machine_mode innermode = TYPE_MODE (op0type);
              bool zextend_p = TYPE_UNSIGNED (op0type);
              bool sat_p = TYPE_SATURATING (TREE_TYPE (subsubexp0));
@@ -8355,9 +8383,8 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
                  && (optab_handler (this_optab, mode)->insn_code
                      != CODE_FOR_nothing))
                {
-                 expand_operands (TREE_OPERAND (subsubexp0, 0),
-                                  TREE_OPERAND (subsubexp1, 0),
-                                  NULL_RTX, &op0, &op1, EXPAND_NORMAL);
+                 expand_operands (top0, top1, NULL_RTX, &op0, &op1,
+                                  EXPAND_NORMAL);
                  op2 = expand_expr (TREE_OPERAND (exp, 1), subtarget,
                                     VOIDmode, EXPAND_NORMAL);
                  temp = expand_ternary_op (mode, this_optab, op0, op1, op2,
@@ -8485,27 +8512,30 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
       /* Check if this is a case for multiplication and subtraction.  */
       if ((TREE_CODE (type) == INTEGER_TYPE
           || TREE_CODE (type) == FIXED_POINT_TYPE)
-         && TREE_CODE (TREE_OPERAND (exp, 1)) == MULT_EXPR)
+         && (subexp1_def = get_def_for_expr (TREE_OPERAND (exp, 1),
+                                             MULT_EXPR)))
        {
          tree subsubexp0, subsubexp1;
-         enum tree_code code0, code1, this_code;
+         gimple subsubexp0_def, subsubexp1_def;
+         enum tree_code this_code;
 
-         subexp1 = TREE_OPERAND (exp, 1);
-         subsubexp0 = TREE_OPERAND (subexp1, 0);
-         subsubexp1 = TREE_OPERAND (subexp1, 1);
-         code0 = TREE_CODE (subsubexp0);
-         code1 = TREE_CODE (subsubexp1);
          this_code = TREE_CODE (type) == INTEGER_TYPE ? NOP_EXPR
                                                       : FIXED_CONVERT_EXPR;
-         if (code0 == this_code && code1 == this_code
-             && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subsubexp0, 0)))
+         subsubexp0 = gimple_assign_rhs1 (subexp1_def);
+         subsubexp0_def = get_def_for_expr (subsubexp0, this_code);
+         subsubexp1 = gimple_assign_rhs2 (subexp1_def);
+         subsubexp1_def = get_def_for_expr (subsubexp1, this_code);
+         if (subsubexp0_def && subsubexp1_def
+             && (top0 = gimple_assign_rhs1 (subsubexp0_def))
+             && (top1 = gimple_assign_rhs1 (subsubexp1_def))
+             && (TYPE_PRECISION (TREE_TYPE (top0))
                  < TYPE_PRECISION (TREE_TYPE (subsubexp0)))
-             && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subsubexp0, 0)))
-                 == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subsubexp1, 0))))
-             && (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (subsubexp0, 0)))
-                 == TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (subsubexp1, 0)))))
+             && (TYPE_PRECISION (TREE_TYPE (top0))
+                 == TYPE_PRECISION (TREE_TYPE (top1)))
+             && (TYPE_UNSIGNED (TREE_TYPE (top0))
+                 == TYPE_UNSIGNED (TREE_TYPE (top1))))
            {
-             tree op0type = TREE_TYPE (TREE_OPERAND (subsubexp0, 0));
+             tree op0type = TREE_TYPE (top0);
              enum machine_mode innermode = TYPE_MODE (op0type);
              bool zextend_p = TYPE_UNSIGNED (op0type);
              bool sat_p = TYPE_SATURATING (TREE_TYPE (subsubexp0));
@@ -8518,9 +8548,8 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
                  && (optab_handler (this_optab, mode)->insn_code
                      != CODE_FOR_nothing))
                {
-                 expand_operands (TREE_OPERAND (subsubexp0, 0),
-                                  TREE_OPERAND (subsubexp1, 0),
-                                  NULL_RTX, &op0, &op1, EXPAND_NORMAL);
+                 expand_operands (top0, top1, NULL_RTX, &op0, &op1,
+                                  EXPAND_NORMAL);
                  op2 = expand_expr (TREE_OPERAND (exp, 0), subtarget,
                                     VOIDmode, EXPAND_NORMAL);
                  temp = expand_ternary_op (mode, this_optab, op0, op1, op2,
@@ -8619,66 +8648,65 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
 
       subexp0 = TREE_OPERAND (exp, 0);
       subexp1 = TREE_OPERAND (exp, 1);
+      subexp0_def = get_def_for_expr (subexp0, NOP_EXPR);
+      subexp1_def = get_def_for_expr (subexp1, NOP_EXPR);
+      top0 = top1 = NULL_TREE;
+
       /* First, check if we have a multiplication of one signed and one
         unsigned operand.  */
-      if (TREE_CODE (subexp0) == NOP_EXPR
-         && TREE_CODE (subexp1) == NOP_EXPR
+      if (subexp0_def
+         && (top0 = gimple_assign_rhs1 (subexp0_def))
+         && subexp1_def
+         && (top1 = gimple_assign_rhs1 (subexp1_def))
          && TREE_CODE (type) == INTEGER_TYPE
-         && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subexp0, 0)))
-             < TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp, 0))))
-         && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subexp0, 0)))
-             == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subexp1, 0))))
-         && (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (subexp0, 0)))
-             != TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (subexp1, 0)))))
+         && (TYPE_PRECISION (TREE_TYPE (top0))
+             < TYPE_PRECISION (TREE_TYPE (subexp0)))
+         && (TYPE_PRECISION (TREE_TYPE (top0))
+             == TYPE_PRECISION (TREE_TYPE (top1)))
+         && (TYPE_UNSIGNED (TREE_TYPE (top0))
+             != TYPE_UNSIGNED (TREE_TYPE (top1))))
        {
          enum machine_mode innermode
-           = TYPE_MODE (TREE_TYPE (TREE_OPERAND (subexp0, 0)));
+           = TYPE_MODE (TREE_TYPE (top0));
          this_optab = usmul_widen_optab;
          if (mode == GET_MODE_WIDER_MODE (innermode))
            {
              if (optab_handler (this_optab, mode)->insn_code != CODE_FOR_nothing)
                {
-                 if (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (subexp0, 0))))
-                   expand_operands (TREE_OPERAND (subexp0, 0),
-                                    TREE_OPERAND (subexp1, 0),
-                                    NULL_RTX, &op0, &op1, EXPAND_NORMAL);
+                 if (TYPE_UNSIGNED (TREE_TYPE (top0)))
+                   expand_operands (top0, top1, NULL_RTX, &op0, &op1,
+                                    EXPAND_NORMAL);
                  else
-                   expand_operands (TREE_OPERAND (subexp0, 0),
-                                    TREE_OPERAND (subexp1, 0),
-                                    NULL_RTX, &op1, &op0, EXPAND_NORMAL);
+                   expand_operands (top0, top1, NULL_RTX, &op1, &op0,
+                                    EXPAND_NORMAL);
 
                  goto binop3;
                }
            }
        }
-      /* Check for a multiplication with matching signedness.  */
-      else if (TREE_CODE (TREE_OPERAND (exp, 0)) == NOP_EXPR
+      /* Check for a multiplication with matching signedness.  If
+        valid, TOP0 and TOP1 were set in the previous if
+        condition.  */
+      else if (top0
          && TREE_CODE (type) == INTEGER_TYPE
-         && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
-             < TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp, 0))))
-         && ((TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
-              && int_fits_type_p (TREE_OPERAND (exp, 1),
-                                  TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
+         && (TYPE_PRECISION (TREE_TYPE (top0))
+             < TYPE_PRECISION (TREE_TYPE (subexp0)))
+         && ((TREE_CODE (subexp1) == INTEGER_CST
+              && int_fits_type_p (subexp1, TREE_TYPE (top0))
               /* Don't use a widening multiply if a shift will do.  */
-              && ((GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 1))))
+              && ((GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (subexp1)))
                    > HOST_BITS_PER_WIDE_INT)
-                  || exact_log2 (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1))) < 0))
+                  || exact_log2 (TREE_INT_CST_LOW (subexp1)) < 0))
              ||
-             (TREE_CODE (TREE_OPERAND (exp, 1)) == NOP_EXPR
-              && (TYPE_PRECISION (TREE_TYPE
-                                  (TREE_OPERAND (TREE_OPERAND (exp, 1), 0)))
-                  == TYPE_PRECISION (TREE_TYPE
-                                     (TREE_OPERAND
-                                      (TREE_OPERAND (exp, 0), 0))))
+             (top1
+              && (TYPE_PRECISION (TREE_TYPE (top1))
+                  == TYPE_PRECISION (TREE_TYPE (top0))
               /* If both operands are extended, they must either both
                  be zero-extended or both be sign-extended.  */
-              && (TYPE_UNSIGNED (TREE_TYPE
-                                 (TREE_OPERAND (TREE_OPERAND (exp, 1), 0)))
-                  == TYPE_UNSIGNED (TREE_TYPE
-                                    (TREE_OPERAND
-                                     (TREE_OPERAND (exp, 0), 0)))))))
+              && (TYPE_UNSIGNED (TREE_TYPE (top1))
+                  == TYPE_UNSIGNED (TREE_TYPE (top0)))))))
        {
-         tree op0type = TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0));
+         tree op0type = TREE_TYPE (top0);
          enum machine_mode innermode = TYPE_MODE (op0type);
          bool zextend_p = TYPE_UNSIGNED (op0type);
          optab other_optab = zextend_p ? smul_widen_optab : umul_widen_optab;
@@ -8688,27 +8716,24 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
            {
              if (optab_handler (this_optab, mode)->insn_code != CODE_FOR_nothing)
                {
-                 if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
-                   expand_operands (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
-                                    TREE_OPERAND (exp, 1),
-                                    NULL_RTX, &op0, &op1, EXPAND_NORMAL);
+                 if (TREE_CODE (subexp1) == INTEGER_CST)
+                   expand_operands (top0, subexp1, NULL_RTX, &op0, &op1,
+                                    EXPAND_NORMAL);
                  else
-                   expand_operands (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
-                                    TREE_OPERAND (TREE_OPERAND (exp, 1), 0),
-                                    NULL_RTX, &op0, &op1, EXPAND_NORMAL);
+                   expand_operands (top0, top1, NULL_RTX, &op0, &op1,
+                                    EXPAND_NORMAL);
                  goto binop3;
                }
              else if (optab_handler (other_optab, mode)->insn_code != CODE_FOR_nothing
                       && innermode == word_mode)
                {
                  rtx htem, hipart;
-                 op0 = expand_normal (TREE_OPERAND (TREE_OPERAND (exp, 0), 0));
-                 if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
+                 op0 = expand_normal (top0);
+                 if (TREE_CODE (subexp1) == INTEGER_CST)
                    op1 = convert_modes (innermode, mode,
-                                        expand_normal (TREE_OPERAND (exp, 1)),
-                                        unsignedp);
+                                        expand_normal (subexp1), unsignedp);
                  else
-                   op1 = expand_normal (TREE_OPERAND (TREE_OPERAND (exp, 1), 0));
+                   op1 = expand_normal (top1);
                  temp = expand_binop (mode, other_optab, op0, op1, target,
                                       unsignedp, OPTAB_LIB_WIDEN);
                  hipart = gen_highpart (innermode, temp);
@@ -8721,8 +8746,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
                }
            }
        }
-      expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1),
-                      subtarget, &op0, &op1, EXPAND_NORMAL);
+      expand_operands (subexp0, subexp1, subtarget, &op0, &op1, EXPAND_NORMAL);
       return REDUCE_BIT_FIELD (expand_mult (mode, op0, op1, target, unsignedp));
 
     case TRUNC_DIV_EXPR:
@@ -9018,7 +9042,12 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
     case LTGT_EXPR:
       temp = do_store_flag (exp,
                            modifier != EXPAND_STACK_PARM ? target : NULL_RTX,
-                           tmode != VOIDmode ? tmode : mode);
+                           (tmode != VOIDmode
+                            /* do_store_flag does not handle target modes
+                               of a different class than the comparison mode.
+                               Avoid ICEing in convert_move.  */
+                            && GET_MODE_CLASS (tmode) == GET_MODE_CLASS (mode))
+                           ? tmode : mode);
       if (temp != 0)
        return temp;
 
@@ -9269,13 +9298,6 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
       /* Lowered by gimplify.c.  */
       gcc_unreachable ();
 
-    case CHANGE_DYNAMIC_TYPE_EXPR:
-      /* This is ignored at the RTL level.  The tree level set
-        DECL_POINTER_ALIAS_SET of any variable to be 0, which is
-        overkill for the RTL layer but is all that we can
-        represent.  */
-      return const0_rtx;
-
     case EXC_PTR_EXPR:
       return get_exception_pointer ();