From: Daniel Santos <daniel.santos@pobox.com>
To: gcc <gcc@gcc.gnu.org>, Joseph Myers <joseph@codesourcery.com>,
Richard Henderson <rth@redhat.com>
Subject: [RFC] GCC 8 Project proposal: Extensions supporting C Metaprogramming, pseudo-templates
Date: Mon, 08 May 2017 23:32:00 -0000 [thread overview]
Message-ID: <02f991c6-7679-9f9b-aa57-35a25e37acd9@pobox.com> (raw)
I would like to make some changes in GCC 8, so I thought that formal
proposal and RFC would be the best path. I'm still relatively new to the
GCC project.
I began experimenting with C metaprogramming techniques back in 2012, in
order to implement more efficient generic libraries in C. The code is
ANSI C compliant and can build anywhere, but exploits GCC attributes,
checks and optimizations (when available) to assure optimal efficiency.
The underlying mechanisms involve the exploitation of constant
propagation and -findirect-inline to cause an inline function to behave
similar to a C++ templatized function that is instantiated at the call
site. The primary aim is to facilitate high-performance generic C
libraries for software where C++ is not suitable, but the cost of
run-time abstraction is unacceptable. A good example is the Linux
kernel, where the source tree is littered with more than 100 hand-coded
or boiler-plate (copy, paste and edit) search cores required to use the
red-black tree library.
Here is a brief example of a simplified qsort algo:
/* A header file for a generic qsort library. */
struct qsort_def {
size_t size;
size_t align;
int (*less_r)(const void *a, const void *b, void *context);
};
inline __attribute__((always_inline, flatten)) void
qsort_template(const struct qsort_def *def, void *const pbase, size_t n,
void *context)
{
/* details omitted... */
}
/* An implementation file using qsort. */
static inline my_less_r (const void *a, const void *b, void *context)
{
const struct my_struct *_a = a;
const struct my_struct *_b = b;
return _a->somefield < _b->somefield;
}
static const struct qsort_def my_qsort_def = {
.size = sizeof (struct my_struct),
.align = 16,
.less_r = my_less_r,
};
void __attribute__((flatten)) my_sort (struct my_struct *o, size_t n)
{
qsort_template (&my_qsort_def, o, n);
}
The purpose of the "my_sort" wrapper function is to contain the template
expansion. Beginning with GCC 4.4, when qsort_template inline expansion
occurs, the entire struct qsort_def is compiled away. The "my_less_r"
function is inlined, and by using __builtin_assume_aligned(), all
manipulation of data is performed with the best available instructions
and unneeded memcpy alignment pro/epilogues are omitted. This results in
code that's both faster and smaller and is analogous in form and
performance to C++'s std::sort, except that we are using the first
parameter (const struct qsort_def *def) in lieu of formalized template
parameters.
To further the usefulness of such techniques, I propose the addition of
a c-family attribute to declare a parameter, variable (and possibly
other declarations) as "constprop" or some similar word. The purpose of
the attribute is to:
1.) Emit a warning or error when the value is not optimized away, and
2.) Direct various optimization passes to prefer (or force) either
cloning or inlining of a function with such a parameter.
This will enable the use of pseudo-templates and:
1.) Eliminate the need for __attribute__((always_inline, flatten)) and
complicated ASSERT_CONST() macros,
2.) Eliminate the need for an __attribute__((flatten) wrapper function,
3.) Reduce the need for the programmer to think about what the compiler
is doing, and
4.) Allow gcc to decide rather inlining or cloning is better.
While not as powerful as C++ template metapgramming (type programming),
there are certainly many more possibilities that haven't yet been
discovered. I would like to be able to put something in GCC 8. Below is
my current progress.
diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
index f2a88e147ba..5ec7b615e24 100644
--- a/gcc/c-family/c-attribs.c
+++ b/gcc/c-family/c-attribs.c
@@ -139,6 +139,7 @@ static tree handle_bnd_variable_size_attribute (tree *, tree, tree, int, bool *)
static tree handle_bnd_legacy (tree *, tree, tree, int, bool *);
static tree handle_bnd_instrument (tree *, tree, tree, int, bool *);
static tree handle_fallthrough_attribute (tree *, tree, tree, int, bool *);
+static tree handle_constprop_attribute (tree *, tree , tree , int , bool *);
/* Table of machine-independent attributes common to all C-like languages.
@@ -345,6 +346,8 @@ const struct attribute_spec c_common_attribute_table[] =
handle_bnd_instrument, false },
{ "fallthrough", 0, 0, false, false, false,
handle_fallthrough_attribute, false },
+ { "constprop", 0, 0, false, false, false,
+ handle_constprop_attribute, false },
{ NULL, 0, 0, false, false, false, NULL, false }
};
@@ -3173,3 +3176,15 @@ handle_fallthrough_attribute (tree *, tree name, tree, int,
*no_add_attrs = true;
return NULL_TREE;
}
+
+static tree
+handle_constprop_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+ int flags, bool *no_add_attrs)
+{
+ if (!DECL_P (*node) || !(VAR_P (*node) || TREE_CODE (*node) == PARM_DECL))
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+ return NULL_TREE;
+}
diff --git a/gcc/common.opt b/gcc/common.opt
index 4021622cf5c..93dd10e0771 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -557,6 +557,10 @@ Wcast-align
Common Var(warn_cast_align) Warning
Warn about pointer casts which increase alignment.
+Wconstprop
+Common Var(warn_constprop) Warning
+Warn when an __attribute__((constprop)) fails to constant-propagate away.
+
Wcpp
Common Var(warn_cpp) Init(1) Warning
Warn when a #warning directive is encountered.
diff --git a/gcc/expr.c b/gcc/expr.c
index 29ebad3a061..c8aba05a76e 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -9717,6 +9717,16 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
}
case SSA_NAME:
+ {
+ tree var = SSA_NAME_VAR (exp);
+ /* TODO: Don't repeat warning for same declaration. */
+ if (var && lookup_attribute ("constprop", DECL_ATTRIBUTES (var)))
+ {
+ warning (OPT_Wconstprop, "Expression %q+D is not constant in this context", var);
+ /* TODO: Set something so we don't repeat this warning. */
+ }
+ }
+
/* ??? ivopts calls expander, without any preparation from
out-of-ssa. So fake instructions as if this was an access to the
base variable. This unnecessarily allocates a pseudo, see how we can
Comments, objections, suggestions?
Thanks,
Daniel
next reply other threads:[~2017-05-08 23:32 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-05-08 23:32 Daniel Santos [this message]
2017-05-09 9:36 ` Florian Weimer
2017-05-10 8:46 ` Daniel Santos
2017-05-09 13:29 ` Allan Sandfeld Jensen
2017-05-10 9:13 ` Daniel Santos
2017-05-10 9:24 ` Jonathan Wakely
2017-05-10 22:09 ` Daniel Santos
2017-05-11 10:12 ` Jonathan Wakely
2017-05-11 10:44 ` Marek Polacek
2017-05-11 14:35 ` Joseph Myers
2017-05-12 20:54 ` Daniel Santos
2017-05-12 21:03 ` Joseph Myers
2017-05-15 11:31 ` Vincent Lefevre
2017-05-12 15:49 ` Martin Sebor
2017-05-12 21:11 ` Daniel Santos
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=02f991c6-7679-9f9b-aa57-35a25e37acd9@pobox.com \
--to=daniel.santos@pobox.com \
--cc=gcc@gcc.gnu.org \
--cc=joseph@codesourcery.com \
--cc=rth@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).