* 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).