aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2004-06-15 09:06:50 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-07 21:02:07 -0700
commit69c6e2d638d9f668b5e8631d3164cd59303c4bb8 (patch)
treef796aab55debcfe25253a33860e91fc8346f6ee5 /expression.c
parent[PATCH] trivial optimization for tokenizer (diff)
downloadsparse-69c6e2d638d9f668b5e8631d3164cd59303c4bb8.tar.gz
sparse-69c6e2d638d9f668b5e8631d3164cd59303c4bb8.tar.bz2
sparse-69c6e2d638d9f668b5e8631d3164cd59303c4bb8.zip
Macroize lr_binop_expression() helper function.
This function was the top performance offender in sparse. We really want it inlined, since all it really does is to do an indirect call or two, and if inlined that call turns into a direct call. Making it a macro allows us to pass in the operation comparison as code rather than as a list of integers, which again allows the compiler to do a much better job.
Diffstat (limited to 'expression.c')
-rw-r--r--expression.c134
1 files changed, 85 insertions, 49 deletions
diff --git a/expression.c b/expression.c
index 9e2863e..27b72e6 100644
--- a/expression.c
+++ b/expression.c
@@ -435,93 +435,126 @@ static struct token *cast_expression(struct token *token, struct expression **tr
return unary_expression(token, tree);
}
-/* Generic left-to-right binop parsing */
-static struct token *lr_binop_expression(struct token *token, struct expression **tree,
- enum expression_type type, struct token *(*inner)(struct token *, struct expression **), ...)
-{
- struct expression *left = NULL;
- struct token * next = inner(token, &left);
-
- if (left) {
- while (token_type(next) == TOKEN_SPECIAL) {
- struct expression *top, *right = NULL;
- int op = next->special;
- va_list args;
-
- va_start(args, inner);
- for (;;) {
- int nextop = va_arg(args, int);
- if (!nextop)
- goto out;
- if (op == nextop)
- break;
- }
- va_end(args);
- top = alloc_expression(next->pos, type);
- next = inner(next->next, &right);
- if (!right) {
- warn(next->pos, "No right hand side of '%s'-expression", show_special(op));
- break;
- }
- top->op = op;
- top->left = left;
- top->right = right;
- left = top;
- }
- }
-out:
- *tree = left;
- return next;
-}
+/*
+ * Generic left-to-right binop parsing
+ *
+ * This _really_ needs to be inlined, because that makes the inner
+ * function call statically deterministic rather than a totally
+ * unpredictable indirect call. But gcc-3 is so "clever" that it
+ * doesn't do so by default even when you tell it to inline it.
+ *
+ * Making it a macro avoids the inlining problem, and also means
+ * that we can pass in the op-comparison as an expression rather
+ * than create a data structure for it.
+ */
+
+#define LR_BINOP_EXPRESSION(token, tree, type, inner, compare) \
+ struct expression *left = NULL; \
+ struct token * next = inner(token, &left); \
+ \
+ if (left) { \
+ while (token_type(next) == TOKEN_SPECIAL) { \
+ struct expression *top, *right = NULL; \
+ int op = next->special; \
+ \
+ if (!(compare)) \
+ goto out; \
+ top = alloc_expression(next->pos, type); \
+ next = inner(next->next, &right); \
+ if (!right) { \
+ warn(next->pos, "No right hand side of '%s'-expression", show_special(op)); \
+ break; \
+ } \
+ top->op = op; \
+ top->left = left; \
+ top->right = right; \
+ left = top; \
+ } \
+ } \
+out: \
+ *tree = left; \
+ return next; \
+
static struct token *multiplicative_expression(struct token *token, struct expression **tree)
{
- return lr_binop_expression(token, tree, EXPR_BINOP, cast_expression, '*', '/', '%', 0);
+ LR_BINOP_EXPRESSION(
+ token, tree, EXPR_BINOP, cast_expression,
+ (op == '*') || (op == '/') || (op == '%')
+ );
}
static struct token *additive_expression(struct token *token, struct expression **tree)
{
- return lr_binop_expression(token, tree, EXPR_BINOP, multiplicative_expression, '+', '-', 0);
+ LR_BINOP_EXPRESSION(
+ token, tree, EXPR_BINOP, multiplicative_expression,
+ (op == '+') || (op == '-')
+ );
}
static struct token *shift_expression(struct token *token, struct expression **tree)
{
- return lr_binop_expression(token, tree, EXPR_BINOP, additive_expression, SPECIAL_LEFTSHIFT, SPECIAL_RIGHTSHIFT, 0);
+ LR_BINOP_EXPRESSION(
+ token, tree, EXPR_BINOP, additive_expression,
+ (op == SPECIAL_LEFTSHIFT) || (op == SPECIAL_RIGHTSHIFT)
+ );
}
static struct token *relational_expression(struct token *token, struct expression **tree)
{
- return lr_binop_expression(token, tree, EXPR_COMPARE, shift_expression, '<', '>', SPECIAL_LTE, SPECIAL_GTE, 0);
+ LR_BINOP_EXPRESSION(
+ token, tree, EXPR_COMPARE, shift_expression,
+ (op == '<') || (op == '>') ||
+ (op == SPECIAL_LTE) || (op == SPECIAL_GTE)
+ );
}
static struct token *equality_expression(struct token *token, struct expression **tree)
{
- return lr_binop_expression(token, tree, EXPR_COMPARE, relational_expression, SPECIAL_EQUAL, SPECIAL_NOTEQUAL, 0);
+ LR_BINOP_EXPRESSION(
+ token, tree, EXPR_COMPARE, relational_expression,
+ (op == SPECIAL_EQUAL) || (op == SPECIAL_NOTEQUAL)
+ );
}
static struct token *bitwise_and_expression(struct token *token, struct expression **tree)
{
- return lr_binop_expression(token, tree, EXPR_BINOP, equality_expression, '&', 0);
+ LR_BINOP_EXPRESSION(
+ token, tree, EXPR_BINOP, equality_expression,
+ (op == '&')
+ );
}
static struct token *bitwise_xor_expression(struct token *token, struct expression **tree)
{
- return lr_binop_expression(token, tree, EXPR_BINOP, bitwise_and_expression, '^', 0);
+ LR_BINOP_EXPRESSION(
+ token, tree, EXPR_BINOP, bitwise_and_expression,
+ (op == '^')
+ );
}
static struct token *bitwise_or_expression(struct token *token, struct expression **tree)
{
- return lr_binop_expression(token, tree, EXPR_BINOP, bitwise_xor_expression, '|', 0);
+ LR_BINOP_EXPRESSION(
+ token, tree, EXPR_BINOP, bitwise_xor_expression,
+ (op == '|')
+ );
}
static struct token *logical_and_expression(struct token *token, struct expression **tree)
{
- return lr_binop_expression(token, tree, EXPR_LOGICAL, bitwise_or_expression, SPECIAL_LOGICAL_AND, 0);
+ LR_BINOP_EXPRESSION(
+ token, tree, EXPR_LOGICAL, bitwise_or_expression,
+ (op == SPECIAL_LOGICAL_AND)
+ );
}
static struct token *logical_or_expression(struct token *token, struct expression **tree)
{
- return lr_binop_expression(token, tree, EXPR_LOGICAL, logical_and_expression, SPECIAL_LOGICAL_OR, 0);
+ LR_BINOP_EXPRESSION(
+ token, tree, EXPR_LOGICAL, logical_and_expression,
+ (op == SPECIAL_LOGICAL_OR)
+ );
}
struct token *conditional_expression(struct token *token, struct expression **tree)
@@ -565,7 +598,10 @@ struct token *assignment_expression(struct token *token, struct expression **tre
static struct token *comma_expression(struct token *token, struct expression **tree)
{
- return lr_binop_expression(token, tree, EXPR_COMMA, assignment_expression, ',', 0);
+ LR_BINOP_EXPRESSION(
+ token, tree, EXPR_COMMA, assignment_expression,
+ (op == ',')
+ );
}
struct token *parse_expression(struct token *token, struct expression **tree)