diff mbox series

[avr,applied] Fix PR87376: Wrong code with __memx and long long addition

Message ID 3b00ab65-ee3f-46a9-99e8-40dd24113d03@gjlay.de
State New
Headers show
Series [avr,applied] Fix PR87376: Wrong code with __memx and long long addition | expand

Commit Message

Georg-Johann Lay July 5, 2024, 11:21 a.m. UTC
The DImode expanders from avr-dimode.md have code like

emit_move_insn(acc_a, operands[1])

where acc_a is a hard register and operands[1] may be a
mem reference to a non-generic address-space. The latter
may require a libcall, and since DImode moves are split into
8 QImode moves, these libcalls might clobber some of the
hard regs that hold acc_a or acc_b.

This patch simply denies non-generic address-space refs
as DImode expander's inputs.

Johann

--

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-bit 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.
diff mbox series

Patch

diff --git a/gcc/config/avr/avr-dimode.md b/gcc/config/avr/avr-dimode.md
index 4b74e77e5e5..c357213e211 100644
--- a/gcc/config/avr/avr-dimode.md
+++ b/gcc/config/avr/avr-dimode.md
@@ -62,8 +62,8 @@  (define_mode_iterator ALL8S [ DQ  DA  TA])
 ;; "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 @@  (define_insn "*add<mode>3_const_insn"
 ;; "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_insn "*sub<mode>3_const_insn"
 
 (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_insn "*<code_stdname><mode>3_const_insn"
 
 (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_insn "*<code_stdname><mode>3_const_insn"
 
 (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 @@  (define_code_iterator di_shifts
 ;; "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 @@  (define_insn "*<code_stdname><mode>3_insn"
 ;; "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 00000000000..c31a4a9dda5
--- /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;
+}