summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/builtins.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/gcc/builtins.c')
-rw-r--r--contrib/gcc/builtins.c241
1 files changed, 73 insertions, 168 deletions
diff --git a/contrib/gcc/builtins.c b/contrib/gcc/builtins.c
index d088274..4c5650a 100644
--- a/contrib/gcc/builtins.c
+++ b/contrib/gcc/builtins.c
@@ -1344,12 +1344,7 @@ expand_builtin_apply (function, arguments, argsize)
OK_DEFER_POP;
/* Return the address of the result block. */
- result = copy_addr_to_reg (XEXP (result, 0));
-#ifdef POINTERS_EXTEND_UNSIGNED
- if (GET_MODE (result) != ptr_mode)
- result = convert_memory_address (ptr_mode, result);
-#endif
- return result;
+ return copy_addr_to_reg (XEXP (result, 0));
}
/* Perform an untyped return. */
@@ -2353,7 +2348,7 @@ expand_builtin_bzero (exp)
return result;
}
-/* Expand expression EXP, which is a call to the memcmp built-in function.
+/* Expand expression EXP, which is a call to the memcmp or the strcmp builtin.
ARGLIST is the argument list for this call. Return 0 if we failed and the
caller should emit a normal call, otherwise try to get the result in
TARGET, if convenient (and in mode MODE, if that's convenient). */
@@ -2490,7 +2485,7 @@ expand_builtin_strcmp (exp, target, mode)
enum machine_mode mode;
{
tree arglist = TREE_OPERAND (exp, 1);
- tree arg1, arg2;
+ tree arg1, arg2, len, len2, fn;
const char *p1, *p2;
if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
@@ -2526,89 +2521,51 @@ expand_builtin_strcmp (exp, target, mode)
return expand_expr (result, target, mode, EXPAND_NORMAL);
}
-#ifdef HAVE_cmpstrsi
- if (HAVE_cmpstrsi)
- {
- tree len, len1, len2;
- rtx arg1_rtx, arg2_rtx, arg3_rtx;
- rtx result, insn;
-
- int arg1_align
- = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
- int arg2_align
- = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
- enum machine_mode insn_mode
- = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
-
- len1 = c_strlen (arg1);
- len2 = c_strlen (arg2);
-
- if (len1)
- len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
- if (len2)
- len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
-
- /* If we don't have a constant length for the first, use the length
- of the second, if we know it. We don't require a constant for
- this case; some cost analysis could be done if both are available
- but neither is constant. For now, assume they're equally cheap
- unless one has side effects. If both strings have constant lengths,
- use the smaller. */
-
- if (!len1)
- len = len2;
- else if (!len2)
- len = len1;
- else if (TREE_SIDE_EFFECTS (len1))
- len = len2;
- else if (TREE_SIDE_EFFECTS (len2))
- len = len1;
- else if (TREE_CODE (len1) != INTEGER_CST)
- len = len2;
- else if (TREE_CODE (len2) != INTEGER_CST)
- len = len1;
- else if (tree_int_cst_lt (len1, len2))
- len = len1;
- else
- len = len2;
+ len = c_strlen (arg1);
+ len2 = c_strlen (arg2);
- /* If both arguments have side effects, we cannot optimize. */
- if (!len || TREE_SIDE_EFFECTS (len))
- return 0;
+ if (len)
+ len = size_binop (PLUS_EXPR, ssize_int (1), len);
- /* If we don't have POINTER_TYPE, call the function. */
- if (arg1_align == 0 || arg2_align == 0)
- return 0;
+ if (len2)
+ len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
- /* Make a place to write the result of the instruction. */
- result = target;
- if (! (result != 0
- && GET_CODE (result) == REG
- && GET_MODE (result) == insn_mode
- && REGNO (result) >= FIRST_PSEUDO_REGISTER))
- result = gen_reg_rtx (insn_mode);
+ /* If we don't have a constant length for the first, use the length
+ of the second, if we know it. We don't require a constant for
+ this case; some cost analysis could be done if both are available
+ but neither is constant. For now, assume they're equally cheap
+ unless one has side effects.
- arg1_rtx = get_memory_rtx (arg1);
- arg2_rtx = get_memory_rtx (arg2);
- arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
- insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
- GEN_INT (MIN (arg1_align, arg2_align)));
- if (!insn)
+ If both strings have constant lengths, use the smaller. This
+ could arise if optimization results in strcpy being called with
+ two fixed strings, or if the code was machine-generated. We should
+ add some code to the `memcmp' handler below to deal with such
+ situations, someday. */
+
+ if (!len || TREE_CODE (len) != INTEGER_CST)
+ {
+ if (len2 && !TREE_SIDE_EFFECTS (len2))
+ len = len2;
+ else if (len == 0)
return 0;
+ }
+ else if (len2 && TREE_CODE (len2) == INTEGER_CST
+ && tree_int_cst_lt (len2, len))
+ len = len2;
- emit_insn (insn);
+ /* If both arguments have side effects, we cannot optimize. */
+ if (TREE_SIDE_EFFECTS (len))
+ return 0;
- /* Return the value in the proper mode for this function. */
- mode = TYPE_MODE (TREE_TYPE (exp));
- if (GET_MODE (result) == mode)
- return result;
- if (target == 0)
- return convert_to_mode (mode, result, 0);
- convert_move (target, result, 0);
- return target;
- }
-#endif
- return 0;
+ fn = built_in_decls[BUILT_IN_MEMCMP];
+ if (!fn)
+ return 0;
+
+ arglist = build_tree_list (NULL_TREE, len);
+ arglist = tree_cons (NULL_TREE, arg2, arglist);
+ arglist = tree_cons (NULL_TREE, arg1, arglist);
+ return expand_expr (build_function_call_expr (fn, arglist),
+ target, mode, EXPAND_NORMAL);
}
/* Expand expression EXP, which is a call to the strncmp builtin. Return 0
@@ -2622,6 +2579,7 @@ expand_builtin_strncmp (exp, target, mode)
enum machine_mode mode;
{
tree arglist = TREE_OPERAND (exp, 1);
+ tree fn, newarglist, len = 0;
tree arg1, arg2, arg3;
const char *p1, *p2;
@@ -2675,94 +2633,41 @@ expand_builtin_strncmp (exp, target, mode)
}
/* If c_strlen can determine an expression for one of the string
- lengths, and it doesn't have side effects, then emit cmpstrsi
- using length MIN(strlen(string)+1, arg3). */
-#ifdef HAVE_cmpstrsi
- if (HAVE_cmpstrsi)
- {
- tree len, len1, len2;
- rtx arg1_rtx, arg2_rtx, arg3_rtx;
- rtx result, insn;
-
- int arg1_align
- = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
- int arg2_align
- = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
- enum machine_mode insn_mode
- = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
-
- len1 = c_strlen (arg1);
- len2 = c_strlen (arg2);
-
- if (len1)
- len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
- if (len2)
- len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
-
- /* If we don't have a constant length for the first, use the length
- of the second, if we know it. We don't require a constant for
- this case; some cost analysis could be done if both are available
- but neither is constant. For now, assume they're equally cheap,
- unless one has side effects. If both strings have constant lengths,
- use the smaller. */
-
- if (!len1)
- len = len2;
- else if (!len2)
- len = len1;
- else if (TREE_SIDE_EFFECTS (len1))
- len = len2;
- else if (TREE_SIDE_EFFECTS (len2))
- len = len1;
- else if (TREE_CODE (len1) != INTEGER_CST)
- len = len2;
- else if (TREE_CODE (len2) != INTEGER_CST)
- len = len1;
- else if (tree_int_cst_lt (len1, len2))
- len = len1;
- else
- len = len2;
-
- /* If both arguments have side effects, we cannot optimize. */
- if (!len || TREE_SIDE_EFFECTS (len))
- return 0;
-
- /* The actual new length parameter is MIN(len,arg3). */
- len = fold (build (MIN_EXPR, TREE_TYPE (len), len, arg3));
-
- /* If we don't have POINTER_TYPE, call the function. */
- if (arg1_align == 0 || arg2_align == 0)
- return 0;
+ lengths, and it doesn't have side effects, then call
+ expand_builtin_memcmp() using length MIN(strlen(string)+1, arg3). */
+
+ /* Perhaps one of the strings is really constant, if so prefer
+ that constant length over the other string's length. */
+ if (p1)
+ len = c_strlen (arg1);
+ else if (p2)
+ len = c_strlen (arg2);
+
+ /* If we still don't have a len, try either string arg as long
+ as they don't have side effects. */
+ if (!len && !TREE_SIDE_EFFECTS (arg1))
+ len = c_strlen (arg1);
+ if (!len && !TREE_SIDE_EFFECTS (arg2))
+ len = c_strlen (arg2);
+ /* If we still don't have a length, punt. */
+ if (!len)
+ return 0;
- /* Make a place to write the result of the instruction. */
- result = target;
- if (! (result != 0
- && GET_CODE (result) == REG
- && GET_MODE (result) == insn_mode
- && REGNO (result) >= FIRST_PSEUDO_REGISTER))
- result = gen_reg_rtx (insn_mode);
+ fn = built_in_decls[BUILT_IN_MEMCMP];
+ if (!fn)
+ return 0;
- arg1_rtx = get_memory_rtx (arg1);
- arg2_rtx = get_memory_rtx (arg2);
- arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
- insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
- GEN_INT (MIN (arg1_align, arg2_align)));
- if (!insn)
- return 0;
+ /* Add one to the string length. */
+ len = fold (size_binop (PLUS_EXPR, len, ssize_int (1)));
- emit_insn (insn);
+ /* The actual new length parameter is MIN(len,arg3). */
+ len = fold (build (MIN_EXPR, TREE_TYPE (len), len, arg3));
- /* Return the value in the proper mode for this function. */
- mode = TYPE_MODE (TREE_TYPE (exp));
- if (GET_MODE (result) == mode)
- return result;
- if (target == 0)
- return convert_to_mode (mode, result, 0);
- convert_move (target, result, 0);
- return target;
- }
-#endif
- return 0;
+ newarglist = build_tree_list (NULL_TREE, len);
+ newarglist = tree_cons (NULL_TREE, arg2, newarglist);
+ newarglist = tree_cons (NULL_TREE, arg1, newarglist);
+ return expand_expr (build_function_call_expr (fn, newarglist),
+ target, mode, EXPAND_NORMAL);
}
/* Expand expression EXP, which is a call to the strcat builtin.
OpenPOWER on IntegriCloud