aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/rs6000/genfusion.pl
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/rs6000/genfusion.pl')
-rwxr-xr-xgcc/config/rs6000/genfusion.pl37
1 files changed, 30 insertions, 7 deletions
diff --git a/gcc/config/rs6000/genfusion.pl b/gcc/config/rs6000/genfusion.pl
index 82e8f86..4d1f825 100755
--- a/gcc/config/rs6000/genfusion.pl
+++ b/gcc/config/rs6000/genfusion.pl
@@ -61,20 +61,31 @@ sub gen_ld_cmpi_p10_one
my $mempred = "non_update_memory_operand";
my $extend;
+ # We need to special case lwa. The prefixed_load_p function in rs6000.cc
+ # (which determines if a load instruction is prefixed) uses the fact that the
+ # register mode is different from the memory mode, and that the sign_extend
+ # attribute is set to use DS-form rules for the address instead of D-form.
+ # If the register size is the same, prefixed_load_p assumes we are doing a
+ # lwz. We change to use an lwz and word compare if we don't need to sign
+ # extend the SImode value. Otherwise if we need the value, we need to
+ # make sure the insn is marked as ds-form.
+ my $cmp_size_char = ($lmode eq "SI"
+ && $ccmode eq "CC"
+ && $result !~ /^EXT|^DI$/) ? "w" : "d";
+
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";
+ ($lmode eq "DI") and $np = "NON_PREFIXED_DS";
+ ($lmode eq "SI" && $cmp_size_char eq "d") and $np = "NON_PREFIXED_DS";
} 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";
+ my $echr = ($ccmode eq "CC" && $cmp_size_char eq "d") ? "a" : "z";
if ($lmode eq "DI") { $echr = ""; }
my $constpred = ($ccmode eq "CC") ? "const_m1_to_1_operand"
: "const_0_to_1_operand";
@@ -91,12 +102,15 @@ sub gen_ld_cmpi_p10_one
}
my $ldst = mode_to_ldst_char($lmode);
+
+ # DS-form addresses need YZ, and not m.
+ 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}"
+(define_insn_and_split "*l${ldst}${echr}_cmp${cmpl}${cmp_size_char}i_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;
@@ -119,7 +133,7 @@ HERE
print <<HERE;
"(TARGET_P10_FUSION)"
- "l${ldst}${echr}%X1 %0,%1\\;cmp${cmpl}di %2,%0,%3"
+ "l${ldst}${echr}%X1 %0,%1\\;cmp${cmpl}${cmp_size_char}i %2,%0,%3"
"&& reload_completed
&& (cc_reg_not_cr0_operand (operands[2], CCmode)
|| !address_is_non_pfx_d_or_x (XEXP (operands[1], 0),
@@ -140,6 +154,15 @@ HERE
""
[(set_attr "type" "fused_load_cmpi")
(set_attr "cost" "8")
+HERE
+
+ if ($lmode eq "SI" && $ccmode eq "CC" && $cmp_size_char eq "d") {
+ # prefixed_load_p needs the sign_extend attribute to validate lwa as a
+ # DS-form instruction instead of D-form.
+ print " (set_attr \"sign_extend\" \"yes\")\n";
+ }
+
+ print <<HERE
(set_attr "length" "8")])
HERE