2016-11-22 Michael Collison <michael.collison@arm.com>
authorMichael Collison <michael.collison@arm.com>
Wed, 23 Nov 2016 07:47:25 +0000 (07:47 +0000)
committerMichael Collison <collison@gcc.gnu.org>
Wed, 23 Nov 2016 07:47:25 +0000 (07:47 +0000)
* config/aarch64/aarch64-protos.h
(aarch64_and_split_imm1, aarch64_and_split_imm2)
(aarch64_and_bitmask_imm): New prototypes
* config/aarch64/aarch64.c (aarch64_and_split_imm1):
New overloaded function to create bit mask covering the
lowest to highest bits set.
(aarch64_and_split_imm2): New overloaded functions to create bit
mask of zeros between first and last bit set.
(aarch64_and_bitmask_imm): New function to determine if a integer
is a valid two instruction "and" operation.
* config/aarch64/aarch64.md:(and<mode>3): New define_insn and _split
allowing wider range of constants with "and" operations.
* (ior<mode>3, xor<mode>3): Use new LOGICAL2 iterator to prevent
"and" operator from matching restricted constant range used for
ior and xor operators.
* config/aarch64/constraints.md (UsO constraint): New SImode constraint
for constants in "and" operantions.
(UsP constraint): New DImode constraint for constants in "and" operations.
* config/aarch64/iterators.md (lconst2): New mode iterator.
(LOGICAL2): New code iterator.
* config/aarch64/predicates.md (aarch64_logical_and_immediate): New
predicate
(aarch64_logical_and_operand): New predicate allowing extended constants
for "and" operations.
* testsuite/gcc.target/aarch64/and_const.c: New test to verify
additional constants are recognized and fewer instructions generated.
* testsuite/gcc.target/aarch64/and_const2.c: New test to verify
additional constants are recognized and fewer instructions generated.

From-SVN: r242739

gcc/ChangeLog
gcc/config/aarch64/aarch64-protos.h
gcc/config/aarch64/aarch64.c
gcc/config/aarch64/aarch64.md
gcc/config/aarch64/constraints.md
gcc/config/aarch64/iterators.md
gcc/config/aarch64/predicates.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/aarch64/and_const.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/and_const2.c [new file with mode: 0644]

index 97320c7..ea39ef0 100644 (file)
@@ -1,3 +1,30 @@
+2016-11-22  Michael Collison  <michael.collison@arm.com>
+
+       * config/aarch64/aarch64-protos.h
+       (aarch64_and_split_imm1, aarch64_and_split_imm2)
+       (aarch64_and_bitmask_imm): New prototypes
+       * config/aarch64/aarch64.c (aarch64_and_split_imm1):
+       New overloaded function to create bit mask covering the
+       lowest to highest bits set.
+       (aarch64_and_split_imm2): New overloaded functions to create bit
+       mask of zeros between first and last bit set.
+       (aarch64_and_bitmask_imm): New function to determine if a integer
+       is a valid two instruction "and" operation.
+       * config/aarch64/aarch64.md:(and<mode>3): New define_insn and _split
+       allowing wider range of constants with "and" operations.
+       * (ior<mode>3, xor<mode>3): Use new LOGICAL2 iterator to prevent
+       "and" operator from matching restricted constant range used for
+       ior and xor operators.
+       * config/aarch64/constraints.md (UsO constraint): New SImode constraint
+       for constants in "and" operantions.
+       (UsP constraint): New DImode constraint for constants in "and" operations.
+       * config/aarch64/iterators.md (lconst2): New mode iterator.
+       (LOGICAL2): New code iterator.
+       * config/aarch64/predicates.md (aarch64_logical_and_immediate): New
+       predicate
+       (aarch64_logical_and_operand): New predicate allowing extended constants
+       for "and" operations.
+
 2016-11-22  Walter Lee  <walt@tilera.com>
 
        * config/tilegx/tilegx.md (trap): New pattern.
index b6ca3df..7f67f14 100644 (file)
@@ -296,6 +296,9 @@ extern struct tune_params aarch64_tune_params;
 HOST_WIDE_INT aarch64_initial_elimination_offset (unsigned, unsigned);
 int aarch64_get_condition_code (rtx);
 bool aarch64_bitmask_imm (HOST_WIDE_INT val, machine_mode);
+unsigned HOST_WIDE_INT aarch64_and_split_imm1 (HOST_WIDE_INT val_in);
+unsigned HOST_WIDE_INT aarch64_and_split_imm2 (HOST_WIDE_INT val_in);
+bool aarch64_and_bitmask_imm (unsigned HOST_WIDE_INT val_in, machine_mode mode);
 int aarch64_branch_cost (bool, bool);
 enum aarch64_symbol_type aarch64_classify_symbolic_expression (rtx);
 bool aarch64_const_vec_all_same_int_p (rtx, HOST_WIDE_INT);
index efcba83..1f35220 100644 (file)
@@ -3674,6 +3674,44 @@ aarch64_bitmask_imm (HOST_WIDE_INT val_in, machine_mode mode)
   return val == mask * bitmask_imm_mul[__builtin_clz (bits) - 26];
 }
 
+/* Create mask of ones, covering the lowest to highest bits set in VAL_IN.  
+   Assumed precondition: VAL_IN Is not zero.  */
+
+unsigned HOST_WIDE_INT
+aarch64_and_split_imm1 (HOST_WIDE_INT val_in)
+{
+  int lowest_bit_set = ctz_hwi (val_in);
+  int highest_bit_set = floor_log2 (val_in);
+  gcc_assert (val_in != 0);
+
+  return ((HOST_WIDE_INT_UC (2) << highest_bit_set) -
+         (HOST_WIDE_INT_1U << lowest_bit_set));
+}
+
+/* Create constant where bits outside of lowest bit set to highest bit set
+   are set to 1.  */
+
+unsigned HOST_WIDE_INT
+aarch64_and_split_imm2 (HOST_WIDE_INT val_in)
+{
+  return val_in | ~aarch64_and_split_imm1 (val_in);
+}
+
+/* Return true if VAL_IN is a valid 'and' bitmask immediate.  */
+
+bool
+aarch64_and_bitmask_imm (unsigned HOST_WIDE_INT val_in, machine_mode mode)
+{
+  if (aarch64_bitmask_imm (val_in, mode))
+    return false;
+
+  if (aarch64_move_imm (val_in, mode))
+    return false;
+
+  unsigned HOST_WIDE_INT imm2 = aarch64_and_split_imm2 (val_in);
+
+  return aarch64_bitmask_imm (imm2, mode);
+}
 
 /* Return true if val is an immediate that can be loaded into a
    register in a single instruction.  */
index 5089ccf..3d21232 100644 (file)
 ;; Logical operations
 ;; -------------------------------------------------------------------
 
+
+(define_insn_and_split "*aarch64_and<mode>_imm2"
+  [(set (match_operand:GPI 0 "register_operand" "=rk")
+       (and:GPI (match_operand:GPI 1 "register_operand" "%r")
+                (match_operand:GPI 2 "aarch64_logical_and_immediate" "<lconst2>")))]
+  ""
+  "#"
+  "true"
+  [(const_int 0)]
+  {
+     HOST_WIDE_INT val = INTVAL (operands[2]);
+     rtx imm1 = GEN_INT (aarch64_and_split_imm1 (val));
+     rtx imm2 = GEN_INT (aarch64_and_split_imm2 (val));
+
+     emit_insn (gen_and<mode>3 (operands[0], operands[1], imm1));
+     emit_insn (gen_and<mode>3 (operands[0], operands[0], imm2));
+     DONE;
+  }
+)
+
 (define_insn "<optab><mode>3"
   [(set (match_operand:GPI 0 "register_operand" "=r,rk,w")
        (LOGICAL:GPI (match_operand:GPI 1 "register_operand" "%r,r,w")
index d64a7eb..7a2847a 100644 (file)
  (and (match_code "const_int")
       (match_test "aarch64_move_imm (ival, DImode)")))
 
+(define_constraint "UsO"
+ "A constant that can be used with a 32-bit and operation."
+ (and (match_code "const_int")
+      (match_test "aarch64_and_bitmask_imm (ival, SImode)")))
+
+(define_constraint "UsP"
+ "A constant that can be used with a 64-bit and operation."
+ (and (match_code "const_int")
+      (match_test "aarch64_and_bitmask_imm (ival, DImode)")))
+
 (define_constraint "S"
   "A constraint that matches an absolute symbolic address."
   (and (match_code "const,symbol_ref,label_ref")
index 52f645a..3d63f34 100644 (file)
 ;; Attribute to describe constants acceptable in logical operations
 (define_mode_attr lconst [(SI "K") (DI "L")])
 
+;; Attribute to describe constants acceptable in logical and operations
+(define_mode_attr lconst2 [(SI "UsO") (DI "UsP")])
+
 ;; Map a mode to a specific constraint character.
 (define_mode_attr cmode [(QI "q") (HI "h") (SI "s") (DI "d")])
 
index 0671cc8..daa991b 100644 (file)
   (ior (match_operand 0 "register_operand")
        (match_operand 0 "aarch64_logical_immediate")))
 
+(define_predicate "aarch64_logical_and_immediate"
+  (and (match_code "const_int")
+       (match_test "aarch64_and_bitmask_imm (INTVAL (op), mode)")))
+
 (define_predicate "aarch64_shift_imm_si"
   (and (match_code "const_int")
        (match_test "(unsigned HOST_WIDE_INT) INTVAL (op) < 32")))
index ad75615..8f3c782 100644 (file)
@@ -1,3 +1,10 @@
+2016-11-23  Michael Collison  <michael.collison@arm.com>
+
+       * testsuite/gcc.target/aarch64/and_const.c: New test to verify
+       additional constants are recognized and fewer instructions generated.
+       * testsuite/gcc.target/aarch64/and_const2.c: New test to verify
+       additional constants are recognized and fewer instructions generated.
+
 2016-11-22  Ian Lance Taylor  <iant@golang.org>
 
        * gcc.misc-tests/godump-1.c: Update expected output for recent
diff --git a/gcc/testsuite/gcc.target/aarch64/and_const.c b/gcc/testsuite/gcc.target/aarch64/and_const.c
new file mode 100644 (file)
index 0000000..9c377d7
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+int f2 (int x)
+{
+   x &= 0x0ffffff8;
+
+   x &= 0xff001fff;
+
+   return x;
+}
+
+/* { dg-final { scan-assembler-times "and\t" 2 } } */
+/* { dg-final { scan-assembler-not "movk\t" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/and_const2.c b/gcc/testsuite/gcc.target/aarch64/and_const2.c
new file mode 100644 (file)
index 0000000..e2b8924
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+long long f2 (long x)
+{
+   x &= 0x0ffffffffffffff8LL;
+
+   x &= 0xff001fffLL;
+
+   return x;
+}
+
+/* { dg-final { scan-assembler-times "and\t" 2 } } */
+/* { dg-final { scan-assembler-not "movk\t" } } */