This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: Bad choices by expand_mult_highpart
- From: Ulrich Weigand <weigand at i1 dot informatik dot uni-erlangen dot de>
- To: rsandifo at redhat dot com (Richard Sandiford)
- Cc: weigand at i1 dot informatik dot uni-erlangen dot de (Ulrich Weigand), roger at eyesopen dot com (Roger Sayle), ja2morri at csclub dot uwaterloo dot ca (James Morrison), gcc-patches at gcc dot gnu dot org
- Date: Mon, 22 Mar 2004 20:35:02 +0100 (CET)
- Subject: Re: Bad choices by expand_mult_highpart
Richard Sandiford wrote:
> I don't understand why the masking and special handling of negative
> constants is necessary. What does synth_mult do wrong wrt negative
> constants? I ask because (a) neg_variant involves using synth_mult
> with the negative of the original constant and (b) expand_mult doesn't
> do anything like this.
Well, synth_mult uses all the bits in the HOST_WIDE_INT it gets to
compute the shift/add sequence. Now, consider what happens when some
bits are 1 outside the range of the mode of the operand this sequence
is later applied to; say we want to compute X * C in a mode of bitsize
N, but C is of the form C1 + 2^N*C2. Then we get:
X*C1 + 2^N*X*C2
as result of the synth_mult algorithm (computed in word mode).
If we interpret the result in mode N as well, then this is just
X*C1 and the high bits are ignored -- so this is just fine for
expand_mult. If we are interested in the *high* part of the
result, this is broken however.
To fix this for expand_mult_highpart, we have two possible strategies:
we could sign-/zero-extend both the first operand and the constant
to wider_mode, and perform synth_mult as is in wider_mode, ignoring
all bits outside of wider_mode in the result.
Or we could truncate the constant to mode, extend the first operand
to wider_mode, perform synth_mult in wider_mode, and adjust for the
error we got because the constant was negative as seen in mode.
What my patch does is the second variant. The reason for this is
that I initially thought that we would intentionally accept a
wider_mode larger than HOST_BITS_PER_WIDE_INT (e.g. in order to
optimize a DImode division on 64-bit targets, we might want to
perform a TImode synth_mult here). In this case, the first
strategy won't work because we cannot extend the constant to
TImode and have it still fit into a HOST_WIDE_INT.
However, later on I decided to restrict wider_mode to word_mode
(which should always fit into a HOST_WIDE_INT) anyway, and so
the first strategy should work as well.
In fact, your point as to neg_variant is well taken -- it looks
as if the second strategy could indeed give incorrect results
if neg_variant is chosen ... I'll see if I can find a test case.
Bye,
Ulrich
--
Dr. Ulrich Weigand
weigand@informatik.uni-erlangen.de