]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR middle-end/54685 ([SH] Improve unsigned int comparison with 0x7FFFFFFF)
authorOleg Endo <olegendo@gcc.gnu.org>
Mon, 8 Oct 2012 10:09:28 +0000 (10:09 +0000)
committerOleg Endo <olegendo@gcc.gnu.org>
Mon, 8 Oct 2012 10:09:28 +0000 (10:09 +0000)
PR target/54685
* config/sh/sh.md (one_cmplsi2): Make insn_and_split.  Add manual
combine matching for an insn sequence where a ge:SI pattern can be used.

PR target/54685
* gcc.target/sh/pr54685.c: New.

From-SVN: r192200

gcc/ChangeLog
gcc/config/sh/sh.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/sh/pr54685.c [new file with mode: 0644]

index 460ed8416bfe836dce6aaade53fd8cdbace8c34a..75b99cd500d6d198ca9943fc0d32a0867dad2d74 100644 (file)
@@ -1,3 +1,9 @@
+2012-10-08  Oleg Endo  <olegendo@gcc.gnu.org>
+
+       PR target/54685
+       * config/sh/sh.md (one_cmplsi2): Make insn_and_split.  Add manual
+       combine matching for an insn sequence where a ge:SI pattern can be used.
+
 2012-10-08  Dodji Seketeli  <dodji@redhat.com>
 
        PR c++/53528 C++11 attribute support
index 989d52e3ea20576667c2b147131fd99b79f0f2a5..0a1cd09c1f8db6f446dfaf829518d4d16a3018af 100644 (file)
@@ -5189,11 +5189,61 @@ label:
   "neg %1,%0"
   [(set_attr "type" "arith")])
 
-(define_insn "one_cmplsi2"
+(define_insn_and_split "one_cmplsi2"
   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
        (not:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
   "TARGET_SH1"
   "not %1,%0"
+  "&& can_create_pseudo_p ()"
+  [(set (reg:SI T_REG) (ge:SI (match_dup 1) (const_int 0)))
+   (set (match_dup 0) (reg:SI T_REG))]
+{
+/* PR 54685
+   If the result of 'unsigned int <= 0x7FFFFFFF' ends up as the following
+   sequence:
+
+     (set (reg0) (not:SI (reg0) (reg1)))
+     (parallel [(set (reg2) (lshiftrt:SI (reg0) (const_int 31)))
+               (clobber (reg:SI T_REG))])
+
+   ... match and combine the sequence manually in the split pass after the
+   combine pass.  Notice that combine does try the target pattern of this
+   split, but if the pattern is added it interferes with other patterns, in
+   particular with the div0s comparisons.
+   This could also be done with a peephole but doing it here before register
+   allocation can save one temporary.
+   When we're here, the not:SI pattern obviously has been matched already
+   and we only have to see whether the following insn is the left shift.  */
+
+  rtx i = next_nonnote_insn_bb (curr_insn);
+  if (i == NULL_RTX || !NONJUMP_INSN_P (i))
+    FAIL;
+
+  rtx p = PATTERN (i);
+  if (GET_CODE (p) != PARALLEL || XVECLEN (p, 0) != 2)
+    FAIL;
+
+  rtx p0 = XVECEXP (p, 0, 0);
+  rtx p1 = XVECEXP (p, 0, 1);
+
+  if (/* (set (reg2) (lshiftrt:SI (reg0) (const_int 31)))  */
+      GET_CODE (p0) == SET
+      && GET_CODE (XEXP (p0, 1)) == LSHIFTRT
+      && REG_P (XEXP (XEXP (p0, 1), 0))
+      && REGNO (XEXP (XEXP (p0, 1), 0)) == REGNO (operands[0])
+      && CONST_INT_P (XEXP (XEXP (p0, 1), 1))
+      && INTVAL (XEXP (XEXP (p0, 1), 1)) == 31
+
+      /* (clobber (reg:SI T_REG))  */
+      && GET_CODE (p1) == CLOBBER && REG_P (XEXP (p1, 0))
+      && REGNO (XEXP (p1, 0)) == T_REG)
+    {
+      operands[0] = XEXP (p0, 0);
+      set_insn_deleted (i);
+    }
+  else
+    FAIL;
+}
   [(set_attr "type" "arith")])
 
 (define_expand "one_cmpldi2"
index d20a9e89304ea5c6f6bae745ad2846e323b6c0a0..1eb751ed9b7158048c7a351a6e1f200aa53aa1ed 100644 (file)
@@ -1,3 +1,8 @@
+2012-10-08  Oleg Endo  <olegendo@gcc.gnu.org>
+
+       PR target/54685
+       * gcc.target/sh/pr54685.c: New.
+
 2012-10-08  Dodji Seketeli  <dodji@redhat.com>
 
        PR c++/53528 C++11 attribute support
diff --git a/gcc/testsuite/gcc.target/sh/pr54685.c b/gcc/testsuite/gcc.target/sh/pr54685.c
new file mode 100644 (file)
index 0000000..ba08a4a
--- /dev/null
@@ -0,0 +1,58 @@
+/* Check that a comparison 'unsigned int <= 0x7FFFFFFF' results in code
+   utilizing the cmp/pz instruction.  */
+/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-options "-O1" } */
+/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } }  */
+/* { dg-final { scan-assembler-not "not" } } */
+/* { dg-final { scan-assembler-times "cmp/pz" 7 } } */
+/* { dg-final { scan-assembler-times "shll" 1 } } */
+/* { dg-final { scan-assembler-times "movt" 4 } } */
+
+int
+test_00 (unsigned int a)
+{
+  return !(a > 0x7FFFFFFF);
+}
+
+int
+test_01 (unsigned int a)
+{
+  return !(a > 0x7FFFFFFF) ? -5 : 10;
+}
+
+int
+test_02 (unsigned int a)
+{
+  /* 1x shll, 1x movt  */
+  return a >= 0x80000000;
+}
+
+int
+test_03 (unsigned int a)
+{
+  return a >= 0x80000000 ? -5 : 10;
+}
+
+int
+test_04 (unsigned int a)
+{
+  return a <= 0x7FFFFFFF;
+}
+
+int
+test_05 (unsigned int a)
+{
+  return a <= 0x7FFFFFFF ? -5 : 10;
+}
+
+int
+test_06 (unsigned int a)
+{
+  return a < 0x80000000;
+}
+
+int
+test_07 (unsigned int a)
+{
+  return a < 0x80000000 ? -5 : 10;
+}