public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
From: Michael Meissner <meissner@gcc.gnu.org>
To: gcc-cvs@gcc.gnu.org
Subject: [gcc(refs/users/meissner/heads/work122)] Fix power10 fusion and -fstack-protector, PR target/105325
Date: Fri,  9 Jun 2023 21:04:05 +0000 (GMT)	[thread overview]
Message-ID: <20230609210405.2B8DE3858D35@sourceware.org> (raw)

https://gcc.gnu.org/g:838ca32dc66c8587ff3730fdb71b07392ed046f6

commit 838ca32dc66c8587ff3730fdb71b07392ed046f6
Author: Michael Meissner <meissner@linux.ibm.com>
Date:   Fri Jun 9 17:03:42 2023 -0400

    Fix power10 fusion and -fstack-protector, PR target/105325
    
    This patch fixes an issue where if you use the -fstack-protector and
    -mcpu=power10 options and you have a large stack frame, the GCC compiler will
    generate a LWA instruction with a large offset.
    
    There are several problems with the current GCC:
    
        1)  The constraints in fusion.md (generated by genfusion.pl) use "m" for LWA
            and LD, when they should use "YZ".
    
        2)  The calls to address_is_non_pfx_d_or_x doesn't work with lwa using
            SImode as the mode.  You need to pass in DImode instead of SImode.  This
            is to allow lwz to be treated differently than lwa.
    
        3)  The rules for automatically setting the prefixed attribute were not
            checking that these fused load and compare immediate fusion operations
            might have prefixed addresses.
    
        4)  We should use lwa_operand for lwa instead of ds_form_mem_operand.  The
            lwa_operand has some additional checks for the lwa instruction.
    
    The fix is to modify genfusion.pl that it sets the "YZ" constraint instead of
    "m" for the ld and lwa instructions.
    
    This patch also passes DImode to the address_is_non_pfx_d_or_x function for the
    lwa instruction so that it properly cheks for DS form restrictions when
    splitting the insn because it won't fuse.
    
    This patch also modifies the prefixed attribute so that it checks load + compare
    immediate instructions for be a load instruction.  This means that the
    lwa_cmpdi_cr0_SI_clobber_CC_none insn must ask for a DImode scratch register
    instead of SImode scratch register and also set the sign_extend attribute.  The
    code for checking if a load is a lwa expects that the register is DImode, the
    memory is SImode, and the sign_extend attribute is set.
    
    I also added a test case for this condition.
    
    2023-06-08   Michael Meissner  <meissner@linux.ibm.com>
    
    gcc/
    
            * config/rs6000/genfusion.pl (gen_ld_cmpi_p10_one): Fix problems that
            allowed prefixed lwa to be generated.
            * config/rs6000/fusion.md: Regenerate.
            * config/rs6000/rs6000.md (prefixed attribute): Add support for load
            plus compare immediate fused insns.
    
    gcc/testsuite/
    
            * g++.target/powerpc/pr105325.C: New test.

Diff:
---
 gcc/config/rs6000/fusion.md                 | 39 ++++++++++++++++-------------
 gcc/config/rs6000/genfusion.pl              | 26 ++++++++++++++++---
 gcc/config/rs6000/rs6000.md                 |  2 +-
 gcc/testsuite/g++.target/powerpc/pr105325.C | 26 +++++++++++++++++++
 4 files changed, 71 insertions(+), 22 deletions(-)

diff --git a/gcc/config/rs6000/fusion.md b/gcc/config/rs6000/fusion.md
index d45fb138a70..be1f6384c5d 100644
--- a/gcc/config/rs6000/fusion.md
+++ b/gcc/config/rs6000/fusion.md
@@ -22,7 +22,7 @@
 ;; load mode is DI result mode is clobber compare mode is CC extend is none
 (define_insn_and_split "*ld_cmpdi_cr0_DI_clobber_CC_none"
   [(set (match_operand:CC 2 "cc_reg_operand" "=x")
-        (compare:CC (match_operand:DI 1 "ds_form_mem_operand" "m")
+        (compare:CC (match_operand:DI 1 "ds_form_mem_operand" "YZ")
                     (match_operand:DI 3 "const_m1_to_1_operand" "n")))
    (clobber (match_scratch:DI 0 "=r"))]
   "(TARGET_P10_FUSION)"
@@ -43,7 +43,7 @@
 ;; load mode is DI result mode is clobber compare mode is CCUNS extend is none
 (define_insn_and_split "*ld_cmpldi_cr0_DI_clobber_CCUNS_none"
   [(set (match_operand:CCUNS 2 "cc_reg_operand" "=x")
-        (compare:CCUNS (match_operand:DI 1 "ds_form_mem_operand" "m")
+        (compare:CCUNS (match_operand:DI 1 "ds_form_mem_operand" "YZ")
                        (match_operand:DI 3 "const_0_to_1_operand" "n")))
    (clobber (match_scratch:DI 0 "=r"))]
   "(TARGET_P10_FUSION)"
@@ -64,7 +64,7 @@
 ;; load mode is DI result mode is DI compare mode is CC extend is none
 (define_insn_and_split "*ld_cmpdi_cr0_DI_DI_CC_none"
   [(set (match_operand:CC 2 "cc_reg_operand" "=x")
-        (compare:CC (match_operand:DI 1 "ds_form_mem_operand" "m")
+        (compare:CC (match_operand:DI 1 "ds_form_mem_operand" "YZ")
                     (match_operand:DI 3 "const_m1_to_1_operand" "n")))
    (set (match_operand:DI 0 "gpc_reg_operand" "=r") (match_dup 1))]
   "(TARGET_P10_FUSION)"
@@ -85,7 +85,7 @@
 ;; load mode is DI result mode is DI compare mode is CCUNS extend is none
 (define_insn_and_split "*ld_cmpldi_cr0_DI_DI_CCUNS_none"
   [(set (match_operand:CCUNS 2 "cc_reg_operand" "=x")
-        (compare:CCUNS (match_operand:DI 1 "ds_form_mem_operand" "m")
+        (compare:CCUNS (match_operand:DI 1 "ds_form_mem_operand" "YZ")
                        (match_operand:DI 3 "const_0_to_1_operand" "n")))
    (set (match_operand:DI 0 "gpc_reg_operand" "=r") (match_dup 1))]
   "(TARGET_P10_FUSION)"
@@ -103,24 +103,25 @@
    (set_attr "length" "8")])
 
 ;; load-cmpi fusion pattern generated by gen_ld_cmpi_p10
-;; load mode is SI result mode is clobber compare mode is CC extend is none
-(define_insn_and_split "*lwa_cmpdi_cr0_SI_clobber_CC_none"
+;; load mode is SI result mode is clobber compare mode is CC extend is sign
+(define_insn_and_split "*lwa_cmpdi_cr0_SI_clobber_CC_sign"
   [(set (match_operand:CC 2 "cc_reg_operand" "=x")
-        (compare:CC (match_operand:SI 1 "ds_form_mem_operand" "m")
+        (compare:CC (match_operand:SI 1 "lwa_operand" "YZ")
                     (match_operand:SI 3 "const_m1_to_1_operand" "n")))
-   (clobber (match_scratch:SI 0 "=r"))]
+   (clobber (match_scratch:DI 0 "=r"))]
   "(TARGET_P10_FUSION)"
   "lwa%X1 %0,%1\;cmpdi %2,%0,%3"
   "&& reload_completed
    && (cc_reg_not_cr0_operand (operands[2], CCmode)
        || !address_is_non_pfx_d_or_x (XEXP (operands[1], 0),
-                                      SImode, NON_PREFIXED_DS))"
-  [(set (match_dup 0) (match_dup 1))
+                                      DImode, NON_PREFIXED_DS))"
+  [(set (match_dup 0) (sign_extend:DI (match_dup 1)))
    (set (match_dup 2)
         (compare:CC (match_dup 0) (match_dup 3)))]
   ""
   [(set_attr "type" "fused_load_cmpi")
    (set_attr "cost" "8")
+    (set_attr "sign_extend" "yes")
    (set_attr "length" "8")])
 
 ;; load-cmpi fusion pattern generated by gen_ld_cmpi_p10
@@ -145,10 +146,10 @@
    (set_attr "length" "8")])
 
 ;; load-cmpi fusion pattern generated by gen_ld_cmpi_p10
-;; load mode is SI result mode is SI compare mode is CC extend is none
-(define_insn_and_split "*lwa_cmpdi_cr0_SI_SI_CC_none"
+;; load mode is SI result mode is SI compare mode is CC extend is sign
+(define_insn_and_split "*lwa_cmpdi_cr0_SI_SI_CC_sign"
   [(set (match_operand:CC 2 "cc_reg_operand" "=x")
-        (compare:CC (match_operand:SI 1 "ds_form_mem_operand" "m")
+        (compare:CC (match_operand:SI 1 "lwa_operand" "YZ")
                     (match_operand:SI 3 "const_m1_to_1_operand" "n")))
    (set (match_operand:SI 0 "gpc_reg_operand" "=r") (match_dup 1))]
   "(TARGET_P10_FUSION)"
@@ -156,13 +157,14 @@
   "&& reload_completed
    && (cc_reg_not_cr0_operand (operands[2], CCmode)
        || !address_is_non_pfx_d_or_x (XEXP (operands[1], 0),
-                                      SImode, NON_PREFIXED_DS))"
-  [(set (match_dup 0) (match_dup 1))
+                                      DImode, NON_PREFIXED_DS))"
+  [(set (match_dup 0) (sign_extend:SI (match_dup 1)))
    (set (match_dup 2)
         (compare:CC (match_dup 0) (match_dup 3)))]
   ""
   [(set_attr "type" "fused_load_cmpi")
    (set_attr "cost" "8")
+    (set_attr "sign_extend" "yes")
    (set_attr "length" "8")])
 
 ;; load-cmpi fusion pattern generated by gen_ld_cmpi_p10
@@ -190,7 +192,7 @@
 ;; load mode is SI result mode is EXTSI compare mode is CC extend is sign
 (define_insn_and_split "*lwa_cmpdi_cr0_SI_EXTSI_CC_sign"
   [(set (match_operand:CC 2 "cc_reg_operand" "=x")
-        (compare:CC (match_operand:SI 1 "ds_form_mem_operand" "m")
+        (compare:CC (match_operand:SI 1 "lwa_operand" "YZ")
                     (match_operand:SI 3 "const_m1_to_1_operand" "n")))
    (set (match_operand:EXTSI 0 "gpc_reg_operand" "=r") (sign_extend:EXTSI (match_dup 1)))]
   "(TARGET_P10_FUSION)"
@@ -198,13 +200,14 @@
   "&& reload_completed
    && (cc_reg_not_cr0_operand (operands[2], CCmode)
        || !address_is_non_pfx_d_or_x (XEXP (operands[1], 0),
-                                      SImode, NON_PREFIXED_DS))"
+                                      DImode, NON_PREFIXED_DS))"
   [(set (match_dup 0) (sign_extend:EXTSI (match_dup 1)))
    (set (match_dup 2)
         (compare:CC (match_dup 0) (match_dup 3)))]
   ""
   [(set_attr "type" "fused_load_cmpi")
    (set_attr "cost" "8")
+    (set_attr "sign_extend" "yes")
    (set_attr "length" "8")])
 
 ;; load-cmpi fusion pattern generated by gen_ld_cmpi_p10
@@ -247,6 +250,7 @@
   ""
   [(set_attr "type" "fused_load_cmpi")
    (set_attr "cost" "8")
+    (set_attr "sign_extend" "yes")
    (set_attr "length" "8")])
 
 ;; load-cmpi fusion pattern generated by gen_ld_cmpi_p10
@@ -289,6 +293,7 @@
   ""
   [(set_attr "type" "fused_load_cmpi")
    (set_attr "cost" "8")
+    (set_attr "sign_extend" "yes")
    (set_attr "length" "8")])
 
 ;; load-cmpi fusion pattern generated by gen_ld_cmpi_p10
diff --git a/gcc/config/rs6000/genfusion.pl b/gcc/config/rs6000/genfusion.pl
index 82e8f863b02..7016f9c7512 100755
--- a/gcc/config/rs6000/genfusion.pl
+++ b/gcc/config/rs6000/genfusion.pl
@@ -59,12 +59,17 @@ sub gen_ld_cmpi_p10_one
 
   my $np = "NON_PREFIXED_D";
   my $mempred = "non_update_memory_operand";
+  my $lmode_prefix_call = $lmode;
   my $extend;
 
   if ($ccmode eq "CC") {
-    # ld and lwa are both DS-FORM.
+    # ld and lwa are both DS-FORM.  lwa needs to pass DImode to
+    # address_is_non_pfx_d_or_x so that it is properly treated as a DS mode
+    # instruction.
     ($lmode =~ /^[SD]I$/) and $np = "NON_PREFIXED_DS";
-    ($lmode =~ /^[SD]I$/) and $mempred = "ds_form_mem_operand";
+    ($lmode eq "DI") and $mempred = "ds_form_mem_operand";
+    ($lmode eq "SI") and $mempred = "lwa_operand";
+    ($lmode eq "SI") and $lmode_prefix_call = "DI";
   } else {
     if ($lmode eq "DI") {
       # ld is DS-form, but lwz is not.
@@ -81,22 +86,28 @@ sub gen_ld_cmpi_p10_one
 
   # For clobber, we need a SI/DI reg in case we
   # split because we have to sign/zero extend.
+  # for lwa, we need a DImode temporary to properly signal that
+  # lwa is a ds-form instruction.
   my $clobbermode = ($lmode =~ /^[QH]I$/) ? "GPR" : $lmode;
   if ($result =~ /^EXT/ || $result eq "GPR" || $clobbermode eq "GPR") {
     # We always need extension if result > lmode.
     $extend = ($ccmode eq "CC") ? "sign" : "zero";
+  } elsif ($ccmode eq "CC" && $lmode eq "SI") {
+     $clobbermode = "DI";
+     $extend = "sign";
   } else {
     # Result of SI/DI does not need sign extension.
     $extend = "none";
   }
 
   my $ldst = mode_to_ldst_char($lmode);
+  my $constraint = ($np eq "NON_PREFIXED_DS") ? "YZ" : "m";
   print <<HERE;
 ;; load-cmpi fusion pattern generated by gen_ld_cmpi_p10
 ;; load mode is $lmode result mode is $result compare mode is $ccmode extend is $extend
 (define_insn_and_split "*l${ldst}${echr}_cmp${cmpl}di_cr0_${lmode}_${result}_${ccmode}_${extend}"
   [(set (match_operand:${ccmode} 2 "cc_reg_operand" "=x")
-        (compare:${ccmode} (match_operand:${lmode} 1 "${mempred}" "m")
+        (compare:${ccmode} (match_operand:${lmode} 1 "${mempred}" "${constraint}")
 HERE
   print "   " if $ccmode eq "CCUNS";
 print <<HERE;
@@ -123,7 +134,7 @@ HERE
   "&& reload_completed
    && (cc_reg_not_cr0_operand (operands[2], CCmode)
        || !address_is_non_pfx_d_or_x (XEXP (operands[1], 0),
-                                      ${lmode}mode, ${np}))"
+                                      ${lmode_prefix_call}mode, ${np}))"
 HERE
 
   if ($extend eq "none") {
@@ -140,6 +151,13 @@ HERE
   ""
   [(set_attr "type" "fused_load_cmpi")
    (set_attr "cost" "8")
+HERE
+
+  if ($ccmode eq "CC" && $lmode ne "DI") {
+    print "    (set_attr \"sign_extend\" \"yes\")\n";
+  }
+
+  print <<HERE
    (set_attr "length" "8")])
 
 HERE
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index b0db8ae508d..ed2f06e56ac 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -302,7 +302,7 @@
 	      (eq_attr "maybe_prefixed" "no"))
 	 (const_string "no")
 
-	 (eq_attr "type" "load,fpload,vecload")
+	 (eq_attr "type" "load,fpload,vecload,fused_load_cmpi")
 	 (if_then_else (match_test "prefixed_load_p (insn)")
 		       (const_string "yes")
 		       (const_string "no"))
diff --git a/gcc/testsuite/g++.target/powerpc/pr105325.C b/gcc/testsuite/g++.target/powerpc/pr105325.C
new file mode 100644
index 00000000000..d0e66a0b897
--- /dev/null
+++ b/gcc/testsuite/g++.target/powerpc/pr105325.C
@@ -0,0 +1,26 @@
+/* { dg-do assemble } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target power10_ok } */
+/* { dg-require-effective-target powerpc_prefixed_addr } */
+/* { dg-options "-O2 -mdejagnu-cpu=power10 -fstack-protector" } */
+
+/* Test that power10 fusion does not generate an LWA/CMPDI instruction pair
+   instead of PLWZ/CMPWI.  Ultimately the code was dying because the fusion
+   load + compare -1/0/1 patterns did not handle the possibility that the load
+   might be prefixed.  The -fstack-protector option is needed to show the
+   bug.  */
+
+struct Ath__array1D {
+  int _current;
+  int getCnt() { return _current; }
+};
+struct extMeasure {
+  int _mapTable[10000];
+  Ath__array1D _metRCTable;
+};
+void measureRC() {
+  extMeasure m;
+  for (; m._metRCTable.getCnt();)
+    for (;;)
+      ;
+}

             reply	other threads:[~2023-06-09 21:04 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-06-09 21:04 Michael Meissner [this message]
  -- strict thread matches above, loose matches on Subject: below --
2023-06-13 23:24 Michael Meissner
2023-06-13 17:21 Michael Meissner
2023-06-13  2:57 Michael Meissner
2023-06-09  6:08 Michael Meissner
2023-06-09  4:17 Michael Meissner
2023-06-09  1:32 Michael Meissner
2023-06-08 21:20 Michael Meissner
2023-06-08 20:23 Michael Meissner
2023-06-08 16:53 Michael Meissner
2023-06-08 14:38 Michael Meissner
2023-06-07 20:58 Michael Meissner
2023-06-07 18:56 Michael Meissner

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230609210405.2B8DE3858D35@sourceware.org \
    --to=meissner@gcc.gnu.org \
    --cc=gcc-cvs@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).