On Thu, Jun 16, 2011 at 3:20 AM, Eric Botcazou <ebotca...@adacore.com> wrote: >> force_to_mode has >> >> /* If X is a CONST_INT, return a new one. Do this here since the >> test below will fail. */ >> if (CONST_INT_P (x)) >> { >> if (SCALAR_INT_MODE_P (mode)) >> return gen_int_mode (INTVAL (x) & mask, mode); >> else >> { >> x = GEN_INT (INTVAL (x) & mask); >> return gen_lowpart_common (mode, x); >> } >> } >> >> /* If X is narrower than MODE and we want all the bits in X's mode, just >> get X in the proper mode. */ >> if (GET_MODE_SIZE (GET_MODE (x)) < GET_MODE_SIZE (mode) >> && (GET_MODE_MASK (GET_MODE (x)) & ~mask) == 0) >> return gen_lowpart (mode, x); >> >> When it gets >> >> (zero_extend:DI (plus:SI (subreg:SI (reg/f:DI 20 frame) 0) >> (const_int -58 [0xffffffffffffffc6]))) >> >> It first sets mask to 32bit and leads to >> >> (subreg:DI (plus:SI (subreg:SI (reg/f:DI 20 frame) 0) >> (const_int -58 [0xffffffffffffffc6])) 0) >> >> with mask == 0xffffffff. The probem is >> >> binop: >> /* For most binary operations, just propagate into the operation and >> change the mode if we have an operation of that mode. */ >> >> op0 = force_to_mode (XEXP (x, 0), mode, mask, next_select); >> op1 = force_to_mode (XEXP (x, 1), mode, mask, next_select); >> >> where it calls force_to_mode with -58, 0xffffffff mask and DImode. This >> transformation is incorrect. > > I think that the conclusion is questionable. If MASK is really 0xffffffff, > then you're guaranteeing to force_to_mode that you don't care about the upper > 32 bits. Of course this is wrong for (zero_extend:DI ...). > > So it seems to me that the origin of the problem is the transition from: > > (zero_extend:DI (plus:SI (subreg:SI (reg/f:DI 20 frame) 0) > (const_int -58 [0xffffffffffffffc6]))) > > to force_to_mode being invoked on: > > (subreg:DI (plus:SI (subreg:SI (reg/f:DI 20 frame) 0) > (const_int -58 [0xffffffffffffffc6])) 0) > > with mask == 0xffffffff. This isn't equivalent, at least alone. > > > Who computes the mask and calls force_to_mode? Is it simplify_and_const_int_1? > > Then it should also mask the returned value, as explained in the code: > > /* Simplify VAROP knowing that we will be only looking at some of the > bits in it. > > Note by passing in CONSTOP, we guarantee that the bits not set in > CONSTOP are not significant and will never be examined. We must > ensure that is the case by explicitly masking out those bits > before returning. */ > varop = force_to_mode (varop, mode, constop, 0); > > If this is what actually happens, why gets this masking lost somewhere? >
You are right. The real bug is http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49504 The fix is at http://gcc.gnu.org/ml/gcc-patches/2011-06/msg01704.html -- H.J.