public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* How to split mulsi3 pattern
@ 2009-11-10 13:48 Mohamed Shafi
  2009-11-10 17:37 ` Richard Henderson
  0 siblings, 1 reply; 4+ messages in thread
From: Mohamed Shafi @ 2009-11-10 13:48 UTC (permalink / raw)
  To: GCC

Hello all,

I am doing a port for a 32bit target in GCC 4.4.0. In my target 32bit
multiply instruction is carried out in two instructions.

Dn = Da x Db is executed as

Dn = (Da.L * Db.H + Da.H * Db.L) << 16
Dn = Dn + (Da.L * Db.L)

Currently the pattern that i have for this is as follows:

(define_insn "mulsi3"
 [(set (match_operand:SI 0 "register_operand"           "=&d")
       (mult:SI (match_operand:SI 1 "register_operand"  "%d")
               (match_operand:SI 2 "register_operand" "d")))]

I would like to split this pattern into two (either after of before
reload). Currently i am doing something like this:

(define_insn_and_split "mulsi3"
 [(set (match_operand:SI 0 "register_operand"           "=&d")
       (mult:SI (match_operand:SI 1 "register_operand"  "%d")
                (match_operand:SI 2 "register_operand" "d")))]
 ""
 "#"
 "reload_completed"
 [(set (match_dup 0)
       (ashift:SI
        (plus:SI (mult:HI (unspec:HI [(match_dup 2)] UNSPEC_REG_LOW)
                          (unspec:HI [(match_dup 1)] UNSPEC_REG_HIGH))
                 (mult:HI (unspec:HI [(match_dup 2)] UNSPEC_REG_HIGH)
                          (unspec:HI [(match_dup 1)] UNSPEC_REG_LOW)))
        (const_int 16)))
  (set (match_dup 0)
       (plus:SI (match_dup 0)
                (mult:HI (unspec:HI [(match_dup 2)] UNSPEC_REG_LOW)
                         (unspec:HI [(match_dup 1)] UNSPEC_REG_LOW))))]
  ""
)

But in few testcases this is creating problems. So i would like to
know better patterns to split mulsi3 pattern.
Can someone help me out.

Regards,
Shafi

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: How to split mulsi3 pattern
  2009-11-10 13:48 How to split mulsi3 pattern Mohamed Shafi
@ 2009-11-10 17:37 ` Richard Henderson
  2009-11-12 13:40   ` Mohamed Shafi
  0 siblings, 1 reply; 4+ messages in thread
From: Richard Henderson @ 2009-11-10 17:37 UTC (permalink / raw)
  To: Mohamed Shafi; +Cc: GCC

On 11/10/2009 05:48 AM, Mohamed Shafi wrote:
> (define_insn "mulsi3"
>  [(set (match_operand:SI 0 "register_operand"           "=&d")
>        (mult:SI (match_operand:SI 1 "register_operand"  "%d")
>                (match_operand:SI 2 "register_operand" "d")))]

Note that "%" is only useful if the constraints for the two operands are 
different (e.g. only one operand accepts an immediate input).  When 
they're identical, you simply waste cpu cycles asking reload to try the 
operands in the other order.

>   [(set (match_dup 0)
>         (ashift:SI
>          (plus:SI (mult:HI (unspec:HI [(match_dup 2)] UNSPEC_REG_LOW)
>                            (unspec:HI [(match_dup 1)] UNSPEC_REG_HIGH))
>                   (mult:HI (unspec:HI [(match_dup 2)] UNSPEC_REG_HIGH)
>                            (unspec:HI [(match_dup 1)] UNSPEC_REG_LOW)))
>          (const_int 16)))
>    (set (match_dup 0)
>         (plus:SI (match_dup 0)
>                  (mult:HI (unspec:HI [(match_dup 2)] UNSPEC_REG_LOW)
>                           (unspec:HI [(match_dup 1)] UNSPEC_REG_LOW))))]

Well for one, your modes don't match.  You actually want your unspecs 
and MULTs to be SImode.

You could probably usefully model the second insn as

(define_insn "mulsi3_part2"
   [(set (match_operand:SI 0 "register_operand" "=d")
         (plus:SI
	  (mult:SI (zero_extend:SI
		     (match_operand:HI 1 "register_operand" "d"))
		   (zero_extend:SI
		     (match_operand:HI 2 "register_operand" "d")))
	  (match_operand:SI 3 "register_operand" "0")))]
   ""
   ...)

(define_expand "mulhisi3"
   [(set (match_operand:SI 0 "register_operand" "")
         (mult:SI (zero_extend:SI
		   (match_operand:HI 1 "register_operand" ""))
		 (zero_extend:SI
		   (match_operand:HI 2 "register_operand" "")))))]
   ""
{
   emit_insn (gen_mulsi3_part2 (operands[0], operands[1], operands[2],
                                force_reg (SImode, const0_rtx)));
   DONE;
})

The first insn *could* be modeled without unspec, but its general 
utility is questionable.  On the other hand, it doesn't hurt.

(define_insn "mulsi3_part1"
   [(set (match_operand:SI 0 "register_operand" "=d")
         (ashift:SI
	  (plus:SI
	    (mult:SI
	      (zero_extract:SI
		(match_operand:SI 1 "register_operand" "d")
		(const_int 16)
		(const_int 0))
	      (zero_extract:SI
		(match_operand:SI 2 "register_operand" "d")
		(const_int 16)
		(const_int 16)))
	    (mult:SI
	      (zero_extract:SI
		(match_dup 1)
		(const_int 16)
		(const_int 16))
	      (zero_extract:SI
		(match_dup 2)
		(const_int 16)
		(const_int 0))))
	  (const_int 16)))]
   ""
   ...)

It does appear that you could help the register allocator out by 
splitting this pattern before reload.  I would hope that the gimple 
optimizers are good enough that you'd get good code simply emitting the 
two insns immediately at expand time, but I can imagine that there are 
places in the rtl optimizers that would be unhappy not being able to 
generate a plain multiply pattern.  So retaining the splitter is likely 
to be best.

But beyond that we can't help without knowing what "creating problems" 
means.


r~

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: How to split mulsi3 pattern
  2009-11-10 17:37 ` Richard Henderson
@ 2009-11-12 13:40   ` Mohamed Shafi
  2009-11-12 16:02     ` Richard Henderson
  0 siblings, 1 reply; 4+ messages in thread
From: Mohamed Shafi @ 2009-11-12 13:40 UTC (permalink / raw)
  To: Richard Henderson; +Cc: GCC

2009/11/10 Richard Henderson <rth@redhat.com>:
> On 11/10/2009 05:48 AM, Mohamed Shafi wrote:
>>
>> (define_insn "mulsi3"
>>  [(set (match_operand:SI 0 "register_operand"           "=&d")
>>       (mult:SI (match_operand:SI 1 "register_operand"  "%d")
>>               (match_operand:SI 2 "register_operand" "d")))]
>
> Note that "%" is only useful if the constraints for the two operands are
> different (e.g. only one operand accepts an immediate input).  When they're
> identical, you simply waste cpu cycles asking reload to try the operands in
> the other order.
>
>>  [(set (match_dup 0)
>>        (ashift:SI
>>         (plus:SI (mult:HI (unspec:HI [(match_dup 2)] UNSPEC_REG_LOW)
>>                           (unspec:HI [(match_dup 1)] UNSPEC_REG_HIGH))
>>                  (mult:HI (unspec:HI [(match_dup 2)] UNSPEC_REG_HIGH)
>>                           (unspec:HI [(match_dup 1)] UNSPEC_REG_LOW)))
>>         (const_int 16)))
>>   (set (match_dup 0)
>>        (plus:SI (match_dup 0)
>>                 (mult:HI (unspec:HI [(match_dup 2)] UNSPEC_REG_LOW)
>>                          (unspec:HI [(match_dup 1)] UNSPEC_REG_LOW))))]
>
> Well for one, your modes don't match.  You actually want your unspecs and
> MULTs to be SImode.
>
> You could probably usefully model the second insn as
>
> (define_insn "mulsi3_part2"
>  [(set (match_operand:SI 0 "register_operand" "=d")
>        (plus:SI
>          (mult:SI (zero_extend:SI
>                     (match_operand:HI 1 "register_operand" "d"))
>                   (zero_extend:SI
>                     (match_operand:HI 2 "register_operand" "d")))
>          (match_operand:SI 3 "register_operand" "0")))]
>  ""
>  ...)

So i need to change the mode of the register from SI to HI after
reloading. Is that allowed?

Regards,
Shafi

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: How to split mulsi3 pattern
  2009-11-12 13:40   ` Mohamed Shafi
@ 2009-11-12 16:02     ` Richard Henderson
  0 siblings, 0 replies; 4+ messages in thread
From: Richard Henderson @ 2009-11-12 16:02 UTC (permalink / raw)
  To: Mohamed Shafi; +Cc: GCC

On 11/12/2009 05:40 AM, Mohamed Shafi wrote:
> So i need to change the mode of the register from SI to HI after
> reloading. Is that allowed?

Of course.  It's also allowed before reload:

   (subreg:HI (reg:SI foo) 0)

See gen_lowpart.


r~

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2009-11-12 16:02 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-11-10 13:48 How to split mulsi3 pattern Mohamed Shafi
2009-11-10 17:37 ` Richard Henderson
2009-11-12 13:40   ` Mohamed Shafi
2009-11-12 16:02     ` Richard Henderson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).