Hi, I've just committed the attached patch that fixes PR 60071 as rev 208242. Originally tested by Kaz: http://gcc.gnu.org/ml/gcc-testresults/2014-02/msg01866.html Tested the new test case with: make check-gcc RUNTESTFLAGS="compile.exp=pr60071.c --target_board=sh-sim \{-m2/-ml,-m2/-mb,-m2a/-mb,-m4/-ml,-m4/-mb,-m4a/-ml,-m4a/-mb}"
Cheers, Oleg gcc/ChangeLog: PR target/60071 * config/sh/sh.md (*mov_t_msb_neg): Split into ... (*mov_t_msb_neg_negc): ... this new insn. testsuite/ChangeLog: PR target/60071 * gcc.c-torture/compile/pr60071.c: New.
Index: gcc/config/sh/sh.md =================================================================== --- gcc/config/sh/sh.md (revision 208241) +++ gcc/config/sh/sh.md (working copy) @@ -11434,6 +11434,10 @@ ;; T = 1: 0x80000000 -> reg ;; T = 0: 0x7FFFFFFF -> reg ;; This works because 0 - 0x80000000 = 0x80000000. +;; +;; This insn must not match again after it has been split into the constant +;; load and negc. This is accomplished by the special negc insn that +;; has a use on the operand. (define_insn_and_split "*mov_t_msb_neg" [(set (match_operand:SI 0 "arith_reg_dest") (minus:SI (const_int -2147483648) ;; 0x80000000 @@ -11444,12 +11448,23 @@ "&& can_create_pseudo_p ()" [(set (match_dup 2) (const_int -2147483648)) (parallel [(set (match_dup 0) (minus:SI (neg:SI (match_dup 2)) - (reg:SI T_REG))) - (clobber (reg:SI T_REG))])] + (reg:SI T_REG))) + (clobber (reg:SI T_REG)) + (use (match_dup 2))])] { operands[2] = gen_reg_rtx (SImode); }) +(define_insn "*mov_t_msb_neg_negc" + [(set (match_operand:SI 0 "arith_reg_dest" "=r") + (minus:SI (neg:SI (match_operand:SI 1 "arith_reg_operand" "r")) + (match_operand:SI 2 "t_reg_operand"))) + (clobber (reg:SI T_REG)) + (use (match_dup 1))] + "TARGET_SH1" + "negc %1,%0" + [(set_attr "type" "arith")]) + ;; These are essentially the same as above, but with the inverted T bit. ;; Combine recognizes the split patterns, but does not take them sometimes ;; if the T_REG clobber is specified. Instead it tries to split out the Index: gcc/testsuite/gcc.c-torture/compile/pr60071.c =================================================================== --- gcc/testsuite/gcc.c-torture/compile/pr60071.c (revision 0) +++ gcc/testsuite/gcc.c-torture/compile/pr60071.c (revision 0) @@ -0,0 +1,8 @@ +int +foo (int cls, int sign) +{ + if (__builtin_expect (cls == 4, 0)) + return (sign + ? (-((int) ((~(unsigned)0) >> 1)))-1 + : ((int) ((~(unsigned)0) >> 1))); +}