public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* Destructive comparison
@ 2009-05-17 16:33 Michael Hope
  2009-05-17 18:28 ` Jim Wilson
  0 siblings, 1 reply; 5+ messages in thread
From: Michael Hope @ 2009-05-17 16:33 UTC (permalink / raw)
  To: gcc

Hi there.  I'm having trouble figuring out how to represent a
destructive comparison on the port I'm attempting.  The ISA is very
simple and accumulator based, so to generate a compare of two
registers you would do:

; Compare R10 and R11, destroying R11 and setting C

LOADACC, R10
XOR, R11

Note that the XOR instruction leaves the result in R11, i.e. R11 = R11 ^ ACC

; Greater than or equals, unsigned:

LOADACC, R10
NOTACC ; Ones complement the accumulator
ADD, R11 ; R11 = R11 + ACC, set C

The C flag is equivalent to a zero flag in many cases and a carry flag
in others so I've followed docs and defined different carry modes.
Setting C is done similar to MMIX and bfin where you finally emit a
set compare instruction such as:

(define_insn "cmpcc_insn"
  [(set (match_operand:CC 0 "register_operand" "=C")
	(compare:CC
	 (match_operand:SI 1 "register_operand" "d")
	 (match_operand:SI 2 "register_operand" "b")))
  ]
  ""
  "XOR, %1"
)

Note here the 'b' constraint is for registers in the ACC_REGS class
and 'd' is for registers in the DATA_REGS class.  This seems to work
fine, properly reloading the right operand into the accumulator.

How should I represent the destruction/clobbering of operand 1?  I've tried:

 * Setting the constraint to '=d' or '+d' to mark it as written
 * Using a (clobber (match_dup 1)) in the insn form, such as:

(define_insn "cmpcc_insn"
  [(set (match_operand:CC 0 "register_operand" "=C")
	(compare:CC
	 (match_operand:SI 1 "register_operand" "d")
	 (match_operand:SI 2 "register_operand" "b")))
  ]
  ""
  "XOR, %1"
)

 * Using a define_expand to clobber operand 1 later (outside the
insn's implicit parallel)
 * Using a define_insn to mark it as both a destructive xor and
compare in parallel, such as:

(define_insn "cmpcc_insn"
  [
  (set (match_operand:SI 0 "register_operand" "=d")
       (xor:SI
	(match_operand:SI 1 "register_operand" "%0")
	(match_operand:SI 2 "register_operand" "b")))
  (set (match_operand:CC 3 "register_operand" "=C")
       (compare:CC
	(match_dup 1)
	(match_dup 2)
	))

I'd rather not use a scratch register as the moving between registers
involves ACC, which would mean I'd need to save the right hand operand
before doing the move.  I'd rather have the reload do the move earlier
if required if the left operand lives past this instruction.

Thanks for any help,

-- Michael

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

* Re: Destructive comparison
  2009-05-17 16:33 Destructive comparison Michael Hope
@ 2009-05-17 18:28 ` Jim Wilson
  2009-05-18 12:34   ` Michael Hope
  0 siblings, 1 reply; 5+ messages in thread
From: Jim Wilson @ 2009-05-17 18:28 UTC (permalink / raw)
  To: Michael Hope; +Cc: gcc

Michael Hope wrote:
>  * Using a define_insn to mark it as both a destructive xor and
> compare in parallel, such as:

When a compare is in a parallel, the compare must be the first 
operation.  You have it second.  This kind of pattern should work.  You 
can find many examples of it in the sparc.md file for instance.  Of 
course, in this case, they aren't generated at RTL generation time. 
They are generated at combine time.  Still, I'd expect this to work, 
though there might be some early RTL optimization passes that are not 
prepared to handle it.

See for instance the cmp_cc_xor_not_set pattern in the sparc.md file, 
which is similar to what you want.

Jim

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

* Re: Destructive comparison
  2009-05-17 18:28 ` Jim Wilson
@ 2009-05-18 12:34   ` Michael Hope
  2009-05-19  0:02     ` Jim Wilson
  0 siblings, 1 reply; 5+ messages in thread
From: Michael Hope @ 2009-05-18 12:34 UTC (permalink / raw)
  To: Jim Wilson; +Cc: gcc

Thanks, that worked.  I ended up using:

(define_insn "cmpcc_xor"
  [(set (match_operand:CC 0 "register_operand" "=C")
	(compare:CC
	 (not:SI (xor:SI (match_operand:SI 1 "register_operand" "%r")
			 (match_operand:SI 2 "register_operand" "b")))
	 (const_int 0)))
  (set (match_operand:SI 3 "register_operand" "=1")
	(not:SI (xor:SI (match_dup 1) (match_dup 2))))]
  ""
  "XOR, %1"
)

The important thing was in the generation.  The XOR is two operand but
I needed to supply a third pretend operand using:

      emit_insn (gen_cmpcc_(cc_reg, x, y, gen_reg_rtx(SImode)));

Using a match_dup instead of operand 3 above, or supplying 'x' twice,
lead to the compiler not noticing the change.

-- Michael

2009/5/18 Jim Wilson <wilson@codesourcery.com>:
> Michael Hope wrote:
>>
>>  * Using a define_insn to mark it as both a destructive xor and
>> compare in parallel, such as:
>
> When a compare is in a parallel, the compare must be the first operation.
>  You have it second.  This kind of pattern should work.  You can find many
> examples of it in the sparc.md file for instance.  Of course, in this case,
> they aren't generated at RTL generation time. They are generated at combine
> time.  Still, I'd expect this to work, though there might be some early RTL
> optimization passes that are not prepared to handle it.
>
> See for instance the cmp_cc_xor_not_set pattern in the sparc.md file, which
> is similar to what you want.
>
> Jim
>

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

* Re: Destructive comparison
  2009-05-18 12:34   ` Michael Hope
@ 2009-05-19  0:02     ` Jim Wilson
  2009-05-19  0:38       ` Michael Hope
  0 siblings, 1 reply; 5+ messages in thread
From: Jim Wilson @ 2009-05-19  0:02 UTC (permalink / raw)
  To: Michael Hope; +Cc: gcc

On Mon, 2009-05-18 at 19:58 +1200, Michael Hope wrote:
>   (set (match_operand:SI 3 "register_operand" "=1")
> 	(not:SI (xor:SI (match_dup 1) (match_dup 2))))]

not xor is aka xnor.  You probably want this without the two "not"
operations.

Jim


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

* Re: Destructive comparison
  2009-05-19  0:02     ` Jim Wilson
@ 2009-05-19  0:38       ` Michael Hope
  0 siblings, 0 replies; 5+ messages in thread
From: Michael Hope @ 2009-05-19  0:38 UTC (permalink / raw)
  To: Jim Wilson; +Cc: gcc

Yip, picked that up after I sent it.  Thanks.

2009/5/19 Jim Wilson <wilson@codesourcery.com>:
> On Mon, 2009-05-18 at 19:58 +1200, Michael Hope wrote:
>>   (set (match_operand:SI 3 "register_operand" "=1")
>>       (not:SI (xor:SI (match_dup 1) (match_dup 2))))]
>
> not xor is aka xnor.  You probably want this without the two "not"
> operations.
>
> Jim
>
>
>

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

end of thread, other threads:[~2009-05-18 19:02 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-05-17 16:33 Destructive comparison Michael Hope
2009-05-17 18:28 ` Jim Wilson
2009-05-18 12:34   ` Michael Hope
2009-05-19  0:02     ` Jim Wilson
2009-05-19  0:38       ` Michael Hope

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