This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]