On Tue, Jul 19, 2011 at 6:47 AM, H.J. Lu <hongjiu...@intel.com> wrote:
So, since copy_to_reg & co. expects x in Pmode or VOIDmode constant (due to force_reg that won't do mode conversion), we have to implement them with a mode conversion... > This patch adds the missing Pmode check and conversion. OK for trunk? > 2011-07-18 H.J. Lu <hongjiu...@intel.com> > > * config/i386/i386.c (ix86_legitimize_address): Convert to > Pmode if needed. > (ix86_expand_move): Likewise. > (ix86_expand_call): Likewise. > (ix86_expand_special_args_builtin): Likewise. > (ix86_expand_builtin): Likewise. > > diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c > index c268899..1ed451b 100644 > --- a/gcc/config/i386/i386.c > +++ b/gcc/config/i386/i386.c > @@ -12618,7 +12667,11 @@ ix86_legitimize_address (rtx x, rtx oldx > ATTRIBUTE_UNUSED, > rtx temp = gen_reg_rtx (Pmode); > rtx val = force_operand (XEXP (x, 1), temp); > if (val != temp) > - emit_move_insn (temp, val); > + { > + if (GET_MODE (val) != Pmode) > + val = convert_to_mode (Pmode, val, 1); > + emit_move_insn (temp, val); > + } > > XEXP (x, 1) = temp; > return x; OK. > @@ -12629,7 +12682,11 @@ ix86_legitimize_address (rtx x, rtx oldx > ATTRIBUTE_UNUSED, > rtx temp = gen_reg_rtx (Pmode); > rtx val = force_operand (XEXP (x, 0), temp); > if (val != temp) > - emit_move_insn (temp, val); > + { > + if (GET_MODE (val) != Pmode) > + val = convert_to_mode (Pmode, val, 1); > + emit_move_insn (temp, val); > + } OK. > @@ -14956,6 +15023,8 @@ ix86_expand_move (enum machine_mode mode, rtx > operands[]) > if (model) > { > op1 = legitimize_tls_address (op1, model, true); > + if (GET_MODE (op1) != mode) > + op1 = convert_to_mode (mode, op1, 1); > op1 = force_operand (op1, op0); > if (op1 == op0) > return; Please write this part in the same form as above two changes. This way, force_operand will emit instructions in narrower mode (i.e. SImode, not in DImode). > @@ -21475,7 +21554,10 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx > callarg1, > ? !sibcall_insn_operand (XEXP (fnaddr, 0), Pmode) > : !call_insn_operand (XEXP (fnaddr, 0), Pmode)) > { > - fnaddr = copy_to_mode_reg (Pmode, XEXP (fnaddr, 0)); > + fnaddr = XEXP (fnaddr, 0); > + if (GET_MODE (fnaddr) != Pmode) > + fnaddr = convert_to_mode (Pmode, fnaddr, 1); > + fnaddr = copy_to_mode_reg (Pmode, fnaddr); > fnaddr = gen_rtx_MEM (QImode, fnaddr); > } > Use force_reg (Pmode, ...) instead of copy_to_mode_reg (Pmode, ...). We know we have Pmode here. No need to copy a register if convert_to_mode returned a register. Better yet: fnaddr = gen_rtx_MEM (QImode, force_reg (Pmode, fnaddr)); > @@ -26700,7 +26782,11 @@ ix86_expand_special_args_builtin (const struct > builtin_description *d, > op = expand_normal (arg); > gcc_assert (target == 0); > if (memory) > - target = gen_rtx_MEM (tmode, copy_to_mode_reg (Pmode, op)); > + { > + if (GET_MODE (op) != Pmode) > + op = convert_to_mode (Pmode, op, 1); > + target = gen_rtx_MEM (tmode, copy_to_mode_reg (Pmode, op)); > + } > else > target = force_reg (tmode, op); > arg_adjust = 1; Use force_reg. > @@ -26743,6 +26829,8 @@ ix86_expand_special_args_builtin (const struct > builtin_description *d, > if (i == memory) > { > /* This must be the memory operand. */ > + if (GET_MODE (op) != Pmode) > + op = convert_to_mode (Pmode, op, 1); > op = gen_rtx_MEM (mode, copy_to_mode_reg (Pmode, op)); > gcc_assert (GET_MODE (op) == mode > || GET_MODE (op) == VOIDmode); Same here. > @@ -26969,6 +27057,8 @@ ix86_expand_builtin (tree exp, rtx target, rtx > subtarget ATTRIBUTE_UNUSED, > mode1 = insn_data[icode].operand[1].mode; > mode2 = insn_data[icode].operand[2].mode; > > + if (GET_MODE (op0) != Pmode) > + op0 = convert_to_mode (Pmode, op0, 1); > op0 = force_reg (Pmode, op0); > op0 = gen_rtx_MEM (mode1, op0); > op0 = gen_rtx_MEM (mode1, force_reg (Pmode, op0)); > @@ -27001,7 +27091,11 @@ ix86_expand_builtin (tree exp, rtx target, rtx > subtarget ATTRIBUTE_UNUSED, > op0 = expand_normal (arg0); > icode = CODE_FOR_sse2_clflush; > if (!insn_data[icode].operand[0].predicate (op0, Pmode)) > + { > + if (GET_MODE (op0) != Pmode) > + op0 = convert_to_mode (Pmode, op0, 1); > op0 = copy_to_mode_reg (Pmode, op0); > + } > > emit_insn (gen_sse2_clflush (op0)); > return 0; Use force_reg. > @@ -27014,7 +27108,11 @@ ix86_expand_builtin (tree exp, rtx target, rtx > subtarget ATTRIBUTE_UNUSED, > op1 = expand_normal (arg1); > op2 = expand_normal (arg2); > if (!REG_P (op0)) > - op0 = copy_to_mode_reg (Pmode, op0); > + { > + if (GET_MODE (op0) != Pmode) > + op0 = convert_to_mode (Pmode, op0, 1); > + op0 = copy_to_mode_reg (Pmode, op0); > + } > if (!REG_P (op1)) > op1 = copy_to_mode_reg (SImode, op1); > if (!REG_P (op2)) And here. > @@ -27094,7 +27192,11 @@ ix86_expand_builtin (tree exp, rtx target, rtx > subtarget ATTRIBUTE_UNUSED, > op0 = expand_normal (arg0); > icode = CODE_FOR_lwp_llwpcb; > if (!insn_data[icode].operand[0].predicate (op0, Pmode)) > - op0 = copy_to_mode_reg (Pmode, op0); > + { > + if (GET_MODE (op0) != Pmode) > + op0 = convert_to_mode (Pmode, op0, 1); > + op0 = copy_to_mode_reg (Pmode, op0); > + } > emit_insn (gen_lwp_llwpcb (op0)); > return 0; > And here. > @@ -27153,7 +27255,10 @@ rdrand_step: > arg0 = CALL_EXPR_ARG (exp, 0); > op1 = expand_normal (arg0); > if (!address_operand (op1, VOIDmode)) > - op1 = copy_addr_to_reg (op1); > + { > + op1 = convert_memory_address (Pmode, op1); > + op1 = copy_addr_to_reg (op1); > + } > emit_move_insn (gen_rtx_MEM (mode0, op1), op0); > > op1 = gen_reg_rtx (SImode); > OK. Please re-test the patch on mainline. OK, if also passes x32 regression tests. Thanks, Uros.