[1/2] rs6000: genfusion: Rewrite load/compare code
Checks
Commit Message
This makes the code more readable, more digestible, more maintainable,
more extensible. That kind of thing. It does that by pulling things
apart a bit, but also making what stays together more cohesive lumps.
The original function was a bunch of loops and early-outs, and then
quite a bit of stuff done per iteration, with the iterations essentially
independent of each other. This patch moves the stuff done for one
iteration to a new _one function.
The second big thing is the stuff printed to the .md file is done in
"here documents" now, which is a lot more readable than having to quote
and escape and double-escape pieces of text. Whitespace inside the
here-document is significant (will be printed as-is), which is a bit
awkward sometimes, or might take some getting used to, but it is also
one of the benefits of using them.
Local variables are declared at first use (or close to first use).
There also shouldn't be many at all, often you can write easier to
read and manage code by omitting to name something that is hard to name
in the first place.
Finally some things are done in more typical, more modern, and tighter
Perl style, for example REs in "if"s or "qw" for lists of constants.
2023-06-06 Segher Boessenkool <segher@kernel.crashing.org>
* config/rs6000/genfusion.pl (gen_ld_cmpi_p10_one): New, rewritten and
split out from...
(gen_ld_cmpi_p10): ... this.
---
gcc/config/rs6000/genfusion.pl | 185 +++++++++++++++++++++++------------------
1 file changed, 103 insertions(+), 82 deletions(-)
@@ -53,92 +53,113 @@ sub mode_to_ldst_char
return '?';
}
+sub gen_ld_cmpi_p10_one
+{
+ my ($lmode, $result, $ccmode) = @_;
+
+ my $np = "NON_PREFIXED_D";
+ my $mempred = "non_update_memory_operand";
+ my $extend;
+
+ if ($ccmode eq "CC") {
+ # ld and lwa are both DS-FORM.
+ ($lmode =~ /^[SD]I$/) and $np = "NON_PREFIXED_DS";
+ ($lmode =~ /^[SD]I$/) and $mempred = "ds_form_mem_operand";
+ } else {
+ if ($lmode eq "DI") {
+ # ld is DS-form, but lwz is not.
+ $np = "NON_PREFIXED_DS";
+ $mempred = "ds_form_mem_operand";
+ }
+ }
+
+ my $cmpl = ($ccmode eq "CC") ? "" : "l";
+ my $echr = ($ccmode eq "CC") ? "a" : "z";
+ if ($lmode eq "DI") { $echr = ""; }
+ my $constpred = ($ccmode eq "CC") ? "const_m1_to_1_operand"
+ : "const_0_to_1_operand";
+
+ # For clobber, we need a SI/DI reg in case we
+ # split because we have to sign/zero extend.
+ 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";
+ } else {
+ # Result of SI/DI does not need sign extension.
+ $extend = "none";
+ }
+
+ my $ldst = mode_to_ldst_char($lmode);
+ 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")
+HERE
+ print " " if $ccmode eq "CCUNS";
+print <<HERE;
+ (match_operand:${lmode} 3 "${constpred}" "n")))
+HERE
+
+ if ($result eq "clobber") {
+ print <<HERE;
+ (clobber (match_scratch:${clobbermode} 0 "=r"))]
+HERE
+ } elsif ($result eq $lmode) {
+ print <<HERE;
+ (set (match_operand:${result} 0 "gpc_reg_operand" "=r") (match_dup 1))]
+HERE
+ } else {
+ print <<HERE;
+ (set (match_operand:${result} 0 "gpc_reg_operand" "=r") (${extend}_extend:${result} (match_dup 1)))]
+HERE
+ }
+
+ print <<HERE;
+ "(TARGET_P10_FUSION)"
+ "l${ldst}${echr}%X1 %0,%1\\;cmp${cmpl}di %2,%0,%3"
+ "&& reload_completed
+ && (cc_reg_not_cr0_operand (operands[2], CCmode)
+ || !address_is_non_pfx_d_or_x (XEXP (operands[1], 0),
+ ${lmode}mode, ${np}))"
+HERE
+
+ if ($extend eq "none") {
+ print " [(set (match_dup 0) (match_dup 1))\n";
+ } elsif ($result eq "clobber") {
+ print " [(set (match_dup 0) (${extend}_extend:${clobbermode} (match_dup 1)))\n";
+ } else {
+ print " [(set (match_dup 0) (${extend}_extend:${result} (match_dup 1)))\n";
+ }
+
+ print <<HERE;
+ (set (match_dup 2)
+ (compare:${ccmode} (match_dup 0) (match_dup 3)))]
+ ""
+ [(set_attr "type" "fused_load_cmpi")
+ (set_attr "cost" "8")
+ (set_attr "length" "8")])
+
+HERE
+}
+
sub gen_ld_cmpi_p10
{
- my ($lmode, $ldst, $clobbermode, $result, $cmpl, $echr, $constpred,
- $mempred, $ccmode, $np, $extend, $resultmode);
- LMODE: foreach $lmode ('DI','SI','HI','QI') {
- $ldst = mode_to_ldst_char($lmode);
- $clobbermode = $lmode;
- # For clobber, we need a SI/DI reg in case we
- # split because we have to sign/zero extend.
- if ($lmode eq 'HI' || $lmode eq 'QI') { $clobbermode = "GPR"; }
- RESULT: foreach $result ('clobber', $lmode, "EXT".$lmode) {
- # EXTDI does not exist, and we cannot directly produce HI/QI results.
- next RESULT if $result eq "EXTDI" || $result eq "HI" || $result eq "QI";
- # Don't allow EXTQI because that would allow HI result which we can't do.
- $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";
- $constpred = "const_m1_to_1_operand";
- } else {
- 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";
- $constpred = "const_0_to_1_operand";
- }
- if ($lmode eq 'DI') { $echr = ""; }
- if ($result =~ m/^EXT/ || $result eq 'GPR' || $clobbermode eq 'GPR') {
- # We always need extension if result > lmode.
- if ( $ccmode eq 'CC' ) {
- $extend = "sign";
- } else {
- $extend = "zero";
- }
- } else {
- # Result of SI/DI does not need sign extension.
- $extend = "none";
- }
- print ";; load-cmpi fusion pattern generated by gen_ld_cmpi_p10\n";
- print ";; load mode is $lmode result mode is $result compare mode is $ccmode extend is $extend\n";
+ foreach my $lmode (qw/DI SI HI QI/) {
+ foreach my $result ("clobber", $lmode, "EXT$lmode") {
+ # EXTDI does not exist, and we cannot directly produce HI/QI results.
+ next if $result =~ /^(QI|HI|EXTDI)$/;
- 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 \"${mempred}\" \"m\")\n";
- if ($ccmode eq 'CCUNS') { print " "; }
- print " (match_operand:${lmode} 3 \"${constpred}\" \"n\")))\n";
- if ($result eq 'clobber') {
- print " (clobber (match_scratch:${clobbermode} 0 \"=r\"))]\n";
- } elsif ($result eq $lmode) {
- print " (set (match_operand:${result} 0 \"gpc_reg_operand\" \"=r\") (match_dup 1))]\n";
- } else {
- print " (set (match_operand:${result} 0 \"gpc_reg_operand\" \"=r\") (${extend}_extend:${result} (match_dup 1)))]\n";
- }
- print " \"(TARGET_P10_FUSION)\"\n";
- print " \"l${ldst}${echr}%X1 %0,%1\\;cmp${cmpl}di %2,%0,%3\"\n";
- print " \"&& reload_completed\n";
- print " && (cc_reg_not_cr0_operand (operands[2], CCmode)\n";
- print " || !address_is_non_pfx_d_or_x (XEXP (operands[1], 0),\n";
- print " ${lmode}mode, ${np}))\"\n";
+ # Don't allow EXTQI because that would allow HI result which we can't do.
+ $result = "GPR" if $result eq "EXTQI";
- if ($extend eq "none") {
- print " [(set (match_dup 0) (match_dup 1))\n";
- } else {
- $resultmode = $result;
- if ( $result eq 'clobber' ) { $resultmode = $clobbermode }
- print " [(set (match_dup 0) (${extend}_extend:${resultmode} (match_dup 1)))\n";
- }
- print " (set (match_dup 2)\n";
- print " (compare:${ccmode} (match_dup 0) (match_dup 3)))]\n";
- print " \"\"\n";
- print " [(set_attr \"type\" \"fused_load_cmpi\")\n";
- print " (set_attr \"cost\" \"8\")\n";
- print " (set_attr \"length\" \"8\")])\n";
- print "\n";
+ foreach my $ccmode (qw/CC CCUNS/) {
+ # We do not have signed single-byte loads.
+ next if ($lmode eq "QI" and $ccmode eq "CC");
+
+ gen_ld_cmpi_p10_one($lmode, $result, $ccmode);
}
}
}