aboutsummaryrefslogtreecommitdiff
path: root/gcc/builtins.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r--gcc/builtins.c97
1 files changed, 97 insertions, 0 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 1ca5b5d..fcb6a7a 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -2520,3 +2520,100 @@ expand_builtin (exp, target, subtarget, mode, ignore)
to be called normally. */
return expand_call (exp, target, ignore);
}
+
+/* Recognize certain built-in functions so we can make tree-codes
+ other than CALL_EXPR. We do this when it enables fold-const.c
+ to do something useful. */
+
+tree
+expand_tree_builtin (function, params, coerced_params)
+ tree function, params, coerced_params;
+{
+ enum tree_code code;
+
+ if (DECL_BUILT_IN_CLASS (function) != BUILT_IN_NORMAL)
+ return NULL_TREE;
+
+ switch (DECL_FUNCTION_CODE (function))
+ {
+ case BUILT_IN_ABS:
+ case BUILT_IN_LABS:
+ case BUILT_IN_FABS:
+ if (coerced_params == 0)
+ return integer_zero_node;
+ return build_unary_op (ABS_EXPR, TREE_VALUE (coerced_params), 0);
+
+ case BUILT_IN_ISGREATER:
+ if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
+ code = UNLE_EXPR;
+ else
+ code = LE_EXPR;
+ goto unordered_cmp;
+
+ case BUILT_IN_ISGREATEREQUAL:
+ if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
+ code = UNLT_EXPR;
+ else
+ code = LT_EXPR;
+ goto unordered_cmp;
+
+ case BUILT_IN_ISLESS:
+ if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
+ code = UNGE_EXPR;
+ else
+ code = GE_EXPR;
+ goto unordered_cmp;
+
+ case BUILT_IN_ISLESSEQUAL:
+ if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
+ code = UNGT_EXPR;
+ else
+ code = GT_EXPR;
+ goto unordered_cmp;
+
+ case BUILT_IN_ISLESSGREATER:
+ if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
+ code = UNEQ_EXPR;
+ else
+ code = EQ_EXPR;
+ goto unordered_cmp;
+
+ case BUILT_IN_ISUNORDERED:
+ if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT)
+ return integer_zero_node;
+ code = UNORDERED_EXPR;
+ goto unordered_cmp;
+
+ unordered_cmp:
+ {
+ tree arg0, arg1;
+
+ if (params == 0
+ || TREE_CHAIN (params) == 0)
+ {
+ error ("too few arguments to function `%s'",
+ IDENTIFIER_POINTER (DECL_NAME (function)));
+ return error_mark_node;
+ }
+ else if (TREE_CHAIN (TREE_CHAIN (params)) != 0)
+ {
+ error ("too many arguments to function `%s'",
+ IDENTIFIER_POINTER (DECL_NAME (function)));
+ return error_mark_node;
+ }
+
+ arg0 = TREE_VALUE (params);
+ arg1 = TREE_VALUE (TREE_CHAIN (params));
+ arg0 = build_binary_op (code, arg0, arg1, 0);
+ if (code != UNORDERED_EXPR)
+ arg0 = build_unary_op (TRUTH_NOT_EXPR, arg0, 0);
+ return arg0;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return NULL_TREE;
+}