md description for intruction that modifies multiple operands

Richard Earnshaw rearnsha@arm.com
Thu May 29 17:37:00 GMT 2003


> >> I don't think so. Though it looks like you might want to define a single
> >> unspec number for the pattern and maybe use a parallel? *guesses*
> 
> I thought each unspec had to have a unique number.

That was probably a cut-and-paste error on my part.  But an unspec is just 
a black-box operation to the compiler.  The number is only there as a 
discriminator to resolve potential ambiguities.  So two insn matches that 
insns of the form

insn_a: (set x (unspec [(y) (z)] 0))
insn_b: (set a (unspec [(b)] 0))

is not illegal, though it is bad style.

> 
> Where are you suggesting placing a "parallel"?

A define_insn is an implicit parallel when there are multiple statements.  
 Only define expand needs an explicit parallel.

> 
> > You are probably better off if you only use match_dup to match inputs to
> > inputs and outputs to outputs.  Use tied register allocation for inputs to
> > outputs.  Ties are best done using adjacent number pairs.  Hence something
> > like:
> 
> Thanks much for the example.  I didn't see anything in the docs about
> "tied register allocation".  What specifically does this mean?  Is it
> a way to get registers allocated in sequence?

It's a way to ensure that an input operand is allocated to the same 
register as an output operand.  Look for "0 in constraint" in the 
documentation (the machine description section).

> 
> Perhaps I should give a more realistic code example and *.md entry.
> 
> The hardware handles vectors of 512 bits each, which can be organized as
> a 4x4 matrix of 16 32-bit ints.  We typedef a "matrix_t" to be a V16SI type.
> Here is an actual code example:
> 
>   typedef int matrix_t __attribute__((__mode__(V16SI)));
> 
>   matrix_t foo (matrix_t t0, matrix_t t1, matrix_t t2, matrix_t t3)
>   {
>     __BLOCK4_M (t0, t1, t2, t3);
>     return (t0);
>   }
> 
> This example takes four matrix_t (V16SI) types as function arguments,
> passed in hardware registers $m0, $m1, $m2, and $m3, for t0, t1, t2,
> and t3 respectively.  The __BLOCK4_M builtin takes four matrix_t
> operands, does some matrix arithmetic on them, and returns the results
> left in the four operands.  One restriction is that the block4
> operands have to be allocated to sequential hardware registers.
> 
> Here is the actual md file entry I put in based on your example:
> 
>   (define_insn "fm_block4"
>     [(set (match_operand:V16SI 0 "register_operand" "=v")
>           (unspec:V16SI [(match_operand:V16SI 3 "register_operand" "2")
>                          (match_operand:V16SI 5 "register_operand" "4")
>                          (match_operand:V16SI 7 "register_operand" "6")] 460))
>      (set (match_operand:V16SI 2 "register_operand" "=v")
>           (unspec:V16SI [(match_operand:V16SI 1 "register_operand" "0")
>                          (match_dup 5) (match_dup 7)] 461))
>      (set (match_operand:V16SI 4 "register_operand" "=v")
>           (unspec:V16SI [(match_dup 1) (match_dup 3) (match_dup 7)] 462))
>      (set (match_operand:V16SI 6 "register_operand" "=v")
>           (unspec:V16SI [(match_dup 1) (match_dup 3) (match_dup 7)] 463))]
>     "TARGET_FM"
>     "block4.m\\t%0,%2,%4,%6"
>     [(set_attr "type" "fm")])
> 
> For the above example, running "cc1 -da -O2 x.c" generates the
> following rtl file and then the compiler gets a segfault due to the
> set of a "(nil)".  BTW, first matrix hardware register is 176, first
> pseudo reg is 200.  Note also I deleted some extraneous instructions
> like NOTES:
> 
>   (insn 3 2 4 (nil) (set (reg/v:V16SI 206 [ t0 ])
>           (reg:V16SI 176 $m0 [ t0 ])) -1 (nil)
>       (nil))
>   
>   (insn 4 3 5 (nil) (set (reg/v:V16SI 207 [ t1 ])
>           (reg:V16SI 177 $m1 [ t1 ])) -1 (nil)
>       (nil))
>   
>   (insn 5 4 6 (nil) (set (reg/v:V16SI 208 [ t2 ])
>           (reg:V16SI 178 $m2 [ t2 ])) -1 (nil)
>       (nil))
>   
>   (insn 6 5 7 (nil) (set (reg/v:V16SI 209 [ t3 ])
>           (reg:V16SI 179 $m3 [ t3 ])) -1 (nil)
>       (nil))
>   
>   (insn 12 10 14 (nil) (parallel [
>               (set (reg/v:V16SI 206 [ t0 ])
>                   (unspec:V16SI [
>                           (reg/v:V16SI 209 [ t3 ])
>                           (reg/v:V16SI 209 [ t3 ])
>                           (reg/v:V16SI 207 [ t1 ])
>                       ] 460))
>               (set (reg/v:V16SI 208 [ t2 ])
>                   (unspec:V16SI [
>                           (reg/v:V16SI 207 [ t1 ])
>                           (reg/v:V16SI 209 [ t3 ])
>                           (reg/v:V16SI 207 [ t1 ])
>                       ] 461))
>               (set (nil)
>                   (unspec:V16SI [
>                           (reg/v:V16SI 207 [ t1 ])
>                           (reg/v:V16SI 209 [ t3 ])
>                           (reg/v:V16SI 207 [ t1 ])
>                       ] 462))
>               (set (reg/v:V16SI 208 [ t2 ])
>                   (unspec:V16SI [
>                           (reg/v:V16SI 207 [ t1 ])
>                           (reg/v:V16SI 209 [ t3 ])
>                           (reg/v:V16SI 207 [ t1 ])
>                       ] 463))
>           ]) -1 (nil)
>       (nil))
>   
>   (insn 16 15 17 (nil) (set (reg:V16SI 205 [ <result> ])
>           (reg/v:V16SI 206 [ t0 ])) -1 (nil)
>       (nil))
>   
>   (jump_insn 17 16 18 (nil) (set (pc)
>           (label_ref 22)) -1 (nil)
>       (nil))
> 

This looks like an expansion problem.  How are you calling 
gen_fm_block4()?  You need to pass 8 arguments to it now, something like

	gen_fm_block4(t0, t0, t1, t1, t2, t2, t3, t3);

> I do much appreciate all the help.  I've been a gdb hacker for the
> last 14 years and a gcc hacker for all of about 2 months.  :-)

I'm nearer the reverse.  Expect me to call in the favour sometime :-)

R.




More information about the Gcc mailing list