Ours is a vliw processor too, but my focus was on register allocation.
Unfortunately, the instruction with unspec is still marked to interfere
with all virtual registers and hence gets spilled. I was hoping the one
with unspecs might do better there, but no change there. So, i end up
with similar performance to the unspec_volatile version.
Thanks for your help
Cheers
Hari
Bingfeng Mei wrote:
Yes, we use this instead of unspec_volatile out of performance concern.
Our target is a VLIW processor, so there is more opportunities to move
instructions around. Did you observe any instruction that should be
moved but not?
Cheers,
Bingfeng
-----Original Message-----
From: Hariharan Sandanagobalane [mailto:harihar...@picochip.com]
Sent: 14 May 2010 12:26
To: Bingfeng Mei
Cc: gcc@gcc.gnu.org
Subject: Re: Machine description question
Hi Bengfeng,
Changing my instruction patterns similar to the ones that you
sent does
get over the correctness issue. Setting the imaginary register
explicitly this way and adding those extra unspec patterns
does seem to
work. But, performance-wise, it still doesn't give me
anything. Did you
decide to use these patterns (instead of the simpler unspec_volatile
ones) for performance reasons? Does using these patterns give
you anything?
Cheers
Hari
Bingfeng Mei wrote:
Hari,
Here are some patterns similar to yours.
(define_insn "putbx"
[(set (reg:BXBC R_BX) (unspec:BXBC [(match_operand:QI 0
"firepath_register" "vr")] UNSPEC_BXM))
(unspec:BXBC [(reg:BXBC R_BX)] UNSPEC_BX)] <---
Important to avoid some wrong optimization (Maybe DCE, I
couldn't remember clearly)
define_insn "getbx"
[(set (reg:BXBC R_BX) (unspec:BXBC [(reg:BXBC R_BX)]
UNSPEC_BX)) <---- Artifical dependency
(set (match_operand:SI 0 "register_operand" "=r")
(unspec:SI [(reg:BXBC R_BX)]UNSPEC_BXM))
(unspec:BXBC [(reg:BXBC R_BX)] UNSPEC_BX)] <----
Important to avoid some optimization.
Our port is still porivate and not in mainline.
Cheers,
Bingfeng
-----Original Message-----
From: Hariharan Sandanagobalane [mailto:harihar...@picochip.com]
Sent: 13 May 2010 10:17
To: Bingfeng Mei
Cc: gcc@gcc.gnu.org
Subject: Re: Machine description question
The patterns for PUT/GET were
; Scalar Put instruction.
(define_insn "commsPut"
[(unspec_volatile [(match_operand:HI 0 "const_int_operand" "")
(match_operand:SI 1 "register_operand" "r")]
UNSPEC_PUT)]
""
"PUT %R1,%0\t// PORT(%0) := %R1"
[(set_attr "type" "comms")
(set_attr "length" "2")])
(define_insn "commsGet"
[(set (match_operand:SI 0 "register_operand" "=r")
(unspec_volatile:SI
[(match_operand:HI 1 "immediate_operand" "n")]
UNSPEC_GET))]
""
"GET %1,%R0\t// %R0 := PORT(%1)"
[(set_attr "type" "comms")
(set_attr "length" "2")])
I changed them to
; Scalar Put instruction.
(define_insn "commsPut"
[(unspec [(match_operand:HI 0 "const_int_operand" "")
(match_operand:SI 1 "register_operand" "r")]
UNSPEC_PUT)
(use (reg:HI DUMMY_COMMN_REGNUM))
(clobber (reg:HI DUMMY_COMMN_REGNUM))]
""
"PUT %R1,%0\t// PORT(%0) := %R1"
[(set_attr "type" "comms")
(set_attr "length" "2")])
; Simple scalar get.
(define_insn "commsGet"
[(set (match_operand:SI 0 "register_operand" "=r")
(unspec:SI
[(match_operand:HI 1 "immediate_operand" "n")]
UNSPEC_GET))
(use (reg:HI DUMMY_COMMN_REGNUM))
(clobber (reg:HI DUMMY_COMMN_REGNUM))]
""
"GET %1,%R0\t// %R0 := PORT(%1)"
[(set_attr "type" "comms")
(set_attr "length" "2")])
As for the DUMMY_COMMN_REGNUM, I just defined this as a
FIXED_REGISTER
and bumped up FIRST_PSUEDO_REG.
Actually, there is one more problem i faced (other than
performance).
The code generated using unspec's was just plain wrong. The unspec
pattern that i was using for GET, which was inside a loop,
was being
hoisted out of the loop by the loop optimizer. I guess i
should have
seen this coming, since unspec is just "machine-specific"
operation and
the optimizer probably rightly assumes that multiple
execution of this
with same parameters would result in same value being
produced. This
obviously is not the case for these communication instructions.
Do you have your code to do this using unspec in gcc
mainline? Can you
point me to that, please?
Thanks
Hari
Bingfeng Mei wrote:
How do you define your imaginary register in target.h?
Can you post
one example of your instruction pattern?
Bingfeng
-----Original Message-----
From: Hariharan Sandanagobalane [mailto:harihar...@picochip.com]
Sent: 12 May 2010 16:40
To: Bingfeng Mei
Cc: gcc@gcc.gnu.org
Subject: Re: Machine description question
Thanks for your help BingFeng.
I gave this a go and ended up with worse code (and worse
memory usage)
than before. I started with this experiment because of the
compilers
"All virtual registers are assumed to be used and clobbered by
unspec_volatile" rule. The get/put instructions read/write to
registers
and the virtual register assigned for them interferes
with all the
virtual registers in the function. So, they were highly
likely to be
spilled and use stack instead. I wanted to try to avoid
this by the
introduction of unspec's and use of imaginary registers.
But, the virtual registers that are involved in unspec
patterns with
these imaginary registers still seem to be marked to
interfere with all
the virtual registers. Is that to be expected? Am i
missing something
obvious here?
Regards
Hari
Bingfeng Mei wrote:
Our architecture has the similar resource, and we use the
first approach
by creating an imaginary register and dependency between
these instructions,
i.e., every such instruction reads and write to the special
register to
create artificial dependency. You may need to add a
(unspec:..) as an
independent expression in your pattern to prevent some
wrong optimizations.
Cheers,
Bingfeng
-----Original Message-----
From: gcc-ow...@gcc.gnu.org [mailto:gcc-ow...@gcc.gnu.org] On
Behalf Of Hariharan
Sent: 12 May 2010 11:18
To: gcc@gcc.gnu.org
Subject: Machine description question
Hello all,
Picochip has communication instructions that allow one array
element to
pass data to another. There are 3 such instructions
PUT/GET/TSTPORT.
Currently, all three of these use UNSPEC_VOLATILE side-effect
expressions to make sure they don't get reordered. But, i
wonder if it
is an overkill to use UNSPEC_VOLATILE for this purpose and
whether i
should use UNSPEC instead. The only thing we care here is
that they
don't reordered with respect to each other. It is okay
for other
instructions to move around the communication instructions
(as long as
normal scheduler dependencies are taken care of). There are
possibly one
of two things i can do.
1. Introduce an implicit dependency between all communication
instructions by adding a use/clobber of an imaginary register.
2. Introduce explicit dependency between them by using some
target hook
to add dependency links. I have not found any appropriate
target hook to
do this.
Can you tell me which one i should try? Has anyone tried
doing anything
similar? Any pointers/suggestions on this will be greatly
appreciated.
Thanks
Hari