target/82931: Make a pattern more generic to match more bit-transfers.
There is already a pattern in avr.md that matches single-bit transfers from one register to another one, but it only handled bit 0 of 8-bit registers. This change makes that pattern more generic so it matches more of similar single-bit transfers. gcc/ PR target/82931 * config/avr/avr.md (*movbitqi.0): Rename to *movbit<mode>.0-6. Handle any bit position and use mode QISI. * config/avr/avr.cc (avr_rtx_costs_1) [IOR]: Return a cost of 2 insns for bit-transfer of respective style. gcc/testsuite/ PR target/82931 * gcc.target/avr/pr82931.c: New test.
This commit is contained in:
parent
e80487dcbe
commit
a499ab08d1
@ -10844,6 +10844,15 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
|
||||
*total += COSTS_N_INSNS (1);
|
||||
return true;
|
||||
}
|
||||
if (IOR == code
|
||||
&& AND == GET_CODE (XEXP (x, 0))
|
||||
&& AND == GET_CODE (XEXP (x, 1))
|
||||
&& single_zero_operand (XEXP (XEXP (x, 0), 1), mode))
|
||||
{
|
||||
// Open-coded bit transfer.
|
||||
*total = COSTS_N_INSNS (2);
|
||||
return true;
|
||||
}
|
||||
*total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
|
||||
*total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
|
||||
if (!CONST_INT_P (XEXP (x, 1)))
|
||||
|
@ -9097,16 +9097,20 @@
|
||||
"bst %3,0\;bld %0,%4"
|
||||
[(set_attr "length" "2")])
|
||||
|
||||
;; Move bit $3.0 into bit $0.0.
|
||||
;; For bit 0, combiner generates slightly different pattern.
|
||||
(define_insn "*movbitqi.0"
|
||||
[(set (match_operand:QI 0 "register_operand" "=r")
|
||||
(ior:QI (and:QI (match_operand:QI 1 "register_operand" "0")
|
||||
(match_operand:QI 2 "single_zero_operand" "n"))
|
||||
(and:QI (match_operand:QI 3 "register_operand" "r")
|
||||
(const_int 1))))]
|
||||
"0 == exact_log2 (~INTVAL(operands[2]) & GET_MODE_MASK (QImode))"
|
||||
"bst %3,0\;bld %0,0"
|
||||
;; Move bit $3.x into bit $0.x.
|
||||
(define_insn "*movbit<mode>.0-6"
|
||||
[(set (match_operand:QISI 0 "register_operand" "=r")
|
||||
(ior:QISI (and:QISI (match_operand:QISI 1 "register_operand" "0")
|
||||
(match_operand:QISI 2 "single_zero_operand" "n"))
|
||||
(and:QISI (match_operand:QISI 3 "register_operand" "r")
|
||||
(match_operand:QISI 4 "single_one_operand" "n"))))]
|
||||
"GET_MODE_MASK(<MODE>mode)
|
||||
== (GET_MODE_MASK(<MODE>mode) & (INTVAL(operands[2]) ^ INTVAL(operands[4])))"
|
||||
{
|
||||
auto bitmask = GET_MODE_MASK (<MODE>mode) & UINTVAL (operands[4]);
|
||||
operands[4] = GEN_INT (exact_log2 (bitmask));
|
||||
return "bst %T3%T4" CR_TAB "bld %T0%T4";
|
||||
}
|
||||
[(set_attr "length" "2")])
|
||||
|
||||
;; Move bit $2.0 into bit $0.7.
|
||||
|
29
gcc/testsuite/gcc.target/avr/pr82931.c
Normal file
29
gcc/testsuite/gcc.target/avr/pr82931.c
Normal file
@ -0,0 +1,29 @@
|
||||
/* { dg-options "-Os" } */
|
||||
/* { dg-final { scan-assembler-times "bst" 4 } } */
|
||||
/* { dg-final { scan-assembler-times "bld" 4 } } */
|
||||
|
||||
typedef __UINT8_TYPE__ uint8_t;
|
||||
typedef __UINT16_TYPE__ uint16_t;
|
||||
|
||||
#define BitMask (1u << 14)
|
||||
#define Bit8Mask ((uint8_t) (1u << 4))
|
||||
|
||||
void merge1_8 (uint8_t *dst, const uint8_t *src)
|
||||
{
|
||||
*dst = (*src & Bit8Mask) | (*dst & ~ Bit8Mask);
|
||||
}
|
||||
|
||||
void merge2_8 (uint8_t *dst, const uint8_t *src)
|
||||
{
|
||||
*dst ^= (*dst ^ *src) & Bit8Mask;
|
||||
}
|
||||
|
||||
void merge1_16 (uint16_t *dst, const uint16_t *src)
|
||||
{
|
||||
*dst = (*src & BitMask) | (*dst & ~ BitMask);
|
||||
}
|
||||
|
||||
void merge2_16 (uint16_t *dst, const uint16_t *src)
|
||||
{
|
||||
*dst ^= (*dst ^ *src) & BitMask;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user