aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@arm.com>2019-11-18 15:36:10 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2019-11-18 15:36:10 +0000
commit58c036c8354e4d14551ceaeffaa1dda2fe445640 (patch)
treec4f41c8fbb38f8a7e7be198e099f370ebd20789b /gcc/config
parent78930e4b4867c0558cf347778591a67a0b235ca0 (diff)
downloadgcc-58c036c8354e4d14551ceaeffaa1dda2fe445640.zip
gcc-58c036c8354e4d14551ceaeffaa1dda2fe445640.tar.gz
gcc-58c036c8354e4d14551ceaeffaa1dda2fe445640.tar.bz2
Add optabs for accelerating RAW and WAR alias checks
This patch adds optabs that check whether a read followed by a write or a write followed by a read can be divided into interleaved byte accesses without changing the dependencies between the bytes. This is one of the uses of the SVE2 WHILERW and WHILEWR instructions. (The instructions can also be used to limit the VF at runtime, but that's future work.) 2019-11-18 Richard Sandiford <richard.sandiford@arm.com> gcc/ * doc/sourcebuild.texi (vect_check_ptrs): Document. * optabs.def (check_raw_ptrs_optab, check_war_ptrs_optab): New optabs. * doc/md.texi: Document them. * internal-fn.def (IFN_CHECK_RAW_PTRS, IFN_CHECK_WAR_PTRS): New internal functions. * internal-fn.h (internal_check_ptrs_fn_supported_p): Declare. * internal-fn.c (check_ptrs_direct): New macro. (expand_check_ptrs_optab_fn): Likewise. (direct_check_ptrs_optab_supported_p): Likewise. (internal_check_ptrs_fn_supported_p): New fuction. * tree-data-ref.c: Include internal-fn.h. (create_ifn_alias_checks): New function. (create_intersect_range_checks): Use it. * config/aarch64/iterators.md (SVE2_WHILE_PTR): New int iterator. (optab, cmp_op): Handle it. (raw_war, unspec): New int attributes. * config/aarch64/aarch64.md (UNSPEC_WHILERW, UNSPEC_WHILE_WR): New constants. * config/aarch64/predicates.md (aarch64_bytes_per_sve_vector_operand): New predicate. * config/aarch64/aarch64-sve2.md (check_<raw_war>_ptrs<mode>): New expander. (@aarch64_sve2_while<cmp_op><GPI:mode><PRED_ALL:mode>_ptest): New pattern. gcc/testsuite/ * lib/target-supports.exp (check_effective_target_vect_check_ptrs): New procedure. * gcc.dg/vect/vect-alias-check-14.c: Expect IFN_CHECK_WAR to be used, if available. * gcc.dg/vect/vect-alias-check-15.c: Likewise. * gcc.dg/vect/vect-alias-check-16.c: Likewise IFN_CHECK_RAW. * gcc.target/aarch64/sve2/whilerw_1.c: New test. * gcc.target/aarch64/sve2/whilewr_1.c: Likewise. * gcc.target/aarch64/sve2/whilewr_2.c: Likewise. From-SVN: r278414
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/aarch64/aarch64-sve2.md58
-rw-r--r--gcc/config/aarch64/aarch64.md2
-rw-r--r--gcc/config/aarch64/iterators.md14
-rw-r--r--gcc/config/aarch64/predicates.md5
4 files changed, 78 insertions, 1 deletions
diff --git a/gcc/config/aarch64/aarch64-sve2.md b/gcc/config/aarch64/aarch64-sve2.md
index 15142d1..106a9a0 100644
--- a/gcc/config/aarch64/aarch64-sve2.md
+++ b/gcc/config/aarch64/aarch64-sve2.md
@@ -331,3 +331,61 @@
}
[(set_attr "movprfx" "*,yes")]
)
+
+;; Use WHILERW and WHILEWR to accelerate alias checks. This is only
+;; possible if the accesses we're checking are exactly the same size
+;; as an SVE vector.
+(define_expand "check_<raw_war>_ptrs<mode>"
+ [(match_operand:GPI 0 "register_operand")
+ (unspec:VNx16BI
+ [(match_operand:GPI 1 "register_operand")
+ (match_operand:GPI 2 "register_operand")
+ (match_operand:GPI 3 "aarch64_bytes_per_sve_vector_operand")
+ (match_operand:GPI 4 "const_int_operand")]
+ SVE2_WHILE_PTR)]
+ "TARGET_SVE2"
+{
+ /* Use the widest predicate mode we can. */
+ unsigned int align = INTVAL (operands[4]);
+ if (align > 8)
+ align = 8;
+ machine_mode pred_mode = aarch64_sve_pred_mode (align).require ();
+
+ /* Emit a WHILERW or WHILEWR, setting the condition codes based on
+ the result. */
+ emit_insn (gen_aarch64_sve2_while_ptest
+ (<SVE2_WHILE_PTR:unspec>, <MODE>mode, pred_mode,
+ gen_rtx_SCRATCH (pred_mode), operands[1], operands[2],
+ CONSTM1_RTX (VNx16BImode), CONSTM1_RTX (pred_mode)));
+
+ /* Set operand 0 to true if the last bit of the predicate result is set,
+ i.e. if all elements are free of dependencies. */
+ rtx cc_reg = gen_rtx_REG (CC_NZCmode, CC_REGNUM);
+ rtx cmp = gen_rtx_LTU (<MODE>mode, cc_reg, const0_rtx);
+ emit_insn (gen_aarch64_cstore<mode> (operands[0], cmp, cc_reg));
+ DONE;
+})
+
+;; A WHILERW or WHILEWR in which only the flags result is interesting.
+(define_insn_and_rewrite "@aarch64_sve2_while<cmp_op><GPI:mode><PRED_ALL:mode>_ptest"
+ [(set (reg:CC_NZC CC_REGNUM)
+ (unspec:CC_NZC
+ [(match_operand 3)
+ (match_operand 4)
+ (const_int SVE_KNOWN_PTRUE)
+ (unspec:PRED_ALL
+ [(match_operand:GPI 1 "register_operand" "r")
+ (match_operand:GPI 2 "register_operand" "r")]
+ SVE2_WHILE_PTR)]
+ UNSPEC_PTEST))
+ (clobber (match_scratch:PRED_ALL 0 "=Upa"))]
+ "TARGET_SVE2"
+ "while<cmp_op>\t%0.<PRED_ALL:Vetype>, %x1, %x2"
+ ;; Force the compiler to drop the unused predicate operand, so that we
+ ;; don't have an unnecessary PTRUE.
+ "&& (!CONSTANT_P (operands[3]) || !CONSTANT_P (operands[4]))"
+ {
+ operands[3] = CONSTM1_RTX (VNx16BImode);
+ operands[4] = CONSTM1_RTX (<PRED_ALL:MODE>mode);
+ }
+)
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index f19e227..87e9b936 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -245,6 +245,8 @@
UNSPEC_WHILE_LO
UNSPEC_WHILE_LS
UNSPEC_WHILE_LT
+ UNSPEC_WHILERW
+ UNSPEC_WHILEWR
UNSPEC_LDN
UNSPEC_STN
UNSPEC_INSR
diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
index bfeebe9..83a0d15 100644
--- a/gcc/config/aarch64/iterators.md
+++ b/gcc/config/aarch64/iterators.md
@@ -2077,6 +2077,8 @@
(define_int_iterator SVE_WHILE [UNSPEC_WHILE_LE UNSPEC_WHILE_LO
UNSPEC_WHILE_LS UNSPEC_WHILE_LT])
+(define_int_iterator SVE2_WHILE_PTR [UNSPEC_WHILERW UNSPEC_WHILEWR])
+
(define_int_iterator SVE_SHIFT_WIDE [UNSPEC_ASHIFT_WIDE
UNSPEC_ASHIFTRT_WIDE
UNSPEC_LSHIFTRT_WIDE])
@@ -2157,6 +2159,8 @@
(UNSPEC_FEXPA "fexpa")
(UNSPEC_FTSMUL "ftsmul")
(UNSPEC_FTSSEL "ftssel")
+ (UNSPEC_WHILERW "vec_check_raw_alias")
+ (UNSPEC_WHILEWR "vec_check_war_alias")
(UNSPEC_COND_FABS "abs")
(UNSPEC_COND_FADD "add")
(UNSPEC_COND_FCADD90 "cadd90")
@@ -2480,13 +2484,18 @@
(UNSPEC_WHILE_LE "le")
(UNSPEC_WHILE_LO "lo")
(UNSPEC_WHILE_LS "ls")
- (UNSPEC_WHILE_LT "lt")])
+ (UNSPEC_WHILE_LT "lt")
+ (UNSPEC_WHILERW "rw")
+ (UNSPEC_WHILEWR "wr")])
(define_int_attr while_optab_cmp [(UNSPEC_WHILE_LE "le")
(UNSPEC_WHILE_LO "ult")
(UNSPEC_WHILE_LS "ule")
(UNSPEC_WHILE_LT "lt")])
+(define_int_attr raw_war [(UNSPEC_WHILERW "raw")
+ (UNSPEC_WHILEWR "war")])
+
(define_int_attr brk_op [(UNSPEC_BRKA "a") (UNSPEC_BRKB "b")
(UNSPEC_BRKN "n")
(UNSPEC_BRKPA "pa") (UNSPEC_BRKPB "pb")])
@@ -2630,3 +2639,6 @@
(UNSPEC_REVB "16")
(UNSPEC_REVH "32")
(UNSPEC_REVW "64")])
+
+(define_int_attr unspec [(UNSPEC_WHILERW "UNSPEC_WHILERW")
+ (UNSPEC_WHILEWR "UNSPEC_WHILEWR")])
diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md
index 2c5c53c..2323612 100644
--- a/gcc/config/aarch64/predicates.md
+++ b/gcc/config/aarch64/predicates.md
@@ -869,3 +869,8 @@
(define_predicate "aarch64_sve_any_binary_operator"
(match_code "plus,minus,mult,div,udiv,smax,umax,smin,umin,and,ior,xor"))
+
+(define_predicate "aarch64_bytes_per_sve_vector_operand"
+ (and (match_code "const_int,const_poly_int")
+ (match_test "known_eq (wi::to_poly_wide (op, mode),
+ BYTES_PER_SVE_VECTOR)")))