diff options
| author | Bernd Schmidt <bernds@codesourcery.com> | 2010-07-02 16:22:33 +0000 | 
|---|---|---|
| committer | Bernd Schmidt <bernds@gcc.gnu.org> | 2010-07-02 16:22:33 +0000 | 
| commit | 18e8200f7082b15957ee05829ce51a06c381b378 (patch) | |
| tree | 3e2175e4e860e041e9dd2980eda39ad668e981e4 | |
| parent | faeb4ee3aac0ece0f8619ba8c3a2908c6ed7b9c1 (diff) | |
| download | gcc-18e8200f7082b15957ee05829ce51a06c381b378.zip gcc-18e8200f7082b15957ee05829ce51a06c381b378.tar.gz gcc-18e8200f7082b15957ee05829ce51a06c381b378.tar.bz2  | |
re PR rtl-optimization/42835 (Missed merging common code sequence at the end of two basic blocks)
	PR target/42835
	* config/arm/arm-modes.def (CC_NOTB): New mode.
	* config/arm/arm.c (get_arm_condition_code): Handle it.
	* config/arm/thumb2.md (thumb2_compare_scc): Delete pattern.
	* config/arm/arm.md (subsi3_compare0_c): New pattern.
	(compare_scc): Now a define_and_split.  Add a number of extra
	splitters before it.
testsuite/
	PR target/42835
	* gcc.target/arm/pr42835.c: New test.
From-SVN: r161725
| -rw-r--r-- | gcc/ChangeLog | 10 | ||||
| -rw-r--r-- | gcc/config/arm/arm-modes.def | 5 | ||||
| -rw-r--r-- | gcc/config/arm/arm.c | 18 | ||||
| -rw-r--r-- | gcc/config/arm/arm.md | 126 | ||||
| -rw-r--r-- | gcc/config/arm/thumb2.md | 36 | ||||
| -rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
| -rw-r--r-- | gcc/testsuite/gcc.target/arm/pr42835.c | 12 | 
7 files changed, 142 insertions, 70 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a398516..da53bdc 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2010-07-02  Bernd Schmidt  <bernds@codesourcery.com> + +	PR target/42835 +	* config/arm/arm-modes.def (CC_NOTB): New mode. +	* config/arm/arm.c (get_arm_condition_code): Handle it. +	* config/arm/thumb2.md (thumb2_compare_scc): Delete pattern. +	* config/arm/arm.md (subsi3_compare0_c): New pattern. +	(compare_scc): Now a define_and_split.  Add a number of extra +	splitters before it. +  2010-07-02  Sandra Loosemore  <sandra@codesourcery.com>  	* config/arm/arm.c (neon_vdup_constant): Expand into canonical RTL diff --git a/gcc/config/arm/arm-modes.def b/gcc/config/arm/arm-modes.def index 813ce8e..55b98bc 100644 --- a/gcc/config/arm/arm-modes.def +++ b/gcc/config/arm/arm-modes.def @@ -34,6 +34,10 @@ ADJUST_FLOAT_FORMAT (HF, ((arm_fp16_format == ARM_FP16_FORMAT_ALTERNATIVE)     CCFPmode should be used with floating equalities.     CC_NOOVmode should be used with SImode integer equalities.     CC_Zmode should be used if only the Z flag is set correctly +   CC_Cmode should be used if only the C flag is set correctly, after an +     addition. +   CC_NOTBmode should be used if only the C flag is set as a not-borrow +     flag, after a subtraction.     CC_Nmode should be used if only the N (sign) flag is set correctly     CCmode should be used otherwise.  */ @@ -53,6 +57,7 @@ CC_MODE (CC_DLTU);  CC_MODE (CC_DGEU);  CC_MODE (CC_DGTU);  CC_MODE (CC_C); +CC_MODE (CC_NOTB);  CC_MODE (CC_N);  /* Vector modes.  */ diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 92f19c3..fbdb90a 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -16129,11 +16129,19 @@ get_arm_condition_code (rtx comparison)      case CC_Cmode:        switch (comp_code) -      { -      case LTU: return ARM_CS; -      case GEU: return ARM_CC; -      default: gcc_unreachable (); -      } +	{ +	case LTU: return ARM_CS; +	case GEU: return ARM_CC; +	default: gcc_unreachable (); +	} + +    case CC_NOTBmode: +      switch (comp_code) +	{ +	case LTU: return ARM_CC; +	case GEU: return ARM_CS; +	default: gcc_unreachable (); +	}      case CCmode:        switch (comp_code) diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 725d505..824022c 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -1149,6 +1149,19 @@    [(set_attr "conds" "set")]  ) +(define_insn "*subsi3_compare0_c" +  [(set (reg:CC_NOTB CC_REGNUM) +	(compare:CC_NOTB (match_operand:SI 1 "arm_rhs_operand" "r,I") +			 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))) +   (set (match_operand:SI 0 "s_register_operand" "=r,r") +	(minus:SI (match_dup 1) (match_dup 2)))] +  "TARGET_32BIT" +  "@ +   sub%.\\t%0, %1, %2 +   rsb%.\\t%0, %2, %1" +  [(set_attr "conds" "set")] +) +  (define_expand "decscc"    [(set (match_operand:SI            0 "s_register_operand" "=r,r")          (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r") @@ -9304,41 +9317,96 @@     (set_attr "length" "4,8")]  ) -(define_insn "*compare_scc" +; A series of splitters for the compare_scc pattern below.  Note that +; order is important. +(define_split +  [(set (match_operand:SI 0 "s_register_operand" "") +	(lt:SI (match_operand:SI 1 "s_register_operand" "") +	       (const_int 0))) +   (clobber (reg:CC CC_REGNUM))] +  "TARGET_32BIT && reload_completed" +  [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))]) + +(define_split +  [(set (match_operand:SI 0 "s_register_operand" "") +	(ge:SI (match_operand:SI 1 "s_register_operand" "") +	       (const_int 0))) +   (clobber (reg:CC CC_REGNUM))] +  "TARGET_32BIT && reload_completed" +  [(set (match_dup 0) (not:SI (match_dup 1))) +   (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))]) + +(define_split +  [(set (match_operand:SI 0 "s_register_operand" "") +	(eq:SI (match_operand:SI 1 "s_register_operand" "") +	       (const_int 0))) +   (clobber (reg:CC CC_REGNUM))] +  "TARGET_32BIT && reload_completed" +  [(parallel +    [(set (reg:CC_NOTB CC_REGNUM) +	  (compare:CC_NOTB (const_int 1) (match_dup 1))) +     (set (match_dup 0) +	  (minus:SI (const_int 1) (match_dup 1)))]) +   (cond_exec (ltu:CC_NOTB (reg:CC_NOTB CC_REGNUM) (const_int 0)) +	      (set (match_dup 0) (const_int 0)))]) + +(define_split +  [(set (match_operand:SI 0 "s_register_operand" "") +	(ne:SI (match_operand:SI 1 "s_register_operand" "") +	       (match_operand:SI 2 "const_int_operand" ""))) +   (clobber (reg:CC CC_REGNUM))] +  "TARGET_32BIT && reload_completed" +  [(parallel +    [(set (reg:CC CC_REGNUM) +	  (compare:CC (match_dup 1) (match_dup 2))) +     (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]) +   (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0)) +	      (set (match_dup 0) (const_int 1)))] +{ +  operands[3] = GEN_INT (-INTVAL (operands[2])); +}) + +(define_split +  [(set (match_operand:SI 0 "s_register_operand" "") +	(ne:SI (match_operand:SI 1 "s_register_operand" "") +	       (match_operand:SI 2 "arm_add_operand" ""))) +   (clobber (reg:CC CC_REGNUM))] +  "TARGET_32BIT && reload_completed" +  [(parallel +    [(set (reg:CC_NOOV CC_REGNUM) +	  (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2)) +			   (const_int 0))) +     (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))]) +   (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0)) +	      (set (match_dup 0) (const_int 1)))]) + +(define_insn_and_split "*compare_scc"    [(set (match_operand:SI 0 "s_register_operand" "=r,r")  	(match_operator:SI 1 "arm_comparison_operator"  	 [(match_operand:SI 2 "s_register_operand" "r,r")  	  (match_operand:SI 3 "arm_add_operand" "rI,L")]))     (clobber (reg:CC CC_REGNUM))] -  "TARGET_ARM" -  "* -    if (operands[3] == const0_rtx) -      { -	if (GET_CODE (operands[1]) == LT) -	  return \"mov\\t%0, %2, lsr #31\"; - -	if (GET_CODE (operands[1]) == GE) -	  return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\"; - -	if (GET_CODE (operands[1]) == EQ) -	  return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\"; -      } +  "TARGET_32BIT" +  "#" +  "&& reload_completed" +  [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3))) +   (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0))) +   (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))] +{ +  rtx tmp1; +  enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), +					   operands[2], operands[3]); +  enum rtx_code rc = GET_CODE (operands[1]); -    if (GET_CODE (operands[1]) == NE) -      { -        if (which_alternative == 1) -	  return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\"; -        return \"subs\\t%0, %2, %3\;movne\\t%0, #1\"; -      } -    if (which_alternative == 1) -      output_asm_insn (\"cmn\\t%2, #%n3\", operands); -    else -      output_asm_insn (\"cmp\\t%2, %3\", operands); -    return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\"; -  " -  [(set_attr "conds" "clob") -   (set_attr "length" "12")] -) +  tmp1 = gen_rtx_REG (mode, CC_REGNUM); +   +  operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx); +  if (mode == CCFPmode || mode == CCFPEmode) +    rc = reverse_condition_maybe_unordered (rc); +  else +    rc = reverse_condition (rc); +  operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx); +})  (define_insn "*cond_move"    [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") diff --git a/gcc/config/arm/thumb2.md b/gcc/config/arm/thumb2.md index 3985183..ac275ad 100644 --- a/gcc/config/arm/thumb2.md +++ b/gcc/config/arm/thumb2.md @@ -599,42 +599,6 @@     (set_attr "length" "6,10")]  ) -(define_insn "*thumb2_compare_scc" -  [(set (match_operand:SI 0 "s_register_operand" "=r,r") -	(match_operator:SI 1 "arm_comparison_operator" -	 [(match_operand:SI 2 "s_register_operand" "r,r") -	  (match_operand:SI 3 "arm_add_operand" "rI,L")])) -   (clobber (reg:CC CC_REGNUM))] -  "TARGET_THUMB2" -  "* -    if (operands[3] == const0_rtx) -      { -	if (GET_CODE (operands[1]) == LT) -	  return \"lsr\\t%0, %2, #31\"; - -	if (GET_CODE (operands[1]) == GE) -	  return \"mvn\\t%0, %2\;lsr\\t%0, %0, #31\"; - -	if (GET_CODE (operands[1]) == EQ) -	  return \"rsbs\\t%0, %2, #1\;it\\tcc\;movcc\\t%0, #0\"; -      } - -    if (GET_CODE (operands[1]) == NE) -      { -        if (which_alternative == 1) -	  return \"adds\\t%0, %2, #%n3\;it\\tne\;movne\\t%0, #1\"; -        return \"subs\\t%0, %2, %3\;it\\tne\;movne\\t%0, #1\"; -      } -    if (which_alternative == 1) -      output_asm_insn (\"cmn\\t%2, #%n3\", operands); -    else -      output_asm_insn (\"cmp\\t%2, %3\", operands); -    return \"ite\\t%D1\;mov%D1\\t%0, #0\;mov%d1\\t%0, #1\"; -  " -  [(set_attr "conds" "clob") -   (set_attr "length" "14")] -) -  (define_insn "*thumb2_cond_move"    [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")  	(if_then_else:SI (match_operator 3 "equality_operator" diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f5b759b..2f7dd0c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2010-07-02  Bernd Schmidt  <bernds@codesourcery.com> + +	PR target/42835 +	* gcc.target/arm/pr42835.c: New test. +  2010-07-02  Paolo Carlini  <paolo.carlini@oracle.com>  	* g++.dg/template/crash98.C: Remove stray // from dg-error comment. diff --git a/gcc/testsuite/gcc.target/arm/pr42835.c b/gcc/testsuite/gcc.target/arm/pr42835.c new file mode 100644 index 0000000..71c51eb --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/pr42835.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-mthumb -Os" }  */ +/* { dg-require-effective-target arm_thumb2_ok } */ + +int foo(int *p, int i) +{ +  return( (i < 0 && *p == 1) +	  || (i > 0 && *p == 2) ); +} + +/* { dg-final { scan-assembler-times "movne\[\\t \]*r.,\[\\t \]*#" 1 } } */ +/* { dg-final { scan-assembler-times "moveq\[\\t \]*r.,\[\\t \]*#" 1 } } */  | 
