From: Jeff Law Date: Thu, 22 Jan 2015 21:24:28 +0000 (-0700) Subject: re PR target/52076 (bloated code for setting single bits in bitfields on m68k) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=5e7821eb98292742a6aa4e1495ad1ccf9832d749;p=gcc.git re PR target/52076 (bloated code for setting single bits in bitfields on m68k) 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c1669330aab..ae5e9a5c332 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2015-01-22 Jeff Law + + 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 Jakub Jelinek diff --git a/gcc/config/m68k/.m68k.md.swp b/gcc/config/m68k/.m68k.md.swp new file mode 100755 index 00000000000..36d768170c0 Binary files /dev/null and b/gcc/config/m68k/.m68k.md.swp differ diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md index d34ad1dce88..6bb296e9e0d 100644 --- a/gcc/config/m68k/m68k.md +++ b/gcc/config/m68k/m68k.md @@ -3838,9 +3838,9 @@ "") (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" { @@ -5583,9 +5583,20 @@ [(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") diff --git a/gcc/config/m68k/predicates.md b/gcc/config/m68k/predicates.md index a7b5c42e2fd..c652f109128 100644 --- a/gcc/config/m68k/predicates.md +++ b/gcc/config/m68k/predicates.md @@ -244,3 +244,16 @@ || 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)); +}) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8bebdac3cf8..1fc0241b994 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2015-01-22 Jeff Law + + PR target/52076 + * gcc.target/m68k/pr52076-1.c: New test. + * gcc.target/m68k/pr52076-2.c: New test. + 2015-01-22 Richard Biener 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 index 00000000000..86df0dcae43 --- /dev/null +++ b/gcc/testsuite/gcc.target/m68k/pr52076-1.c @@ -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 index 00000000000..30c6991839c --- /dev/null +++ b/gcc/testsuite/gcc.target/m68k/pr52076-2.c @@ -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; +}