From 43fd192f76a0121197dcc3975a49b79b201f6411 Mon Sep 17 00:00:00 2001 From: Michael Collison Date: Wed, 23 Nov 2016 07:47:25 +0000 Subject: [PATCH] 2016-11-22 Michael Collison * 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:(and3): New define_insn and _split allowing wider range of constants with "and" operations. * (ior3, xor3): 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 | 27 +++++++++++++++++++ gcc/config/aarch64/aarch64-protos.h | 3 +++ gcc/config/aarch64/aarch64.c | 38 +++++++++++++++++++++++++++ gcc/config/aarch64/aarch64.md | 20 ++++++++++++++ gcc/config/aarch64/constraints.md | 10 +++++++ gcc/config/aarch64/iterators.md | 3 +++ gcc/config/aarch64/predicates.md | 4 +++ gcc/testsuite/ChangeLog | 7 +++++ gcc/testsuite/gcc.target/aarch64/and_const.c | 14 ++++++++++ gcc/testsuite/gcc.target/aarch64/and_const2.c | 14 ++++++++++ 10 files changed, 140 insertions(+) create mode 100644 gcc/testsuite/gcc.target/aarch64/and_const.c create mode 100644 gcc/testsuite/gcc.target/aarch64/and_const2.c 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 + + * 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:(and3): New define_insn and _split + allowing wider range of constants with "and" operations. + * (ior3, xor3): 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 * 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_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" "")))] + "" + "#" + "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_and3 (operands[0], operands[1], imm1)); + emit_insn (gen_and3 (operands[0], operands[0], imm2)); + DONE; + } +) + (define_insn "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 + + * 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 * 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" } } */ -- 2.7.4