aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMichael Collison <michael.collison@arm.com>2016-11-23 07:47:25 +0000
committerMichael Collison <collison@gcc.gnu.org>2016-11-23 07:47:25 +0000
commit43fd192f76a0121197dcc3975a49b79b201f6411 (patch)
treee928fb5fdbc6ba8b63c59833f9f46e4eafc0ae9a /gcc
parented9e2fa904c6112180bcba317908b49c106c0cd0 (diff)
downloadgcc-43fd192f76a0121197dcc3975a49b79b201f6411.zip
gcc-43fd192f76a0121197dcc3975a49b79b201f6411.tar.gz
gcc-43fd192f76a0121197dcc3975a49b79b201f6411.tar.bz2
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. * 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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog27
-rw-r--r--gcc/config/aarch64/aarch64-protos.h3
-rw-r--r--gcc/config/aarch64/aarch64.c38
-rw-r--r--gcc/config/aarch64/aarch64.md20
-rw-r--r--gcc/config/aarch64/constraints.md10
-rw-r--r--gcc/config/aarch64/iterators.md3
-rw-r--r--gcc/config/aarch64/predicates.md4
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/gcc.target/aarch64/and_const.c14
-rw-r--r--gcc/testsuite/gcc.target/aarch64/and_const2.c14
10 files changed, 140 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 97320c7..ea39ef0 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index b6ca3df..7f67f14 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -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);
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index efcba83..1f35220 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -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. */
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 5089ccf..3d21232 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -3397,6 +3397,26 @@
;; 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")
diff --git a/gcc/config/aarch64/constraints.md b/gcc/config/aarch64/constraints.md
index d64a7eb..7a2847a 100644
--- a/gcc/config/aarch64/constraints.md
+++ b/gcc/config/aarch64/constraints.md
@@ -69,6 +69,16 @@
(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")
diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
index 52f645a..3d63f34 100644
--- a/gcc/config/aarch64/iterators.md
+++ b/gcc/config/aarch64/iterators.md
@@ -440,6 +440,9 @@
;; 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")])
diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md
index 0671cc8..daa991b 100644
--- a/gcc/config/aarch64/predicates.md
+++ b/gcc/config/aarch64/predicates.md
@@ -106,6 +106,10 @@
(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")))
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index ad75615..8f3c782 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..9c377d7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/and_const.c
@@ -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
index 0000000..e2b8924
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/and_const2.c
@@ -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" } } */