diff options
author | Roger Sayle <roger@nextmovesoftware.com> | 2023-10-03 12:52:04 +0100 |
---|---|---|
committer | Roger Sayle <roger@nextmovesoftware.com> | 2023-10-03 12:52:04 +0100 |
commit | 09881218137f4af9b7c894c2d350cf2ff8e0ee23 (patch) | |
tree | fc819d69b4600fbc1a91bda0f7015564f15e0569 /gcc | |
parent | 3ca09d684e496240a87c0327687e2898060c2363 (diff) | |
download | gcc-09881218137f4af9b7c894c2d350cf2ff8e0ee23.zip gcc-09881218137f4af9b7c894c2d350cf2ff8e0ee23.tar.gz gcc-09881218137f4af9b7c894c2d350cf2ff8e0ee23.tar.bz2 |
ARC: Use rlc r0,0 to implement scc_ltu (i.e. carry_flag ? 1 : 0)
This patch teaches the ARC backend that the contents of the carry flag
can be placed in an integer register conveniently using the "rlc rX,0"
instruction, which is a rotate-left-through-carry using zero as a source.
This is a convenient special case for the LTU form of the scc pattern.
unsigned int foo(unsigned int x, unsigned int y)
{
return (x+y) < x;
}
With -O2 -mcpu=em this is currently compiled to:
foo: add.f 0,r0,r1
mov_s r0,1 ;3
j_s.d [blink]
mov.hs r0,0
[which after an addition to set the carry flag, sets r0 to 1,
followed by a conditional assignment of r0 to zero if the
carry flag is clear]. With the new define_insn/optimization
in this patch, this becomes:
foo: add.f 0,r0,r1
j_s.d [blink]
rlc r0,0
This define_insn is also a useful building block for implementing
shifts and rotates.
2023-10-03 Roger Sayle <roger@nextmovesoftware.com>
gcc/ChangeLog
* config/arc/arc.md (CC_ltu): New mode iterator for CC and CC_C.
(scc_ltu_<mode>): New define_insn to handle LTU form of scc_insn.
(*scc_insn): Don't split to a conditional move sequence for LTU.
gcc/testsuite/ChangeLog
* gcc.target/arc/scc-ltu.c: New test case.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/config/arc/arc.md | 14 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/arc/scc-ltu.c | 12 |
2 files changed, 25 insertions, 1 deletions
diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md index d37ecbf..fe2e7fb 100644 --- a/gcc/config/arc/arc.md +++ b/gcc/config/arc/arc.md @@ -3658,12 +3658,24 @@ archs4x, archs4xd" (define_expand "scc_insn" [(set (match_operand:SI 0 "dest_reg_operand" "=w") (match_operand:SI 1 ""))]) +(define_mode_iterator CC_ltu [CC_C CC]) + +(define_insn "scc_ltu_<mode>" + [(set (match_operand:SI 0 "dest_reg_operand" "=w") + (ltu:SI (reg:CC_ltu CC_REG) (const_int 0)))] + "" + "rlc\\t%0,0" + [(set_attr "type" "shift") + (set_attr "predicable" "no") + (set_attr "length" "4")]) + (define_insn_and_split "*scc_insn" [(set (match_operand:SI 0 "dest_reg_operand" "=w") (match_operator:SI 1 "proper_comparison_operator" [(reg CC_REG) (const_int 0)]))] "" "#" - "reload_completed" + "reload_completed + && GET_CODE (operands[1]) != LTU" [(set (match_dup 0) (const_int 1)) (cond_exec (match_dup 1) diff --git a/gcc/testsuite/gcc.target/arc/scc-ltu.c b/gcc/testsuite/gcc.target/arc/scc-ltu.c new file mode 100644 index 0000000..653c55d --- /dev/null +++ b/gcc/testsuite/gcc.target/arc/scc-ltu.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mcpu=em" } */ + +unsigned int foo(unsigned int x, unsigned int y) +{ + return (x+y) < x; +} + +/* { dg-final { scan-assembler "rlc\\s+r0,0" } } */ +/* { dg-final { scan-assembler "add.f\\s+0,r0,r1" } } */ +/* { dg-final { scan-assembler-not "mov_s\\s+r0,1" } } */ +/* { dg-final { scan-assembler-not "mov\.hs\\s+r0,0" } } */ |