From 4ca75988218b329167e97444ac1eaa78a8dd7ed1 Mon Sep 17 00:00:00 2001 From: jakub Date: Sun, 29 May 2011 18:51:48 +0000 Subject: [PATCH] PR rtl-optimization/49095 * config/i386/predicates.md (plusminuslogic_operator): New predicate. * config/i386/i386.md: Add peepholes for mem {+,-,&,|,^}= x; mem != 0. * gcc.target/i386/pr49095.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@174413 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 6 +++ gcc/config/i386/i386.md | 85 +++++++++++++++++++++++++++++++++ gcc/config/i386/predicates.md | 6 ++- gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/gcc.target/i386/pr49095.c | 73 ++++++++++++++++++++++++++++ 5 files changed, 174 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr49095.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6f99232021e..eaa7f6438b9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2011-05-29 Jakub Jelinek + + PR rtl-optimization/49095 + * config/i386/predicates.md (plusminuslogic_operator): New predicate. + * config/i386/i386.md: Add peepholes for mem {+,-,&,|,^}= x; mem != 0. + 2011-05-29 Richard Sandiford PR target/43995 diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 2e7633dfc7d..73dc7e891ff 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -16868,6 +16868,91 @@ (clobber (reg:CC FLAGS_REG))]) (set (match_dup 0) (match_dup 2))]) +;; Attempt to use arith or logical operations with memory outputs with +;; setting of flags. +(define_peephole2 + [(set (match_operand:SWI 0 "register_operand" "") + (match_operand:SWI 1 "memory_operand" "")) + (parallel [(set (match_dup 0) + (match_operator:SWI 3 "plusminuslogic_operator" + [(match_dup 0) + (match_operand:SWI 2 "" "")])) + (clobber (reg:CC FLAGS_REG))]) + (set (match_dup 1) (match_dup 0)) + (set (reg FLAGS_REG) (compare (match_dup 0) (const_int 0)))] + "(TARGET_READ_MODIFY_WRITE || optimize_insn_for_size_p ()) + && peep2_reg_dead_p (4, operands[0]) + && !reg_overlap_mentioned_p (operands[0], operands[1]) + && ix86_match_ccmode (peep2_next_insn (3), + (GET_CODE (operands[3]) == PLUS + || GET_CODE (operands[3]) == MINUS) + ? CCGOCmode : CCNOmode)" + [(parallel [(set (match_dup 4) (match_dup 5)) + (set (match_dup 1) (match_op_dup 3 [(match_dup 1) + (match_dup 2)]))])] + "operands[4] = SET_DEST (PATTERN (peep2_next_insn (3))); + operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), mode, + copy_rtx (operands[1]), + copy_rtx (operands[2])); + operands[5] = gen_rtx_COMPARE (GET_MODE (operands[4]), + operands[5], const0_rtx);") + +(define_peephole2 + [(parallel [(set (match_operand:SWI 0 "register_operand" "") + (match_operator:SWI 2 "plusminuslogic_operator" + [(match_dup 0) + (match_operand:SWI 1 "memory_operand" "")])) + (clobber (reg:CC FLAGS_REG))]) + (set (match_dup 1) (match_dup 0)) + (set (reg FLAGS_REG) (compare (match_dup 0) (const_int 0)))] + "(TARGET_READ_MODIFY_WRITE || optimize_insn_for_size_p ()) + && GET_CODE (operands[2]) != MINUS + && peep2_reg_dead_p (3, operands[0]) + && !reg_overlap_mentioned_p (operands[0], operands[1]) + && ix86_match_ccmode (peep2_next_insn (2), + GET_CODE (operands[2]) == PLUS + ? CCGOCmode : CCNOmode)" + [(parallel [(set (match_dup 3) (match_dup 4)) + (set (match_dup 1) (match_op_dup 2 [(match_dup 1) + (match_dup 0)]))])] + "operands[3] = SET_DEST (PATTERN (peep2_next_insn (2))); + operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[2]), mode, + copy_rtx (operands[1]), + copy_rtx (operands[0])); + operands[4] = gen_rtx_COMPARE (GET_MODE (operands[3]), + operands[4], const0_rtx);") + +(define_peephole2 + [(set (match_operand:SWI12 0 "register_operand" "") + (match_operand:SWI12 1 "memory_operand" "")) + (parallel [(set (match_operand:SI 4 "register_operand" "") + (match_operator:SI 3 "plusminuslogic_operator" + [(match_dup 4) + (match_operand:SI 2 "nonmemory_operand" "")])) + (clobber (reg:CC FLAGS_REG))]) + (set (match_dup 1) (match_dup 0)) + (set (reg FLAGS_REG) (compare (match_dup 0) (const_int 0)))] + "(TARGET_READ_MODIFY_WRITE || optimize_insn_for_size_p ()) + && REG_P (operands[0]) && REG_P (operands[4]) + && REGNO (operands[0]) == REGNO (operands[4]) + && peep2_reg_dead_p (4, operands[0]) + && !reg_overlap_mentioned_p (operands[0], operands[1]) + && ix86_match_ccmode (peep2_next_insn (3), + (GET_CODE (operands[3]) == PLUS + || GET_CODE (operands[3]) == MINUS) + ? CCGOCmode : CCNOmode)" + [(parallel [(set (match_dup 4) (match_dup 5)) + (set (match_dup 1) (match_dup 6))])] + "operands[2] = gen_lowpart (mode, operands[2]); + operands[4] = SET_DEST (PATTERN (peep2_next_insn (3))); + operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), mode, + copy_rtx (operands[1]), operands[2]); + operands[5] = gen_rtx_COMPARE (GET_MODE (operands[4]), + operands[5], const0_rtx); + operands[6] = gen_rtx_fmt_ee (GET_CODE (operands[3]), mode, + copy_rtx (operands[1]), + copy_rtx (operands[2]));") + ;; Attempt to always use XOR for zeroing registers. (define_peephole2 [(set (match_operand 0 "register_operand" "") diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md index 1471f5a2282..358d04f6532 100644 --- a/gcc/config/i386/predicates.md +++ b/gcc/config/i386/predicates.md @@ -1,5 +1,5 @@ ;; Predicate definitions for IA-32 and x86-64. -;; Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 +;; Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 ;; Free Software Foundation, Inc. ;; ;; This file is part of GCC. @@ -1070,6 +1070,10 @@ (define_predicate "div_operator" (match_code "div")) +;; Return true if this is a plus, minus, and, ior or xor operation. +(define_predicate "plusminuslogic_operator" + (match_code "plus,minus,and,ior,xor")) + ;; Return true if this is a float extend operation. (define_predicate "float_operator" (match_code "float")) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c416d1aea30..0f2b1dc1fe2 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2011-05-29 Jakub Jelinek + + PR rtl-optimization/49095 + * gcc.target/i386/pr49095.c: New test. + 2011-05-29 Tobias Burnus PR fortran/18918 diff --git a/gcc/testsuite/gcc.target/i386/pr49095.c b/gcc/testsuite/gcc.target/i386/pr49095.c new file mode 100644 index 00000000000..bc820204e97 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr49095.c @@ -0,0 +1,73 @@ +/* PR rtl-optimization/49095 */ +/* { dg-do compile } */ +/* { dg-options "-Os" } */ +/* { dg-options "-Os -mregparm=2" { target ilp32 } } */ + +void foo (void *); + +int * +f1 (int *x) +{ + if (!--*x) + foo (x); + return x; +} + +int +g1 (int x) +{ + if (!--x) + foo ((void *) 0); + return x; +} + +#define F(T, OP, OPN) \ +T * \ +f##T##OPN (T *x, T y) \ +{ \ + *x OP y; \ + if (!*x) \ + foo (x); \ + return x; \ +} \ + \ +T \ +g##T##OPN (T x, T y) \ +{ \ + x OP y; \ + if (!x) \ + foo ((void *) 0); \ + return x; \ +} \ + \ +T * \ +h##T##OPN (T *x) \ +{ \ + *x OP 24; \ + if (!*x) \ + foo (x); \ + return x; \ +} \ + \ +T \ +i##T##OPN (T x, T y) \ +{ \ + x OP 24; \ + if (!x) \ + foo ((void *) 0); \ + return x; \ +} + +#define G(T) \ +F (T, +=, plus) \ +F (T, -=, minus) \ +F (T, &=, and) \ +F (T, |=, or) \ +F (T, ^=, xor) + +G (char) +G (short) +G (int) +G (long) + +/* { dg-final { scan-assembler-not "test\[lq\]" } } */ -- 2.11.4.GIT