summaryrefslogtreecommitdiff
path: root/tools/perf/util/expr.y
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/expr.y')
-rw-r--r--tools/perf/util/expr.y86
1 files changed, 69 insertions, 17 deletions
diff --git a/tools/perf/util/expr.y b/tools/perf/util/expr.y
index 4ce931cccb63..f04963eb6be0 100644
--- a/tools/perf/util/expr.y
+++ b/tools/perf/util/expr.y
@@ -123,20 +123,6 @@ static struct ids handle_id(struct expr_parse_ctx *ctx, char *id,
* constant value using OP. Its invariant that there are no ids. If computing
* ids for non-constants union the set of IDs that must be computed.
*/
-#define BINARY_LONG_OP(RESULT, OP, LHS, RHS) \
- if (!compute_ids || (is_const(LHS.val) && is_const(RHS.val))) { \
- assert(LHS.ids == NULL); \
- assert(RHS.ids == NULL); \
- if (isnan(LHS.val) || isnan(RHS.val)) { \
- RESULT.val = NAN; \
- } else { \
- RESULT.val = (long)LHS.val OP (long)RHS.val; \
- } \
- RESULT.ids = NULL; \
- } else { \
- RESULT = union_expr(LHS, RHS); \
- }
-
#define BINARY_OP(RESULT, OP, LHS, RHS) \
if (!compute_ids || (is_const(LHS.val) && is_const(RHS.val))) { \
assert(LHS.ids == NULL); \
@@ -213,9 +199,75 @@ expr: NUMBER
}
| ID { $$ = handle_id(ctx, $1, compute_ids, /*source_count=*/false); }
| SOURCE_COUNT '(' ID ')' { $$ = handle_id(ctx, $3, compute_ids, /*source_count=*/true); }
-| expr '|' expr { BINARY_LONG_OP($$, |, $1, $3); }
-| expr '&' expr { BINARY_LONG_OP($$, &, $1, $3); }
-| expr '^' expr { BINARY_LONG_OP($$, ^, $1, $3); }
+| expr '|' expr
+{
+ if (is_const($1.val) && is_const($3.val)) {
+ assert($1.ids == NULL);
+ assert($3.ids == NULL);
+ $$.ids = NULL;
+ $$.val = (fpclassify($1.val) == FP_ZERO && fpclassify($3.val) == FP_ZERO) ? 0 : 1;
+ } else if (is_const($1.val)) {
+ assert($1.ids == NULL);
+ if (fpclassify($1.val) == FP_ZERO) {
+ $$ = $3;
+ } else {
+ $$.val = 1;
+ $$.ids = NULL;
+ ids__free($3.ids);
+ }
+ } else if (is_const($3.val)) {
+ assert($3.ids == NULL);
+ if (fpclassify($3.val) == FP_ZERO) {
+ $$ = $1;
+ } else {
+ $$.val = 1;
+ $$.ids = NULL;
+ ids__free($1.ids);
+ }
+ } else {
+ $$ = union_expr($1, $3);
+ }
+}
+| expr '&' expr
+{
+ if (is_const($1.val) && is_const($3.val)) {
+ assert($1.ids == NULL);
+ assert($3.ids == NULL);
+ $$.val = (fpclassify($1.val) != FP_ZERO && fpclassify($3.val) != FP_ZERO) ? 1 : 0;
+ $$.ids = NULL;
+ } else if (is_const($1.val)) {
+ assert($1.ids == NULL);
+ if (fpclassify($1.val) != FP_ZERO) {
+ $$ = $3;
+ } else {
+ $$.val = 0;
+ $$.ids = NULL;
+ ids__free($3.ids);
+ }
+ } else if (is_const($3.val)) {
+ assert($3.ids == NULL);
+ if (fpclassify($3.val) != FP_ZERO) {
+ $$ = $1;
+ } else {
+ $$.val = 0;
+ $$.ids = NULL;
+ ids__free($1.ids);
+ }
+ } else {
+ $$ = union_expr($1, $3);
+ }
+}
+| expr '^' expr
+{
+ if (is_const($1.val) && is_const($3.val)) {
+ assert($1.ids == NULL);
+ assert($3.ids == NULL);
+ $$.val = (fpclassify($1.val) == FP_ZERO) != (fpclassify($3.val) == FP_ZERO) ? 1 : 0;
+ $$.ids = NULL;
+ } else {
+ $$ = union_expr($1, $3);
+ }
+}
| expr '<' expr { BINARY_OP($$, <, $1, $3); }
| expr '>' expr { BINARY_OP($$, >, $1, $3); }
| expr '+' expr { BINARY_OP($$, +, $1, $3); }