Tighten predicates for p10 ld/cmpi fusion
authorAaron Sawdey <acsawdey@linux.ibm.com>
Sun, 7 Mar 2021 20:47:31 +0000 (14:47 -0600)
committerAaron Sawdey <acsawdey@linux.ibm.com>
Tue, 9 Mar 2021 02:49:47 +0000 (20:49 -0600)
PR99070 is caused by a fusion pattern matching that the individual
instructions do not match when it is split later. In this case the
ld+cmpi patterns were allowing a d-form load address, which the split
condition would rightly split, however that left us with something that
could not be matched by a ds-form ld instruction, hence the ICE. This
only happened if the target cpu was not power10 -- if we were targeting
power10 then a prefixed pld instruction would get generated because that
can handle d-form. However this is not optimal code either.

So the solution is a new predicate (ds_form_mem_operand) that only
accepts what we can take as for a ds-form load. Then a small
modification of the genfusion.pl script changes the relevant
ld+cmpi patterns to use the new predicate.

gcc/ChangeLog

PR target/99070
* config/rs6000/predicates.md (ds_form_mem_operand) New
predicate.
* config/rs6000/genfusion.pl (gen_ld_cmpi_p10) Use
ds_form_mem_operand in ld/lwa patterns.
* config/rs6000/fusion.md: Regenerate file.

gcc/config/rs6000/fusion.md
gcc/config/rs6000/genfusion.pl
gcc/config/rs6000/predicates.md

index 737a6da..56478fc 100644 (file)
@@ -1,7 +1,6 @@
-;; -*- buffer-read-only: t -*-
 ;; Generated automatically by genfusion.pl
 
-;; Copyright (C) 2020 Free Software Foundation, Inc.
+;; Copyright (C) 2020,2021 Free Software Foundation, Inc.
 ;;
 ;; This file is part of GCC.
 ;;
 ;; 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 "non_update_memory_operand" "m")
-                 (match_operand:DI 3 "const_m1_to_1_operand" "n")))
+        (compare:CC (match_operand:DI 1 "ds_form_mem_operand" "m")
+                    (match_operand:DI 3 "const_m1_to_1_operand" "n")))
    (clobber (match_scratch:DI 0 "=r"))]
   "(TARGET_P10_FUSION && TARGET_P10_FUSION_LD_CMPI)"
-  "ld%X1 %0,%1\;cmpdi 0,%0,%3"
+  "ld%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), DImode, NON_PREFIXED_DS))"
+       || !address_is_non_pfx_d_or_x (XEXP (operands[1], 0),
+                                      DImode, NON_PREFIXED_DS))"
   [(set (match_dup 0) (match_dup 1))
    (set (match_dup 2)
-        (compare:CC (match_dup 0)
-                   (match_dup 3)))]
+        (compare:CC (match_dup 0) (match_dup 3)))]
   ""
   [(set_attr "type" "load")
    (set_attr "cost" "8")
 ;; 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 "non_update_memory_operand" "m")
-                 (match_operand:DI 3 "const_0_to_1_operand" "n")))
+        (compare:CCUNS (match_operand:DI 1 "ds_form_mem_operand" "m")
+                       (match_operand:DI 3 "const_0_to_1_operand" "n")))
    (clobber (match_scratch:DI 0 "=r"))]
   "(TARGET_P10_FUSION && TARGET_P10_FUSION_LD_CMPI)"
-  "ld%X1 %0,%1\;cmpldi 0,%0,%3"
+  "ld%X1 %0,%1\;cmpldi %2,%0,%3"
   "&& reload_completed
    && (cc_reg_not_cr0_operand (operands[2], CCmode)
-       || !address_is_non_pfx_d_or_x (XEXP (operands[1],0), DImode, NON_PREFIXED_DS))"
+       || !address_is_non_pfx_d_or_x (XEXP (operands[1], 0),
+                                      DImode, NON_PREFIXED_DS))"
   [(set (match_dup 0) (match_dup 1))
    (set (match_dup 2)
-        (compare:CCUNS (match_dup 0)
-                   (match_dup 3)))]
+        (compare:CCUNS (match_dup 0) (match_dup 3)))]
   ""
   [(set_attr "type" "load")
    (set_attr "cost" "8")
 ;; 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 "non_update_memory_operand" "m")
-                 (match_operand:DI 3 "const_m1_to_1_operand" "n")))
+        (compare:CC (match_operand:DI 1 "ds_form_mem_operand" "m")
+                    (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 && TARGET_P10_FUSION_LD_CMPI)"
-  "ld%X1 %0,%1\;cmpdi 0,%0,%3"
+  "ld%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), DImode, NON_PREFIXED_DS))"
+       || !address_is_non_pfx_d_or_x (XEXP (operands[1], 0),
+                                      DImode, NON_PREFIXED_DS))"
   [(set (match_dup 0) (match_dup 1))
    (set (match_dup 2)
-        (compare:CC (match_dup 0)
-                   (match_dup 3)))]
+        (compare:CC (match_dup 0) (match_dup 3)))]
   ""
   [(set_attr "type" "load")
    (set_attr "cost" "8")
 ;; 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 "non_update_memory_operand" "m")
-                 (match_operand:DI 3 "const_0_to_1_operand" "n")))
+        (compare:CCUNS (match_operand:DI 1 "ds_form_mem_operand" "m")
+                       (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 && TARGET_P10_FUSION_LD_CMPI)"
-  "ld%X1 %0,%1\;cmpldi 0,%0,%3"
+  "ld%X1 %0,%1\;cmpldi %2,%0,%3"
   "&& reload_completed
    && (cc_reg_not_cr0_operand (operands[2], CCmode)
-       || !address_is_non_pfx_d_or_x (XEXP (operands[1],0), DImode, NON_PREFIXED_DS))"
+       || !address_is_non_pfx_d_or_x (XEXP (operands[1], 0),
+                                      DImode, NON_PREFIXED_DS))"
   [(set (match_dup 0) (match_dup 1))
    (set (match_dup 2)
-        (compare:CCUNS (match_dup 0)
-                   (match_dup 3)))]
+        (compare:CCUNS (match_dup 0) (match_dup 3)))]
   ""
   [(set_attr "type" "load")
    (set_attr "cost" "8")
 ;; 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"
   [(set (match_operand:CC 2 "cc_reg_operand" "=x")
-        (compare:CC (match_operand:SI 1 "non_update_memory_operand" "m")
-                 (match_operand:SI 3 "const_m1_to_1_operand" "n")))
+        (compare:CC (match_operand:SI 1 "ds_form_mem_operand" "m")
+                    (match_operand:SI 3 "const_m1_to_1_operand" "n")))
    (clobber (match_scratch:SI 0 "=r"))]
   "(TARGET_P10_FUSION && TARGET_P10_FUSION_LD_CMPI)"
-  "lwa%X1 %0,%1\;cmpdi 0,%0,%3"
+  "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))"
+       || !address_is_non_pfx_d_or_x (XEXP (operands[1], 0),
+                                      SImode, NON_PREFIXED_DS))"
   [(set (match_dup 0) (match_dup 1))
    (set (match_dup 2)
-        (compare:CC (match_dup 0)
-                   (match_dup 3)))]
+        (compare:CC (match_dup 0) (match_dup 3)))]
   ""
   [(set_attr "type" "load")
    (set_attr "cost" "8")
 (define_insn_and_split "*lwz_cmpldi_cr0_SI_clobber_CCUNS_none"
   [(set (match_operand:CCUNS 2 "cc_reg_operand" "=x")
         (compare:CCUNS (match_operand:SI 1 "non_update_memory_operand" "m")
-                 (match_operand:SI 3 "const_0_to_1_operand" "n")))
+                       (match_operand:SI 3 "const_0_to_1_operand" "n")))
    (clobber (match_scratch:SI 0 "=r"))]
   "(TARGET_P10_FUSION && TARGET_P10_FUSION_LD_CMPI)"
-  "lwz%X1 %0,%1\;cmpldi 0,%0,%3"
+  "lwz%X1 %0,%1\;cmpldi %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_D))"
+       || !address_is_non_pfx_d_or_x (XEXP (operands[1], 0),
+                                      SImode, NON_PREFIXED_D))"
   [(set (match_dup 0) (match_dup 1))
    (set (match_dup 2)
-        (compare:CCUNS (match_dup 0)
-                   (match_dup 3)))]
+        (compare:CCUNS (match_dup 0) (match_dup 3)))]
   ""
   [(set_attr "type" "load")
    (set_attr "cost" "8")
 ;; 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"
   [(set (match_operand:CC 2 "cc_reg_operand" "=x")
-        (compare:CC (match_operand:SI 1 "non_update_memory_operand" "m")
-                 (match_operand:SI 3 "const_m1_to_1_operand" "n")))
+        (compare:CC (match_operand:SI 1 "ds_form_mem_operand" "m")
+                    (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 && TARGET_P10_FUSION_LD_CMPI)"
-  "lwa%X1 %0,%1\;cmpdi 0,%0,%3"
+  "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))"
+       || !address_is_non_pfx_d_or_x (XEXP (operands[1], 0),
+                                      SImode, NON_PREFIXED_DS))"
   [(set (match_dup 0) (match_dup 1))
    (set (match_dup 2)
-        (compare:CC (match_dup 0)
-                   (match_dup 3)))]
+        (compare:CC (match_dup 0) (match_dup 3)))]
   ""
   [(set_attr "type" "load")
    (set_attr "cost" "8")
 (define_insn_and_split "*lwz_cmpldi_cr0_SI_SI_CCUNS_none"
   [(set (match_operand:CCUNS 2 "cc_reg_operand" "=x")
         (compare:CCUNS (match_operand:SI 1 "non_update_memory_operand" "m")
-                 (match_operand:SI 3 "const_0_to_1_operand" "n")))
+                       (match_operand:SI 3 "const_0_to_1_operand" "n")))
    (set (match_operand:SI 0 "gpc_reg_operand" "=r") (match_dup 1))]
   "(TARGET_P10_FUSION && TARGET_P10_FUSION_LD_CMPI)"
-  "lwz%X1 %0,%1\;cmpldi 0,%0,%3"
+  "lwz%X1 %0,%1\;cmpldi %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_D))"
+       || !address_is_non_pfx_d_or_x (XEXP (operands[1], 0),
+                                      SImode, NON_PREFIXED_D))"
   [(set (match_dup 0) (match_dup 1))
    (set (match_dup 2)
-        (compare:CCUNS (match_dup 0)
-                   (match_dup 3)))]
+        (compare:CCUNS (match_dup 0) (match_dup 3)))]
   ""
   [(set_attr "type" "load")
    (set_attr "cost" "8")
 ;; 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 "non_update_memory_operand" "m")
-                 (match_operand:SI 3 "const_m1_to_1_operand" "n")))
+        (compare:CC (match_operand:SI 1 "ds_form_mem_operand" "m")
+                    (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 && TARGET_P10_FUSION_LD_CMPI)"
-  "lwa%X1 %0,%1\;cmpdi 0,%0,%3"
+  "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))"
+       || !address_is_non_pfx_d_or_x (XEXP (operands[1], 0),
+                                      SImode, 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)))]
+        (compare:CC (match_dup 0) (match_dup 3)))]
   ""
   [(set_attr "type" "load")
    (set_attr "cost" "8")
 (define_insn_and_split "*lwz_cmpldi_cr0_SI_EXTSI_CCUNS_zero"
   [(set (match_operand:CCUNS 2 "cc_reg_operand" "=x")
         (compare:CCUNS (match_operand:SI 1 "non_update_memory_operand" "m")
-                 (match_operand:SI 3 "const_0_to_1_operand" "n")))
+                       (match_operand:SI 3 "const_0_to_1_operand" "n")))
    (set (match_operand:EXTSI 0 "gpc_reg_operand" "=r") (zero_extend:EXTSI (match_dup 1)))]
   "(TARGET_P10_FUSION && TARGET_P10_FUSION_LD_CMPI)"
-  "lwz%X1 %0,%1\;cmpldi 0,%0,%3"
+  "lwz%X1 %0,%1\;cmpldi %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_D))"
+       || !address_is_non_pfx_d_or_x (XEXP (operands[1], 0),
+                                      SImode, NON_PREFIXED_D))"
   [(set (match_dup 0) (zero_extend:EXTSI (match_dup 1)))
    (set (match_dup 2)
-        (compare:CCUNS (match_dup 0)
-                   (match_dup 3)))]
+        (compare:CCUNS (match_dup 0) (match_dup 3)))]
   ""
   [(set_attr "type" "load")
    (set_attr "cost" "8")
 (define_insn_and_split "*lha_cmpdi_cr0_HI_clobber_CC_sign"
   [(set (match_operand:CC 2 "cc_reg_operand" "=x")
         (compare:CC (match_operand:HI 1 "non_update_memory_operand" "m")
-                 (match_operand:HI 3 "const_m1_to_1_operand" "n")))
+                    (match_operand:HI 3 "const_m1_to_1_operand" "n")))
    (clobber (match_scratch:GPR 0 "=r"))]
   "(TARGET_P10_FUSION && TARGET_P10_FUSION_LD_CMPI)"
-  "lha%X1 %0,%1\;cmpdi 0,%0,%3"
+  "lha%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), HImode, NON_PREFIXED_D))"
+       || !address_is_non_pfx_d_or_x (XEXP (operands[1], 0),
+                                      HImode, NON_PREFIXED_D))"
   [(set (match_dup 0) (sign_extend:GPR (match_dup 1)))
    (set (match_dup 2)
-        (compare:CC (match_dup 0)
-                   (match_dup 3)))]
+        (compare:CC (match_dup 0) (match_dup 3)))]
   ""
   [(set_attr "type" "load")
    (set_attr "cost" "8")
 (define_insn_and_split "*lhz_cmpldi_cr0_HI_clobber_CCUNS_zero"
   [(set (match_operand:CCUNS 2 "cc_reg_operand" "=x")
         (compare:CCUNS (match_operand:HI 1 "non_update_memory_operand" "m")
-                 (match_operand:HI 3 "const_0_to_1_operand" "n")))
+                       (match_operand:HI 3 "const_0_to_1_operand" "n")))
    (clobber (match_scratch:GPR 0 "=r"))]
   "(TARGET_P10_FUSION && TARGET_P10_FUSION_LD_CMPI)"
-  "lhz%X1 %0,%1\;cmpldi 0,%0,%3"
+  "lhz%X1 %0,%1\;cmpldi %2,%0,%3"
   "&& reload_completed
    && (cc_reg_not_cr0_operand (operands[2], CCmode)
-       || !address_is_non_pfx_d_or_x (XEXP (operands[1],0), HImode, NON_PREFIXED_D))"
+       || !address_is_non_pfx_d_or_x (XEXP (operands[1], 0),
+                                      HImode, NON_PREFIXED_D))"
   [(set (match_dup 0) (zero_extend:GPR (match_dup 1)))
    (set (match_dup 2)
-        (compare:CCUNS (match_dup 0)
-                   (match_dup 3)))]
+        (compare:CCUNS (match_dup 0) (match_dup 3)))]
   ""
   [(set_attr "type" "load")
    (set_attr "cost" "8")
 (define_insn_and_split "*lha_cmpdi_cr0_HI_EXTHI_CC_sign"
   [(set (match_operand:CC 2 "cc_reg_operand" "=x")
         (compare:CC (match_operand:HI 1 "non_update_memory_operand" "m")
-                 (match_operand:HI 3 "const_m1_to_1_operand" "n")))
+                    (match_operand:HI 3 "const_m1_to_1_operand" "n")))
    (set (match_operand:EXTHI 0 "gpc_reg_operand" "=r") (sign_extend:EXTHI (match_dup 1)))]
   "(TARGET_P10_FUSION && TARGET_P10_FUSION_LD_CMPI)"
-  "lha%X1 %0,%1\;cmpdi 0,%0,%3"
+  "lha%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), HImode, NON_PREFIXED_D))"
+       || !address_is_non_pfx_d_or_x (XEXP (operands[1], 0),
+                                      HImode, NON_PREFIXED_D))"
   [(set (match_dup 0) (sign_extend:EXTHI (match_dup 1)))
    (set (match_dup 2)
-        (compare:CC (match_dup 0)
-                   (match_dup 3)))]
+        (compare:CC (match_dup 0) (match_dup 3)))]
   ""
   [(set_attr "type" "load")
    (set_attr "cost" "8")
 (define_insn_and_split "*lhz_cmpldi_cr0_HI_EXTHI_CCUNS_zero"
   [(set (match_operand:CCUNS 2 "cc_reg_operand" "=x")
         (compare:CCUNS (match_operand:HI 1 "non_update_memory_operand" "m")
-                 (match_operand:HI 3 "const_0_to_1_operand" "n")))
+                       (match_operand:HI 3 "const_0_to_1_operand" "n")))
    (set (match_operand:EXTHI 0 "gpc_reg_operand" "=r") (zero_extend:EXTHI (match_dup 1)))]
   "(TARGET_P10_FUSION && TARGET_P10_FUSION_LD_CMPI)"
-  "lhz%X1 %0,%1\;cmpldi 0,%0,%3"
+  "lhz%X1 %0,%1\;cmpldi %2,%0,%3"
   "&& reload_completed
    && (cc_reg_not_cr0_operand (operands[2], CCmode)
-       || !address_is_non_pfx_d_or_x (XEXP (operands[1],0), HImode, NON_PREFIXED_D))"
+       || !address_is_non_pfx_d_or_x (XEXP (operands[1], 0),
+                                      HImode, NON_PREFIXED_D))"
   [(set (match_dup 0) (zero_extend:EXTHI (match_dup 1)))
    (set (match_dup 2)
-        (compare:CCUNS (match_dup 0)
-                   (match_dup 3)))]
+        (compare:CCUNS (match_dup 0) (match_dup 3)))]
   ""
   [(set_attr "type" "load")
    (set_attr "cost" "8")
 (define_insn_and_split "*lbz_cmpldi_cr0_QI_clobber_CCUNS_zero"
   [(set (match_operand:CCUNS 2 "cc_reg_operand" "=x")
         (compare:CCUNS (match_operand:QI 1 "non_update_memory_operand" "m")
-                 (match_operand:QI 3 "const_0_to_1_operand" "n")))
+                       (match_operand:QI 3 "const_0_to_1_operand" "n")))
    (clobber (match_scratch:GPR 0 "=r"))]
   "(TARGET_P10_FUSION && TARGET_P10_FUSION_LD_CMPI)"
-  "lbz%X1 %0,%1\;cmpldi 0,%0,%3"
+  "lbz%X1 %0,%1\;cmpldi %2,%0,%3"
   "&& reload_completed
    && (cc_reg_not_cr0_operand (operands[2], CCmode)
-       || !address_is_non_pfx_d_or_x (XEXP (operands[1],0), QImode, NON_PREFIXED_D))"
+       || !address_is_non_pfx_d_or_x (XEXP (operands[1], 0),
+                                      QImode, NON_PREFIXED_D))"
   [(set (match_dup 0) (zero_extend:GPR (match_dup 1)))
    (set (match_dup 2)
-        (compare:CCUNS (match_dup 0)
-                   (match_dup 3)))]
+        (compare:CCUNS (match_dup 0) (match_dup 3)))]
   ""
   [(set_attr "type" "load")
    (set_attr "cost" "8")
 (define_insn_and_split "*lbz_cmpldi_cr0_QI_GPR_CCUNS_zero"
   [(set (match_operand:CCUNS 2 "cc_reg_operand" "=x")
         (compare:CCUNS (match_operand:QI 1 "non_update_memory_operand" "m")
-                 (match_operand:QI 3 "const_0_to_1_operand" "n")))
+                       (match_operand:QI 3 "const_0_to_1_operand" "n")))
    (set (match_operand:GPR 0 "gpc_reg_operand" "=r") (zero_extend:GPR (match_dup 1)))]
   "(TARGET_P10_FUSION && TARGET_P10_FUSION_LD_CMPI)"
-  "lbz%X1 %0,%1\;cmpldi 0,%0,%3"
+  "lbz%X1 %0,%1\;cmpldi %2,%0,%3"
   "&& reload_completed
    && (cc_reg_not_cr0_operand (operands[2], CCmode)
-       || !address_is_non_pfx_d_or_x (XEXP (operands[1],0), QImode, NON_PREFIXED_D))"
+       || !address_is_non_pfx_d_or_x (XEXP (operands[1], 0),
+                                      QImode, NON_PREFIXED_D))"
   [(set (match_dup 0) (zero_extend:GPR (match_dup 1)))
    (set (match_dup 2)
-        (compare:CCUNS (match_dup 0)
-                   (match_dup 3)))]
+        (compare:CCUNS (match_dup 0) (match_dup 3)))]
   ""
   [(set_attr "type" "load")
    (set_attr "cost" "8")
index e1c45f5..c86c743 100755 (executable)
@@ -56,7 +56,7 @@ sub mode_to_ldst_char
 sub gen_ld_cmpi_p10
 {
     my ($lmode, $ldst, $clobbermode, $result, $cmpl, $echr, $constpred,
-       $ccmode, $np, $extend, $resultmode);
+       $mempred, $ccmode, $np, $extend, $resultmode);
   LMODE: foreach $lmode ('DI','SI','HI','QI') {
       $ldst = mode_to_ldst_char($lmode);
       $clobbermode = $lmode;
@@ -70,11 +70,13 @@ sub gen_ld_cmpi_p10
        $result = "GPR" if $result eq "EXTQI";
       CCMODE: foreach $ccmode ('CC','CCUNS') {
          $np = "NON_PREFIXED_D";
+         $mempred = "non_update_memory_operand";
          if ( $ccmode eq 'CC' ) {
              next CCMODE if $lmode eq 'QI';
              if ( $lmode eq 'DI' || $lmode eq 'SI' ) {
                  # ld and lwa are both DS-FORM.
                  $np = "NON_PREFIXED_DS";
+                 $mempred = "ds_form_mem_operand";
              }
              $cmpl = "";
              $echr = "a";
@@ -83,6 +85,7 @@ sub gen_ld_cmpi_p10
              if ( $lmode eq 'DI' ) {
                  # ld is DS-form, but lwz is not.
                  $np = "NON_PREFIXED_DS";
+                 $mempred = "ds_form_mem_operand";
              }
              $cmpl = "l";
              $echr = "z";
@@ -105,7 +108,7 @@ sub gen_ld_cmpi_p10
 
          print "(define_insn_and_split \"*l${ldst}${echr}_cmp${cmpl}di_cr0_${lmode}_${result}_${ccmode}_${extend}\"\n";
          print "  [(set (match_operand:${ccmode} 2 \"cc_reg_operand\" \"=x\")\n";
-         print "        (compare:${ccmode} (match_operand:${lmode} 1 \"non_update_memory_operand\" \"m\")\n";
+         print "        (compare:${ccmode} (match_operand:${lmode} 1 \"${mempred}\" \"m\")\n";
          if ($ccmode eq 'CCUNS') { print "   "; }
          print "                    (match_operand:${lmode} 3 \"${constpred}\" \"n\")))\n";
          if ($result eq 'clobber') {
index bd6ef1e..1556514 100644 (file)
   return INTVAL (offset) % 4 == 0;
 })
 
+;; Return 1 if the operand is a memory operand that has a valid address for
+;; a DS-form instruction. I.e. the address has to be either just a register,
+;; or register + const where the two low order bits of const are zero.
+(define_predicate "ds_form_mem_operand"
+  (match_code "subreg,mem")
+{
+  rtx inner, addr, offset;
+
+  inner = op;
+  if (reload_completed && SUBREG_P (inner))
+    inner = SUBREG_REG (inner);
+
+  if (!any_memory_operand (inner, mode))
+    return false;
+
+  addr = XEXP (inner, 0);
+
+  return address_to_insn_form (addr, mode, NON_PREFIXED_DS) == INSN_FORM_DS;
+})
+
 ;; Return 1 if the operand, used inside a MEM, is a SYMBOL_REF.
 (define_predicate "symbol_ref_operand"
   (and (match_code "symbol_ref")