diff options
author | Georg-Johann Lay <avr@gjlay.de> | 2024-07-05 13:22:12 +0200 |
---|---|---|
committer | Georg-Johann Lay <avr@gjlay.de> | 2024-07-05 13:24:43 +0200 |
commit | 23a0935262d6817097406578b1c70563f424804b (patch) | |
tree | f6b2f09d39e5106fb3c5ad1fdb12d1d445d63e94 | |
parent | f63896ff5a4fa4fe451f9ec7f16026eb97ed8e6d (diff) | |
download | gcc-23a0935262d6817097406578b1c70563f424804b.zip gcc-23a0935262d6817097406578b1c70563f424804b.tar.gz gcc-23a0935262d6817097406578b1c70563f424804b.tar.bz2 |
AVR: target/87376 - Use nop_general_operand for DImode inputs.
The avr-dimode.md expanders have code like emit_move_insn(acc_a, operands[1])
where acc_a is a hard register and operands[1] might be a non-generic
address-space memory reference. Such loads may clobber hard regs since
some of them are implemented as libgcc calls /and/ 64-moves are
expanded as eight byte-moves, so that acc_a or acc_b might be clobbered
by such a load.
This patch simply denies non-generic address-space references by using
nop_general_operand for all avr-dimode.md input predicates.
With the patch, all memory loads that require library calls are issued
before the expander codes from avr-dimode.md are run.
PR target/87376
gcc/
* config/avr/avr-dimode.md: Use "nop_general_operand" instead
of "general_operand" as predicate for all input operands.
gcc/testsuite/
* gcc.target/avr/torture/pr87376.c: New test.
-rw-r--r-- | gcc/config/avr/avr-dimode.md | 26 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/avr/torture/pr87376.c | 60 |
2 files changed, 73 insertions, 13 deletions
diff --git a/gcc/config/avr/avr-dimode.md b/gcc/config/avr/avr-dimode.md index 4b74e77..c357213 100644 --- a/gcc/config/avr/avr-dimode.md +++ b/gcc/config/avr/avr-dimode.md @@ -62,8 +62,8 @@ ;; "addta3" "adduta3" (define_expand "add<mode>3" [(parallel [(match_operand:ALL8 0 "general_operand" "") - (match_operand:ALL8 1 "general_operand" "") - (match_operand:ALL8 2 "general_operand" "")])] + (match_operand:ALL8 1 "nop_general_operand") + (match_operand:ALL8 2 "nop_general_operand")])] "avr_have_dimode" { rtx acc_a = gen_rtx_REG (<MODE>mode, ACC_A); @@ -178,8 +178,8 @@ ;; "subta3" "subuta3" (define_expand "sub<mode>3" [(parallel [(match_operand:ALL8 0 "general_operand" "") - (match_operand:ALL8 1 "general_operand" "") - (match_operand:ALL8 2 "general_operand" "")])] + (match_operand:ALL8 1 "nop_general_operand") + (match_operand:ALL8 2 "nop_general_operand")])] "avr_have_dimode" { rtx acc_a = gen_rtx_REG (<MODE>mode, ACC_A); @@ -259,8 +259,8 @@ (define_expand "<code_stdname><mode>3" [(set (match_operand:ALL8S 0 "general_operand" "") - (ss_addsub:ALL8S (match_operand:ALL8S 1 "general_operand" "") - (match_operand:ALL8S 2 "general_operand" "")))] + (ss_addsub:ALL8S (match_operand:ALL8S 1 "nop_general_operand") + (match_operand:ALL8S 2 "nop_general_operand")))] "avr_have_dimode" { rtx acc_a = gen_rtx_REG (<MODE>mode, ACC_A); @@ -332,8 +332,8 @@ (define_expand "<code_stdname><mode>3" [(set (match_operand:ALL8U 0 "general_operand" "") - (us_addsub:ALL8U (match_operand:ALL8U 1 "general_operand" "") - (match_operand:ALL8U 2 "general_operand" "")))] + (us_addsub:ALL8U (match_operand:ALL8U 1 "nop_general_operand") + (match_operand:ALL8U 2 "nop_general_operand")))] "avr_have_dimode" { rtx acc_a = gen_rtx_REG (<MODE>mode, ACC_A); @@ -405,7 +405,7 @@ (define_expand "negdi2" [(parallel [(match_operand:DI 0 "general_operand" "") - (match_operand:DI 1 "general_operand" "")])] + (match_operand:DI 1 "nop_general_operand")])] "avr_have_dimode" { rtx acc_a = gen_rtx_REG (DImode, ACC_A); @@ -602,8 +602,8 @@ ;; "ashluta3" "ashruta3" "lshruta3" "rotluta3" (define_expand "<code_stdname><mode>3" [(parallel [(match_operand:ALL8 0 "general_operand" "") - (di_shifts:ALL8 (match_operand:ALL8 1 "general_operand" "") - (match_operand:QI 2 "general_operand" ""))])] + (di_shifts:ALL8 (match_operand:ALL8 1 "nop_general_operand") + (match_operand:QI 2 "nop_general_operand"))])] "avr_have_dimode" { rtx acc_a = gen_rtx_REG (<MODE>mode, ACC_A); @@ -648,8 +648,8 @@ ;; "mulsidi3" (define_expand "<extend_u>mulsidi3" [(parallel [(match_operand:DI 0 "register_operand" "") - (match_operand:SI 1 "general_operand" "") - (match_operand:SI 2 "general_operand" "") + (match_operand:SI 1 "nop_general_operand") + (match_operand:SI 2 "nop_general_operand") ;; Just to mention the iterator (clobber (any_extend:SI (match_dup 1)))])] "avr_have_dimode diff --git a/gcc/testsuite/gcc.target/avr/torture/pr87376.c b/gcc/testsuite/gcc.target/avr/torture/pr87376.c new file mode 100644 index 0000000..c31a4a9 --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/torture/pr87376.c @@ -0,0 +1,60 @@ +/* { dg-do run { target { ! avr_tiny } } } */ +/* { dg-additional-options "-std=gnu99" } */ + +typedef __UINT64_TYPE__ uint64_t; + +extern const __memx uint64_t aa __asm ("real_aa"); +extern const uint64_t bb __asm ("real_bb"); + +const __memx uint64_t real_aa = 0x1122334455667788; +const uint64_t real_bb = 0x0908070605040302; + +__attribute__((noinline,noclone)) +uint64_t add1 (void) +{ + return aa + bb; +} + +__attribute__((noinline,noclone)) +uint64_t add2 (void) +{ + return bb + aa; +} + +__attribute__((noinline,noclone)) +uint64_t sub1 (void) +{ + return aa - bb; +} + +__attribute__((noinline,noclone)) +uint64_t sub2 (void) +{ + return bb - aa; +} + +__attribute__((noinline,noclone)) +uint64_t neg1 (void) +{ + return -aa; +} + +int main (void) +{ + if (neg1() != -real_aa) + __builtin_exit (__LINE__); + + if (add1() != real_aa + real_bb) + __builtin_exit (__LINE__); + + if (add2() != real_bb + real_aa) + __builtin_exit (__LINE__); + + if (sub1() != real_aa - real_bb) + __builtin_exit (__LINE__); + + if (sub2() != real_bb - real_aa) + __builtin_exit (__LINE__); + + return 0; +} |