re PR target/52076 (bloated code for setting single bits in bitfields on m68k)
authorJeff Law <law@redhat.com>
Thu, 22 Jan 2015 21:24:28 +0000 (14:24 -0700)
committerJeff Law <law@gcc.gnu.org>
Thu, 22 Jan 2015 21:24:28 +0000 (14:24 -0700)
PR target/52076
* config/m68k/m68k.md (xorsi3_internal): Twiddle constraints to
improve code density for small immediate to memory case.
(insv): Better handle bitfield assignments when the field is
being set to all ones.
* config/m68k/predicates.md (reg_or_pow2_m1_operand): New
operand predicate.

PR target/52076
* gcc.target/m68k/pr52076-1.c: New test.
* gcc.target/m68k/pr52076-2.c: New test.

From-SVN: r220015

gcc/ChangeLog
gcc/config/m68k/.m68k.md.swp [new file with mode: 0755]
gcc/config/m68k/m68k.md
gcc/config/m68k/predicates.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/m68k/pr52076-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/m68k/pr52076-2.c [new file with mode: 0644]

index c1669330aab55712786fd93812ad064c8434f3d5..ae5e9a5c332e18f201d47aa0301252eded46538e 100644 (file)
@@ -1,3 +1,13 @@
+2015-01-22  Jeff Law  <law@redhat.com>
+
+       PR target/52076
+       * config/m68k/m68k.md (xorsi3_internal): Twiddle constraints to
+       improve code density for small immediate to memory case.
+       (insv): Better handle bitfield assignments when the field is
+       being set to all ones.
+       * config/m68k/predicates.md (reg_or_pow2_m1_operand): New
+       operand predicate.
+
 2015-01-22  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
            Jakub Jelinek  <jakub@redhat.com>
 
diff --git a/gcc/config/m68k/.m68k.md.swp b/gcc/config/m68k/.m68k.md.swp
new file mode 100755 (executable)
index 0000000..36d7681
Binary files /dev/null and b/gcc/config/m68k/.m68k.md.swp differ
index d34ad1dce88b322feeb4e14e8c1831c37eed6669..6bb296e9e0d345b71815f8e719e46888c6df0ffb 100644 (file)
   "")
 
 (define_insn "xorsi3_internal"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=do,m")
-       (xor:SI (match_operand:SI 1 "general_operand" "%0,0")
-                (match_operand:SI 2 "general_operand" "di,dKT")))]
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=d,o,m")
+       (xor:SI (match_operand:SI 1 "general_operand" "%0, 0,0")
+                (match_operand:SI 2 "general_operand" "di,dK,dKT")))]
 
   "!TARGET_COLDFIRE"
 {
   [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "")
                         (match_operand:SI 1 "const_int_operand" "")
                         (match_operand:SI 2 "const_int_operand" ""))
-       (match_operand:SI 3 "register_operand" ""))]
+       (match_operand:SI 3 "reg_or_pow2_m1_operand" ""))]
   "TARGET_68020 && TARGET_BITFIELD"
-  "")
+  "
+{
+  /* Special case initializing a field to all ones. */
+  if (GET_CODE (operands[3]) == CONST_INT)
+    {
+      if (exact_log2 (INTVAL (operands[3]) + 1) != INTVAL (operands[1]))
+       operands[3] = force_reg (SImode, operands[3]);
+      else
+       operands[3] = constm1_rtx;
+
+    }
+}")
 
 (define_insn "*insv_bfins_mem"
   [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+o")
index a7b5c42e2fd508a574b58feed72fe16fd65f4d24..c652f1091286c682ddaa2fbfa617ccc6797973ac 100644 (file)
                 || reload_in_progress
                 || reload_completed));
 })
+
+;; Used to detect when an operand is either a register
+;; or a constant that is all ones in its lower bits.
+;; Used by insv pattern to help detect when we're initializing
+;; a bitfield to all ones.
+
+(define_predicate "reg_or_pow2_m1_operand"
+  (match_code "reg,const_int")
+{
+  return (REG_P (op)
+         || (GET_CODE (op) == CONST_INT
+             && exact_log2 (INTVAL (op) + 1) >= 0));
+})
index 8bebdac3cf8a0677645044dda258d0256c2e2cd1..1fc0241b994c7e750485675b1397650dc1cc4fee 100644 (file)
@@ -1,3 +1,9 @@
+2015-01-22  Jeff Law  <law@redhat.com>
+
+       PR target/52076
+       * gcc.target/m68k/pr52076-1.c: New test.
+       * gcc.target/m68k/pr52076-2.c: New test.
+
 2015-01-22  Richard Biener  <rguenther@suse.de>
 
        PR middle-end/64728
diff --git a/gcc/testsuite/gcc.target/m68k/pr52076-1.c b/gcc/testsuite/gcc.target/m68k/pr52076-1.c
new file mode 100644 (file)
index 0000000..86df0dc
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do assemble } /*
+/* { dg-options "-Os -fomit-frame-pointer -m68040" } */
+/* { dg-final { object-size text <= 72 } } */
+
+struct kobject {
+        unsigned int b7:1;
+        unsigned int :6;
+        unsigned int b0:1;
+        unsigned char x;
+        unsigned int f;
+};
+
+void ior(struct kobject *kobj) { kobj->f |= 4; }
+void ior_m(struct kobject *kobj) { kobj->f |= -4; }
+
+void xor(struct kobject *kobj) { kobj->f ^= 4; }
+void xor_m(struct kobject *kobj) { kobj->f ^= -4; }
+
+void and(struct kobject *kobj) { kobj->f &= 4; }
+void and_m(struct kobject *kobj) { kobj->f &= -4; }
diff --git a/gcc/testsuite/gcc.target/m68k/pr52076-2.c b/gcc/testsuite/gcc.target/m68k/pr52076-2.c
new file mode 100644 (file)
index 0000000..30c6991
--- /dev/null
@@ -0,0 +1,27 @@
+/* { dg-do assemble } /*
+/* { dg-options "-Os -fomit-frame-pointer -m68040" } */
+/* { dg-final { object-size text <= 30 } } */
+
+struct kobject {
+        unsigned int b7:1;
+        unsigned int b56:2;
+        unsigned int b1234:4;
+        unsigned int b0:1;
+        unsigned char x;
+        unsigned int f;
+};
+
+void b7(struct kobject *kobj)
+{
+        kobj->b7 = 1;
+}
+
+void b56(struct kobject *kobj)
+{
+        kobj->b56 = 3;
+}
+
+void b1234(struct kobject *kobj)
+{
+        kobj->b1234 = 15;
+}