The compiler cannot assume that the eqsi etc. patterns write a properly extended result to a DI reg. The current way to tell it is to add an extra pattern with an extend. This patch does that. A less cumbersome method of specifying this would be nice -- maybe one where we say in the SI pattern that the result is already extended correctly as DI (both sign- and zero-extended, in this case).
This partially fixes PR36557 (and is the best we can do for the test case there, we cannot assume function args are correctly extended for their type). Tested as usual; okay for mainline? Segher 2015-01-07 Segher Boessenkool <seg...@kernel.crashing.org> gcc/ PR target/36557 * config/rs6000/rs6000.md (*eqsi3_ext<mode>, *nesi3_ext<mode>): New. --- gcc/config/rs6000/rs6000.md | 60 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 3da529c..6da1a6a 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -12588,6 +12588,66 @@ (define_insn_and_split "*minus_ne_<mode>" (if_then_else (match_test "operands[2] == const0_rtx") (const_string "8") (const_string "12")))]) + +(define_insn_and_split "*eqsi3_ext<mode>" + [(set (match_operand:EXTSI 0 "gpc_reg_operand" "=r") + (eq:EXTSI (match_operand:SI 1 "gpc_reg_operand" "r") + (match_operand:SI 2 "scc_eq_operand" "rKLI"))) + (clobber (match_scratch:SI 3 "=r")) + (clobber (match_scratch:SI 4 "=r"))] + "" + "#" + "" + [(set (match_dup 4) + (clz:SI (match_dup 3))) + (set (match_dup 0) + (zero_extend:EXTSI + (lshiftrt:SI (match_dup 4) + (const_int 5))))] +{ + operands[3] = rs6000_emit_eqne (SImode, + operands[1], operands[2], operands[3]); + + if (GET_CODE (operands[4]) == SCRATCH) + operands[4] = gen_reg_rtx (SImode); +} + [(set (attr "length") + (if_then_else (match_test "operands[2] == const0_rtx") + (const_string "8") + (const_string "12")))]) + +(define_insn_and_split "*nesi3_ext<mode>" + [(set (match_operand:EXTSI 0 "gpc_reg_operand" "=r") + (ne:EXTSI (match_operand:SI 1 "gpc_reg_operand" "r") + (match_operand:SI 2 "scc_eq_operand" "rKLI"))) + (clobber (match_scratch:SI 3 "=r")) + (clobber (match_scratch:SI 4 "=r")) + (clobber (match_scratch:EXTSI 5 "=r"))] + "" + "#" + "" + [(set (match_dup 4) + (clz:SI (match_dup 3))) + (set (match_dup 5) + (zero_extend:EXTSI + (lshiftrt:SI (match_dup 4) + (const_int 5)))) + (set (match_dup 0) + (xor:EXTSI (match_dup 5) + (const_int 1)))] +{ + operands[3] = rs6000_emit_eqne (SImode, + operands[1], operands[2], operands[3]); + + if (GET_CODE (operands[4]) == SCRATCH) + operands[4] = gen_reg_rtx (SImode); + if (GET_CODE (operands[5]) == SCRATCH) + operands[5] = gen_reg_rtx (<MODE>mode); +} + [(set (attr "length") + (if_then_else (match_test "operands[2] == const0_rtx") + (const_string "12") + (const_string "16")))]) ;; Define both directions of branch and return. If we need a reload ;; register, we'd rather use CR0 since it is much easier to copy a -- 1.8.1.4