From 9361f19e081294b04e16ac2f6056b3b910f27ff4 Mon Sep 17 00:00:00 2001 From: Georg-Johann Lay Date: Mon, 18 Mar 2024 08:50:02 +0100 Subject: [PATCH] avr.md - Tweak xor insn constraints. xor insn can handle some more values without the requirement of a scratch register. This patch adds a new constraint alternative for such values. The output function avr_out_bitop already handles these cases, so no change is needed there. gcc/ * config/avr/constraints.md (CX2, CX3, CX4): New constraints. * config/avr/avr-protos.h (avr_xor_noclobber_dconst): New proto. * config/avr/avr.cc (avr_xor_noclobber_dconst): New function. * config/avr/avr.md (xorhi3, *xorhi3): Add "d,0,CX2,X" alternative. (xorpsi3, *xorpsi3): Add "d,0,CX3,X" alternative. (xorsi3, *xorsi3): Add "d,0,CX4,X" alternative. --- gcc/config/avr/avr-protos.h | 1 + gcc/config/avr/avr.cc | 25 +++++++++++++++ gcc/config/avr/avr.md | 60 +++++++++++++++++------------------ gcc/config/avr/constraints.md | 17 +++++++++- 4 files changed, 72 insertions(+), 31 deletions(-) diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h index bb680312117..dc23cfbf461 100644 --- a/gcc/config/avr/avr-protos.h +++ b/gcc/config/avr/avr-protos.h @@ -101,6 +101,7 @@ extern const char* avr_out_xload (rtx_insn *, rtx*, int*); extern const char* avr_out_cpymem (rtx_insn *, rtx*, int*); extern const char* avr_out_insert_bits (rtx*, int*); extern bool avr_popcount_each_byte (rtx, int, int); +extern bool avr_xor_noclobber_dconst (rtx, int); extern bool avr_has_nibble_0xf (rtx); extern int extra_constraint_Q (rtx x); diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc index 00fce8da15f..12c59668b4c 100644 --- a/gcc/config/avr/avr.cc +++ b/gcc/config/avr/avr.cc @@ -281,6 +281,31 @@ avr_popcount_each_byte (rtx xval, int n_bytes, int pop_mask) } +/* Constraint helper function. XVAL is a CONST_INT. Return true if we + can perform XOR without a clobber reg, provided the operation is on + a d-register. This means each byte is in { 0, 0xff, 0x80 }. */ + +bool +avr_xor_noclobber_dconst (rtx xval, int n_bytes) +{ + machine_mode mode = GET_MODE (xval); + + if (VOIDmode == mode) + mode = SImode; + + for (int i = 0; i < n_bytes; ++i) + { + rtx xval8 = simplify_gen_subreg (QImode, xval, mode, i); + unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode); + + if (val8 != 0 && val8 != 0xff && val8 != 0x80) + return false; + } + + return true; +} + + /* Access some RTX as INT_MODE. If X is a CONST_FIXED we can get the bit representation of X by "casting" it to CONST_INT. */ diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index bc408633eb5..97f42be7729 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -4741,10 +4741,10 @@ [(set_attr "length" "1")]) (define_insn_and_split "xorhi3" - [(set (match_operand:HI 0 "register_operand" "=??r,r ,r") - (xor:HI (match_operand:HI 1 "register_operand" "%0,0 ,0") - (match_operand:HI 2 "nonmemory_operand" "r,Cx2,n"))) - (clobber (match_scratch:QI 3 "=X,X ,&d"))] + [(set (match_operand:HI 0 "register_operand" "=??r,r ,d ,r") + (xor:HI (match_operand:HI 1 "register_operand" "%0,0 ,0 ,0") + (match_operand:HI 2 "nonmemory_operand" "r,Cx2,CX2,n"))) + (clobber (match_scratch:QI 3 "=X,X ,X ,&d"))] "" "#" "&& reload_completed" @@ -4755,10 +4755,10 @@ (clobber (reg:CC REG_CC))])]) (define_insn "*xorhi3" - [(set (match_operand:HI 0 "register_operand" "=??r,r ,r") - (xor:HI (match_operand:HI 1 "register_operand" "%0,0 ,0") - (match_operand:HI 2 "nonmemory_operand" "r,Cx2,n"))) - (clobber (match_scratch:QI 3 "=X,X ,&d")) + [(set (match_operand:HI 0 "register_operand" "=??r,r ,d ,r") + (xor:HI (match_operand:HI 1 "register_operand" "%0,0 ,0 ,0") + (match_operand:HI 2 "nonmemory_operand" "r,Cx2,CX2,n"))) + (clobber (match_scratch:QI 3 "=X,X ,X ,&d")) (clobber (reg:CC REG_CC))] "reload_completed" { @@ -4767,14 +4767,14 @@ return avr_out_bitop (insn, operands, NULL); } - [(set_attr "length" "2,2,4") - (set_attr "adjust_len" "*,out_bitop,out_bitop")]) + [(set_attr "length" "2,2,4,4") + (set_attr "adjust_len" "*,out_bitop,out_bitop,out_bitop")]) (define_insn_and_split "xorpsi3" - [(set (match_operand:PSI 0 "register_operand" "=??r,r ,r") - (xor:PSI (match_operand:PSI 1 "register_operand" "%0,0 ,0") - (match_operand:PSI 2 "nonmemory_operand" "r,Cx3,n"))) - (clobber (match_scratch:QI 3 "=X,X ,&d"))] + [(set (match_operand:PSI 0 "register_operand" "=??r,r ,d ,r") + (xor:PSI (match_operand:PSI 1 "register_operand" "%0,0 ,0 ,0") + (match_operand:PSI 2 "nonmemory_operand" "r,Cx3,CX3,n"))) + (clobber (match_scratch:QI 3 "=X,X ,X ,&d"))] "" "#" "&& reload_completed" @@ -4785,10 +4785,10 @@ (clobber (reg:CC REG_CC))])]) (define_insn "*xorpsi3" - [(set (match_operand:PSI 0 "register_operand" "=??r,r ,r") - (xor:PSI (match_operand:PSI 1 "register_operand" "%0,0 ,0") - (match_operand:PSI 2 "nonmemory_operand" "r,Cx3,n"))) - (clobber (match_scratch:QI 3 "=X,X ,&d")) + [(set (match_operand:PSI 0 "register_operand" "=??r,r ,d ,r") + (xor:PSI (match_operand:PSI 1 "register_operand" "%0,0 ,0 ,0") + (match_operand:PSI 2 "nonmemory_operand" "r,Cx3,CX3,n"))) + (clobber (match_scratch:QI 3 "=X,X ,X ,&d")) (clobber (reg:CC REG_CC))] "reload_completed" { @@ -4799,14 +4799,14 @@ return avr_out_bitop (insn, operands, NULL); } - [(set_attr "length" "3,6,6") - (set_attr "adjust_len" "*,out_bitop,out_bitop")]) + [(set_attr "length" "3,6,6,6") + (set_attr "adjust_len" "*,out_bitop,out_bitop,out_bitop")]) (define_insn_and_split "xorsi3" - [(set (match_operand:SI 0 "register_operand" "=??r,r ,r") - (xor:SI (match_operand:SI 1 "register_operand" "%0,0 ,0") - (match_operand:SI 2 "nonmemory_operand" "r,Cx4,n"))) - (clobber (match_scratch:QI 3 "=X,X ,&d"))] + [(set (match_operand:SI 0 "register_operand" "=??r,r ,d ,r") + (xor:SI (match_operand:SI 1 "register_operand" "%0,0 ,0 ,0") + (match_operand:SI 2 "nonmemory_operand" "r,Cx4,CX4,n"))) + (clobber (match_scratch:QI 3 "=X,X ,X ,&d"))] "" "#" "&& reload_completed" @@ -4817,10 +4817,10 @@ (clobber (reg:CC REG_CC))])]) (define_insn "*xorsi3" - [(set (match_operand:SI 0 "register_operand" "=??r,r ,r") - (xor:SI (match_operand:SI 1 "register_operand" "%0,0 ,0") - (match_operand:SI 2 "nonmemory_operand" "r,Cx4,n"))) - (clobber (match_scratch:QI 3 "=X,X ,&d")) + [(set (match_operand:SI 0 "register_operand" "=??r,r ,d ,r") + (xor:SI (match_operand:SI 1 "register_operand" "%0,0 ,0 ,0") + (match_operand:SI 2 "nonmemory_operand" "r,Cx4,CX4,n"))) + (clobber (match_scratch:QI 3 "=X,X ,X ,&d")) (clobber (reg:CC REG_CC))] "reload_completed" { @@ -4832,8 +4832,8 @@ return avr_out_bitop (insn, operands, NULL); } - [(set_attr "length" "4,8,8") - (set_attr "adjust_len" "*,out_bitop,out_bitop")]) + [(set_attr "length" "4,8,8,8") + (set_attr "adjust_len" "*,out_bitop,out_bitop,out_bitop")]) (define_split diff --git a/gcc/config/avr/constraints.md b/gcc/config/avr/constraints.md index fac54da17db..b4e5525d197 100644 --- a/gcc/config/avr/constraints.md +++ b/gcc/config/avr/constraints.md @@ -169,7 +169,7 @@ (match_test "avr_popcount_each_byte (op, 4, (1<<0) | (1<<7) | (1<<8))"))) (define_constraint "Co1" - "Constant 1-byte integer that allows AND by means of SET + BLD." + "Constant 1-byte integer that allows OR by means of SET + BLD." (and (match_code "const_int") (match_test "avr_popcount_each_byte (op, 1, 1<<1)"))) @@ -218,6 +218,21 @@ (and (match_code "const_int") (match_test "avr_popcount_each_byte (op, 4, (1<<0) | (1<<8))"))) +(define_constraint "CX2" + "Constant 2-byte integer that allows XOR without clobber register but requires a d-register." + (and (match_code "const_int") + (match_test "avr_xor_noclobber_dconst (op, 2)"))) + +(define_constraint "CX3" + "Constant 3-byte integer that allows XOR without clobber register but requires a d-register." + (and (match_code "const_int") + (match_test "avr_xor_noclobber_dconst (op, 3)"))) + +(define_constraint "CX4" + "Constant 4-byte integer that allows XOR without clobber register but requires a d-register." + (and (match_code "const_int") + (match_test "avr_xor_noclobber_dconst (op, 4)"))) + (define_constraint "Csp" "Integer constant in the range -11 @dots{} 6." (and (match_code "const_int")