Hi, I am sending some old patches that we have internally since GCC 10 to the Arm Branch but feel free to comment as we will be looking to submit them for GCC 12 to mainline.
This patch adds the option '-fno-alias'. The option makes the compiler treat any pointer being passed as a parameter as if it had the keyword restrict. This option makes it easier to check whether using restrict gives a performance boost, without having to change the sources. Of course this option can only be used if you know for a fact that all pointers do not alias, or just like with the restrict keyword, things can go very wrong. The way this patch implements this option is when the option is passed, create a qualified pointer type for any pointer type encountered as a parameter. This qualified pointer type will have the TYPE_QUAL_RESTRICT bit set, just as if we had parsed a 'restrict' keyword. Bootstraped on aarch64-none-linux-gnu, to make sure I didn't break anything obvious in the build. Is this OK for trunk? gcc/ChangeLog: 2020-xx-xx Andre Vieira <andre.simoesdiasvie...@arm.com> * common.opt (fno-alias): New option. * c/cdecl.c (grokdeclarator): When flag_no_alias make all pointers passed as parameters restrict. * cp/decl.c (grokdeclarator): Likewise. * doc/invoke.texi (fno-alias): Document new option. gcc/testsuite/ChangeLog: 2020-xx-xx Andre Vieira <andre.simoesdiasvie...@arm.com> * gcc.dg/vect/vect-no-alias.c: New test. * gcc.dg/vect/noalias.h: New include file used in test. * g++.dg/vect/simd-no-alias.cc: New test. --
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index c819fd0d0d54b7147c782850f28e861b2f6b0349..f101ea090f3fd2254a1c9c891644a53fe11f75c0 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -7160,8 +7160,18 @@ grokdeclarator (const struct c_declarator *declarator, type = c_build_pointer_type (type); type_quals = TYPE_UNQUALIFIED; } - else if (type_quals) - type = c_build_qualified_type (type, type_quals); + else + { + /* If -fno-alias then make all pointers used as parameters + restrict pointers. */ + if (flag_no_alias && POINTER_TYPE_P (type) + && !POINTER_TYPE_P (TREE_TYPE (type)) + && TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE) + type_quals |= TYPE_QUAL_RESTRICT; + + if (type_quals) + type = c_build_qualified_type (type, type_quals); + } decl = build_decl (declarator->id_loc, PARM_DECL, declarator->u.id.id, type); diff --git a/gcc/common.opt b/gcc/common.opt index fa9da505fc2766794e731312ef6394f75a940d82..02882ec633a74b3014426ffa8da1485c373415a4 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -3392,4 +3392,7 @@ fipa-ra Common Report Var(flag_ipa_ra) Optimization Use caller save register across calls if possible. +fno-alias +Common RejectNegative Var(flag_no_alias) Optimization + ; This comment is to ensure we retain the blank line above. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index e3f4b435a4905d38e66215a8343f96429af834a0..0c843b29cfe3f69a2b544f66887087659edb1d32 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -13035,6 +13035,16 @@ grokdeclarator (const cp_declarator *declarator, if (decl_context == PARM) { + /* If -fno-alias then make all pointers used as parameters + restrict pointers. */ + if (flag_no_alias && POINTER_TYPE_P (type) + && !POINTER_TYPE_P (TREE_TYPE (type)) + && TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE) + { + type = cp_build_qualified_type (type, + TYPE_QUALS (type) + | TYPE_QUAL_RESTRICT); + } decl = cp_build_parm_decl (NULL_TREE, unqualified_id, type); DECL_ARRAY_PARAMETER_P (decl) = array_parameter_p; diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 54375ebd6799447bf468a56b03d044ac997fb842..44cb584f45f08c8f0a19d7370fc43d44641ba52c 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -496,7 +496,7 @@ Objective-C and Objective-C++ Dialects}. -fno-defer-pop -fno-fp-int-builtin-inexact -fno-function-cse @gol -fno-guess-branch-probability -fno-inline -fno-math-errno -fno-peephole @gol -fno-peephole2 -fno-printf-return-value -fno-sched-interblock @gol --fno-sched-spec -fno-signed-zeros @gol +-fno-sched-spec -fno-signed-zeros -fno-alias @gol -fno-toplevel-reorder -fno-trapping-math -fno-zero-initialized-in-bss @gol -fomit-frame-pointer -foptimize-sibling-calls @gol -fpartial-inlining -fpeel-loops -fpredictive-commoning @gol @@ -10887,6 +10887,14 @@ example, an @code{unsigned int} can alias an @code{int}, but not a @code{void*} or a @code{double}. A character type may alias any other type. +@item -fno-alias +@opindex fno-alias +This option is equivalent to adding the @code{restrict} keyword to all pointers +used as parameters. This option can be used to assess the performance impact +of adding restrict to your pointers without having to make code changes. Be +aware that the compiler does not actually perform any check to the validity of +adding restrict and if pointers do alias correctness is not guaranteed. + @anchor{Type-punning}Pay special attention to code like this: @smallexample union a_union @{ diff --git a/gcc/testsuite/g++.dg/vect/simd-no-alias.cc b/gcc/testsuite/g++.dg/vect/simd-no-alias.cc new file mode 100644 index 0000000000000000000000000000000000000000..a73e0e94f6442ff609c38c80920ed20c2cb65e89 --- /dev/null +++ b/gcc/testsuite/g++.dg/vect/simd-no-alias.cc @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-fno-alias" } */ +/* { dg-require-effective-target vect_int } */ + +class A { + +public: + +A (); +void foo (int * dest, int * src1, int * src2, int n, void (*__func)(void)); +}; + + +void A::foo (int * dest, int * src1, int * src2, int n, void (*__func)(void)) +{ + for (int i = 0; i < n; ++i) + dest[i] = src1[i] + src2[i]; + + __func (); +} + +/* { dg-final { scan-tree-dump-not "versioning for alias required" "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/noalias.h b/gcc/testsuite/gcc.dg/vect/noalias.h new file mode 100644 index 0000000000000000000000000000000000000000..604e4b1efc89061f6602018810e9e378f29eff6f --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/noalias.h @@ -0,0 +1 @@ +extern int *a; diff --git a/gcc/testsuite/gcc.dg/vect/vect-no-alias.c b/gcc/testsuite/gcc.dg/vect/vect-no-alias.c new file mode 100644 index 0000000000000000000000000000000000000000..4921afb874eac18a184519316f140fb395f14c03 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-no-alias.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-fno-alias" } */ +/* { dg-require-effective-target vect_int } */ + +void foo (int * dest, int * src1, int * src2, int n) +{ + for (int i = 0; i < n; ++i) + dest[i] = src1[i] + src2[i]; +} + +/* The rest of this test is to make sure we aren't adding restrict to pointers + that should not have restrict. */ + +void bar (void (* __func) (void)) +{ + __func (); +} + +#include "noalias.h" +int *a; + +/* { dg-final { scan-tree-dump-not "versioning for alias required" "vect" } } */