From 07c0b5604acc658ba193b2b5f0c592ade689e8e4 Mon Sep 17 00:00:00 2001 From: Oleg Endo Date: Sun, 11 Mar 2012 13:18:08 +0000 Subject: [PATCH] re PR target/51244 ([SH] Inefficient conditional branch and code around T bit) PR target/51244 * config/sh/sh.md (movnegt): Expand into respective insns immediately. Use movrt_negc instead of negc pattern for non-SH2A. (*movnegt): Remove. (*movrt_negc, *negnegt, *movtt, *movt_qi): New insns and splits. PR target/51244 * gcc.target/sh/pr51244-1.c: Fix thinkos. From-SVN: r185192 --- gcc/ChangeLog | 8 +++ gcc/config/sh/sh.md | 91 +++++++++++++++++++++++++-------- gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/gcc.target/sh/pr51244-1.c | 12 ++--- 4 files changed, 90 insertions(+), 26 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8e5b4a9..faafd80 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2012-03-11 Oleg Endo + + PR target/51244 + * config/sh/sh.md (movnegt): Expand into respective insns immediately. + Use movrt_negc instead of negc pattern for non-SH2A. + (*movnegt): Remove. + (*movrt_negc, *negnegt, *movtt, *movt_qi): New insns and splits. + 2012-03-10 H.J. Lu * config/i386/i386.c (ix86_decompose_address): Disallow fs:(reg) diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index eb1c852..528a120 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -9679,37 +9679,88 @@ mov.l\\t1f,r0\\n\\ ;; If the constant -1 can be CSE-ed or lifted out of a loop it effectively ;; becomes a one instruction operation. Moreover, care must be taken that ;; the insn can still be combined with inverted compare and branch code -;; around it. -;; The expander will reserve the constant -1, the insn makes the whole thing -;; combinable, the splitter finally emits the insn if it was not combined -;; away. -;; Notice that when using the negc variant the T bit also gets inverted. +;; around it. On the other hand, if a function returns the complement of +;; a previous comparison result in the T bit, the xor #1,r0 approach might +;; lead to better code. (define_expand "movnegt" - [(set (match_dup 1) (const_int -1)) - (parallel [(set (match_operand:SI 0 "arith_reg_dest" "") - (xor:SI (reg:SI T_REG) (const_int 1))) - (use (match_dup 1))])] + [(set (match_operand:SI 0 "arith_reg_dest" "") + (xor:SI (reg:SI T_REG) (const_int 1)))] "" { - operands[1] = gen_reg_rtx (SImode); + if (TARGET_SH2A) + emit_insn (gen_movrt (operands[0])); + else + { + rtx val = force_reg (SImode, gen_int_mode (-1, SImode)); + emit_insn (gen_movrt_negc (operands[0], val)); + } + DONE; }) -(define_insn_and_split "*movnegt" +(define_insn "movrt_negc" [(set (match_operand:SI 0 "arith_reg_dest" "=r") (xor:SI (reg:SI T_REG) (const_int 1))) + (set (reg:SI T_REG) (const_int 1)) (use (match_operand:SI 1 "arith_reg_operand" "r"))] "TARGET_SH1" + "negc %1,%0" + [(set_attr "type" "arith")]) + +;; The *negnegt patterns help the combine pass to figure out how to fold +;; an explicit double T bit negation. +(define_insn_and_split "*negnegt" + [(set (reg:SI T_REG) + (eq:SI (subreg:QI (xor:SI (reg:SI T_REG) (const_int 1)) 3) + (const_int 0)))] + "! TARGET_LITTLE_ENDIAN" "#" - "&& 1" - [(const_int 0)] -{ - if (TARGET_SH2A) - emit_insn (gen_movrt (operands[0])); - else - emit_insn (gen_negc (operands[0], operands[1])); - DONE; -} + "" + [(const_int 0)]) + +(define_insn_and_split "*negnegt" + [(set (reg:SI T_REG) + (eq:SI (subreg:QI (xor:SI (reg:SI T_REG) (const_int 1)) 0) + (const_int 0)))] + "TARGET_LITTLE_ENDIAN" + "#" + "" + [(const_int 0)]) + +;; The *movtt patterns improve code at -O1. +(define_insn_and_split "*movtt" + [(set (reg:SI T_REG) + (eq:SI (zero_extend:SI (subreg:QI (reg:SI T_REG) 3)) + (const_int 1)))] + "! TARGET_LITTLE_ENDIAN" + "#" + "" + [(const_int 0)]) + +(define_insn_and_split "*movtt" + [(set (reg:SI T_REG) + (eq:SI (zero_extend:SI (subreg:QI (reg:SI T_REG) 0)) + (const_int 1)))] + "TARGET_LITTLE_ENDIAN" + "#" + "" + [(const_int 0)]) + +;; The *movt_qi patterns help the combine pass convert a movrt_negc pattern +;; into a movt Rn, xor #1 Rn pattern. This can happen when e.g. a function +;; returns the inverted T bit value. +(define_insn "*movt_qi" + [(set (match_operand:SI 0 "arith_reg_dest" "=r") + (zero_extend:SI (subreg:QI (reg:SI T_REG) 3)))] + "! TARGET_LITTLE_ENDIAN" + "movt %0" + [(set_attr "type" "arith")]) + +(define_insn "*movt_qi" + [(set (match_operand:SI 0 "arith_reg_dest" "=r") + (zero_extend:SI (subreg:QI (reg:SI T_REG) 0)))] + "TARGET_LITTLE_ENDIAN" + "movt %0" [(set_attr "type" "arith")]) (define_expand "cstoresf4" diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0234217..a9a3120 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2012-03-11 Oleg Endo + + PR target/51244 + * gcc.target/sh/pr51244-1.c: Fix thinkos. + 2012-03-10 John David Anglin PR target/52450 diff --git a/gcc/testsuite/gcc.target/sh/pr51244-1.c b/gcc/testsuite/gcc.target/sh/pr51244-1.c index 57af104..34e1b02 100644 --- a/gcc/testsuite/gcc.target/sh/pr51244-1.c +++ b/gcc/testsuite/gcc.target/sh/pr51244-1.c @@ -13,20 +13,20 @@ testfunc_00 (int a, int b, int c, int d) } int -testfunc_01 (int a, char* p, int b, int c) +testfunc_01 (int a, int b, int c, int d) { - return (a == b && a == c) ? b : c; + return (a == b || a == d) ? b : c; } int -testfunc_02 (int a, char* p, int b, int c) +testfunc_02 (int a, int b, int c, int d) { - return (a == b && a == c) ? b : c; + return (a == b && a == d) ? b : c; } int -testfunc_03 (int a, char* p, int b, int c) +testfunc_03 (int a, int b, int c, int d) { - return (a != b && a != c) ? b : c; + return (a != b && a != d) ? b : c; } -- 2.7.4