(expand_expr): In NOP_EXPR case, truncate and reextend integer constants.
authorRichard Stallman <rms@gnu.org>
Wed, 30 Dec 1992 07:08:14 +0000 (07:08 +0000)
committerRichard Stallman <rms@gnu.org>
Wed, 30 Dec 1992 07:08:14 +0000 (07:08 +0000)
From-SVN: r2987

gcc/expr.c

index 6265f21c039c9139c11dedf4a6b4a4abf7dd7026..3e3e6ce62b130c8394e96df0642dcb8faa550b1a 100644 (file)
@@ -4134,7 +4134,43 @@ expand_expr (exp, target, tmode, modifier)
          return target;
        }
       op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, mode, 0);
-      if (GET_MODE (op0) == mode || GET_MODE (op0) == VOIDmode)
+      if (GET_MODE (op0) == mode)
+       return op0;
+      /* If arg is a constant integer being extended from a narrower mode,
+        we must really truncate to get the extended bits right.  Otherwise
+        (unsigned long) (unsigned char) ("\377"[0])
+        would come out as ffffffff.  */
+      if (GET_MODE (op0) == VOIDmode
+         && (GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))
+             < GET_MODE_BITSIZE (mode)))
+       {
+         /* MODE must be narrower than HOST_BITS_PER_INT.  */
+         int width = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))));
+
+         if (width < HOST_BITS_PER_WIDE_INT)
+           {
+             HOST_WIDE_INT val = (GET_CODE (op0) == CONST_INT ? INTVAL (op0)
+                                  : CONST_DOUBLE_LOW (op0));
+             if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0)))
+                 || !(val & ((HOST_WIDE_INT) 1 << (width - 1))))
+               val &= ((HOST_WIDE_INT) 1 << width) - 1;
+             else
+               val |= ~(((HOST_WIDE_INT) 1 << width) - 1);
+
+             op0 = GEN_INT (val);
+           }
+         else
+           {
+             op0 = (simplify_unary_operation
+                    ((TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0)))
+                      ? ZERO_EXTEND : SIGN_EXTEND),
+                     mode, op0,
+                     TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))));
+             if (op0 == 0)
+               abort ();
+           }
+       }
+      if (GET_MODE (op0) == VOIDmode)
        return op0;
       if (modifier == EXPAND_INITIALIZER)
        return gen_rtx (unsignedp ? ZERO_EXTEND : SIGN_EXTEND, mode, op0);