summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Tomsich <philipp.tomsich@theobroma-systems.com>2014-02-12 16:00:40 +0100
committerChristoph Muellner <christoph.muellner@theobroma-systems.com>2018-04-27 10:16:56 +0200
commitd7e5332c0809d246afdbe6e27c65ed4aae7005ac (patch)
tree0f67def2ee2a58ef712ec49ef7f5393a8ed91833
parentd0145f7336fe98a040938f89eb045115207ccd00 (diff)
aarch64: Optimize and(s) patterns for HI/QI operands.
HImode and QImode operands can be handled in a more optimal way for logical AND than for logical OR operations. An AND will never set bits that are not already set in its operands, so the resulting mode/precision depends on the least precision of its operands with an implicit zero-extension to any larger precision. These patterns help to avoid unnecessary zero-extension operations on benchmarks, including some SPEC workloads.
-rw-r--r--gcc/config/aarch64/aarch64.md48
-rw-r--r--gcc/config/aarch64/iterators.md2
2 files changed, 48 insertions, 2 deletions
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 742d9d5b9b75..e3c493ae85e0 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -3442,6 +3442,17 @@
[(set_attr "type" "logic_reg,logic_imm")]
)
+;; zero_extend version of above
+(define_insn "*and<mode>3_zeroextend"
+ [(set (match_operand:GPI 0 "register_operand" "=r")
+ (zero_extend:GPI
+ (and:ALLX (match_operand:ALLX 1 "register_operand" "r")
+ (match_operand:ALLX 2 "const_int_operand" "<andconst>"))))]
+ ""
+ "and\\t%w0, %w1, %w2"
+ [(set_attr "type" "logic_imm")]
+)
+
(define_insn "*and<mode>3_compare0"
[(set (reg:CC_NZ CC_REGNUM)
(compare:CC_NZ
@@ -3457,12 +3468,28 @@
[(set_attr "type" "logics_reg,logics_imm")]
)
+;; special variant for HI and QI operators (implicitly zero-extending)
+(define_insn "*and<mode>3_compare0"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ
+ (and:GPI (match_operand:SHORT 1 "register_operand" "%r,r")
+ (match_operand:SHORT 2 "aarch64_logical_operand" "r,<andconst>"))
+ (const_int 0)))
+ (set (match_operand:GPI 0 "register_operand" "=r,r")
+ (and:GPI (match_dup 1) (match_dup 2)))]
+ ""
+ "@
+ ands\\t%<w>0, %<w>1, %<w>2
+ ands\\t%<w>0, %<w>1, %2"
+ [(set_attr "type" "logic_reg,logic_imm")]
+)
+
;; zero_extend version of above
(define_insn "*andsi3_compare0_uxtw"
[(set (reg:CC_NZ CC_REGNUM)
(compare:CC_NZ
- (and:SI (match_operand:SI 1 "register_operand" "%r,r")
- (match_operand:SI 2 "aarch64_logical_operand" "r,K"))
+ (and:SI (match_operand:ALLX 1 "register_operand" "%r,r")
+ (match_operand:ALLX 2 "aarch64_logical_operand" "r,K"))
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=r,r")
(zero_extend:DI (and:SI (match_dup 1) (match_dup 2))))]
@@ -3505,6 +3532,23 @@
[(set_attr "type" "logics_shift_imm")]
)
+;; specialized form for bitfield tests
+(define_insn "*ands<mode>3_zeroextract_internal2"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ
+ (zero_extract:GPI (match_operand:GPI 0 "register_operand" "r")
+ (match_operand 1 "const_int_operand" "n")
+ (match_operand 2 "const_int_operand" "n"))
+ (const_int 0)))]
+ "aarch64_bitmask_imm((((HOST_WIDE_INT)1 << (UINTVAL(operands[1]))) - 1) << UINTVAL(operands[2]), <MODE>mode)"
+ "*
+ {
+ operands[3] = GEN_INT((((HOST_WIDE_INT)1 << (UINTVAL(operands[1]))) - 1) << UINTVAL(operands[2]));
+ return \"ands\\t<w>zr, %<w>0, %<w>3\";
+ }"
+ [(set_attr "type" "logics_reg")]
+)
+
(define_insn "*<LOGICAL:optab>_<SHIFT:optab><mode>3"
[(set (match_operand:GPI 0 "register_operand" "=r")
(LOGICAL:GPI (SHIFT:GPI
diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
index 43be7fd36111..128c906ffb93 100644
--- a/gcc/config/aarch64/iterators.md
+++ b/gcc/config/aarch64/iterators.md
@@ -442,6 +442,7 @@
;; Attribute to describe constants acceptable in logical operations
(define_mode_attr lconst [(SI "K") (DI "L")])
+(define_mode_attr andconst [(QI "K") (HI "K") (SI "K") (DI "L")])
;; Attribute to describe constants acceptable in logical and operations
(define_mode_attr lconst2 [(SI "UsO") (DI "UsP")])
@@ -815,6 +816,7 @@
;; Code iterator for logical operations
(define_code_iterator LOGICAL [and ior xor])
+(define_code_iterator OR [ior xor])
;; Code iterator for logical operations whose :nlogical works on SIMD registers.
(define_code_iterator NLOGICAL [and ior])