POINTERS_EXTEND_UNSIGNED fix (found on IA64 HP-UX)

Steve Ellcey sje@cup.hp.com
Wed Jul 17 10:02:00 GMT 2002


> Incidentally, the CONST_INT/CONST_DOUBLE case looks wrong.  We
> should be adjusting the constant according to POINTERS_EXTEND_UNSIGNED
> from from_mode to to_mode.  Really that means
> 
>   case CONST_INT: 
>   case CONST_DOUBLE:
>     if (GET_MODE_SIZE (to_mode) < GET_MODE_SIZE (from_mode))
>       code = TRUNCATE;
>     else if (POINTERS_EXTEND_UNSIGNED)
>       code = ZERO_EXTEND;
>     else
>       code = SIGN_EXTEND;
>     return simplify_unary_operation (code, to_mode, x, from_mode);

Richard,

Following up to my own response, I think this change you are suggesting
will interact badly with the PLUS optimization on some platforms.  The
problem is that we have:

|    case PLUS:
|    case MULT:
|       /* For addition the second operand is a small constant, we can safely
|          permute the conversion and addition operation.  We can always safely
|          permute them if we are making the address narrower.  In addition,
|          always permute the operations if this is a constant.  */
|       if ((GET_MODE_SIZE (to_mode) < GET_MODE_SIZE (from_mode)
|               || (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == CONST_INT
|                   && POINTERS_EXTEND_UNSIGNED < 0
|                   && (INTVAL (XEXP (x, 1)) + 20000 < 40000
|                       || CONSTANT_P (XEXP (x, 0))))))
|         return gen_rtx_fmt_ee (GET_CODE (x), to_mode,
|                                convert_memory_address (to_mode, XEXP (x, 0)),
|                                convert_memory_address (to_mode, XEXP (x, 1)));
|       break;

Now, if we are truncating I don't think there is any problem, but if we
are extending a PLUS operator then we are calling convert_memory_address
with both sides of the PLUS and I think that is wrong because we are
really adding together an address and an offset, not two addresses and
if we zero-extended both the address and the offset and if the offset is
actually a negative CONST_INT won't that turn the offset into a large
positive number and won't that mean that when we add them together we
will get the wrong result compared with adding the two values together
first and then extending the result of the PLUS.

The full solution (I think) would be to add your CONST_INT/CONST_DOUBLE
change and fix this code to not call convert_memory_address on "XEXP (x,
1)" but do a call to simplify_unary_operation with SIGN_EXTEND
(regardless of the value of POINTERS_EXTEND_UNSIGNED, but I would like
your opinion on it.  I could just turn off the PLUS optimization on IA64
HP-UX (based on the value of POINTERS_EXTEND_UNSIGNED) and leave
everything else (CONST_INT/CONST_DOUBLE) alone and be happy.

Steve Ellcey
sje@cup.hp.com



More information about the Gcc-patches mailing list