diff options
Diffstat (limited to 'gcc/config/rs6000/genfusion.pl')
-rwxr-xr-x | gcc/config/rs6000/genfusion.pl | 37 |
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 |