Hi!

On Sun, Jul 05, 2020 at 09:17:57PM -0500, Xionghu Luo wrote:
> For extracting high part element from DImode register like:
> 
> {%1:SF=unspec[r122:DI>>0x20#0] 86;clobber scratch;}
> 
> split it before reload with "and mask" to avoid generating shift right
> 32 bit then shift left 32 bit.
> 
> srdi 3,3,32
> sldi 9,3,32
> mtvsrd 1,9
> xscvspdpn 1,1
> 
> =>
> 
> rldicr 3,3,0,31
> mtvsrd 1,3
> xscvspdpn 1,1

Great :-)

> +;; For extracting high part element from DImode register like:
> +;;     {%1:SF=unspec[r122:DI>>0x20#0] 86;clobber scratch;}
> +;; split it before reload with "and mask" to avoid generating shift right
> +;; 32 bit then shift left 32 bit.
> +(define_insn_and_split "movsf_from_si2"
> +  [(set (match_operand:SF 0 "nonimmediate_operand"
> +         "=!r,       f,         v,         wa,        m,         Z,
> +          Z,         wa,        ?r,        !r")
> +         (unspec:SF [
> +          (subreg:SI (ashiftrt:DI
> +            (match_operand:DI 1 "input_operand"
> +        "m,         m,         wY,        Z,         r,         f,
> +        wa,        r,         wa,        r")
> +       (const_int 32)) 0)]
> +                UNSPEC_SF_FROM_SI))
> +  (clobber (match_scratch:DI 2
> +         "=X,        X,         X,         X,         X,         X,
> +         X,         r,         X,         X"))]
> +  "TARGET_NO_SF_SUBREG
> +   && (register_operand (operands[0], SFmode)
> +       && register_operand (operands[1], DImode))"

If the insn condition requires operands 0 and 1 to be register_operands,
it can ask for that in the predicates, instead: not nonimmediate_operand
and input_operand, but just gpc_reg_operand instead.  You can leave out
the impossible alternatives as well (0, 1, 2, 3, 4, 5, 6), leaving just

(define_insn_and_split "movsf_from_si2"
  [(set (match_operand:SF 0 "gpc_reg_operand" "=wa,?r,!r")
        (unspec:SF
          [(subreg:SI (ashiftrt:DI
                        (match_operand:DI 1 "input_operand" "r,wa,r")
                        (const_int 32))
                      0)]
          UNSPEC_SF_FROM_SI)))]
  "TARGET_NO_SF_SUBREG"
  "@
   #
   mfvsrwz %0,%x1
   mr %0,%1"

  "&& !reload_completed
   && vsx_reg_sfsubreg_ok (operands[0], SFmode)"
  [(const_int 0)]
{
  rtx op0 = operands[0];
  rtx op1 = operands[1];
  rtx tmp = gen_reg_rtx (DImode);

You cannot call gen_reg_rtx too late in the pass pipeline.  What we
usually do for such cases is put it as a match_scratch in the pattern,
and then do code like

  if (GET_CODE (operands[2]) == SCRATCH)
    operands[2] = gen_reg_rtx (DImode);

so that it will work both before and after reload.

  /* Avoid split {r155:SI#0=unspec[r133:DI>>0x20#0] 86;clobber scratch;} from 
PR42745.  */

(This line is too long, btw.)

  if (!SUBREG_P (operands[0]))
    {
      rtx mask = GEN_INT (HOST_WIDE_INT_M1U << 32);
      emit_insn (gen_anddi3 (tmp, op1, mask));
      emit_insn (gen_p8_mtvsrd_sf (op0, tmp));
      emit_insn (gen_vsx_xscvspdpn_directmove (op0, op0));
      DONE;
    }
  else
    FAIL;
}
  [(set_attr "length" "12,*,*")
   (set_attr "type" "vecfloat,mffgpr,*")
   (set_attr "isa" "p8v,p8v,*")])

I wonder what will happen if you actually do FAIL here...  There then is
no insn alternative that can match, so we ICE?  In that case, just leave
out the whole FAIL thing, it is useless?  You can do a gcc_assert if you
want to check something.

Oh, and maybe you only want to handle GPRs here, not VSRs?  So just the
"r", not the "wa" at all?  What code would it generate for vector regs?

Lots of questions, sorry!


Segher

Reply via email to