diff options
author | kan <kan@FreeBSD.org> | 2003-11-07 03:05:29 +0000 |
---|---|---|
committer | kan <kan@FreeBSD.org> | 2003-11-07 03:05:29 +0000 |
commit | a084c35ceb956547fd51afa69bbb1ddde34622dc (patch) | |
tree | ff877898269dfc629cdb62275a4c8db7b18b8956 /contrib/gcc/builtins.c | |
parent | 1fb226c0cab359db650569c666e4fac31032482f (diff) | |
download | FreeBSD-src-a084c35ceb956547fd51afa69bbb1ddde34622dc.zip FreeBSD-src-a084c35ceb956547fd51afa69bbb1ddde34622dc.tar.gz |
No FreeBSD-local changes in these files.
Diffstat (limited to 'contrib/gcc/builtins.c')
-rw-r--r-- | contrib/gcc/builtins.c | 241 |
1 files changed, 168 insertions, 73 deletions
diff --git a/contrib/gcc/builtins.c b/contrib/gcc/builtins.c index 4c5650a..d088274 100644 --- a/contrib/gcc/builtins.c +++ b/contrib/gcc/builtins.c @@ -1344,7 +1344,12 @@ expand_builtin_apply (function, arguments, argsize) OK_DEFER_POP; /* Return the address of the result block. */ - return copy_addr_to_reg (XEXP (result, 0)); + 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; } /* Perform an untyped return. */ @@ -2348,7 +2353,7 @@ expand_builtin_bzero (exp) return result; } -/* Expand expression EXP, which is a call to the memcmp or the strcmp builtin. +/* Expand expression EXP, which is a call to the memcmp built-in function. 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). */ @@ -2485,7 +2490,7 @@ expand_builtin_strcmp (exp, target, mode) enum machine_mode mode; { tree arglist = TREE_OPERAND (exp, 1); - tree arg1, arg2, len, len2, fn; + tree arg1, arg2; const char *p1, *p2; if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) @@ -2521,51 +2526,89 @@ expand_builtin_strcmp (exp, target, mode) return expand_expr (result, target, mode, EXPAND_NORMAL); } - len = c_strlen (arg1); - len2 = c_strlen (arg2); - - if (len) - len = size_binop (PLUS_EXPR, ssize_int (1), len); +#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 (len2) - len2 = size_binop (PLUS_EXPR, ssize_int (1), len2); + /* If both arguments have side effects, we cannot optimize. */ + if (!len || TREE_SIDE_EFFECTS (len)) + return 0; - /* 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 we don't have POINTER_TYPE, call the function. */ + if (arg1_align == 0 || arg2_align == 0) + return 0; - 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. */ + /* 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 (!len || TREE_CODE (len) != INTEGER_CST) - { - if (len2 && !TREE_SIDE_EFFECTS (len2)) - len = len2; - else if (len == 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; - } - else if (len2 && TREE_CODE (len2) == INTEGER_CST - && tree_int_cst_lt (len2, len)) - len = len2; - /* If both arguments have side effects, we cannot optimize. */ - if (TREE_SIDE_EFFECTS (len)) - return 0; - - fn = built_in_decls[BUILT_IN_MEMCMP]; - if (!fn) - return 0; + emit_insn (insn); - 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); + /* 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; } /* Expand expression EXP, which is a call to the strncmp builtin. Return 0 @@ -2579,7 +2622,6 @@ 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; @@ -2633,41 +2675,94 @@ 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 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; + 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; - fn = built_in_decls[BUILT_IN_MEMCMP]; - if (!fn) - return 0; + /* If both arguments have side effects, we cannot optimize. */ + if (!len || TREE_SIDE_EFFECTS (len)) + return 0; - /* Add one to the string length. */ - len = fold (size_binop (PLUS_EXPR, len, ssize_int (1))); + /* The actual new length parameter is MIN(len,arg3). */ + len = fold (build (MIN_EXPR, TREE_TYPE (len), len, arg3)); - /* 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; - 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); + /* 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); + + 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; + + emit_insn (insn); + + /* 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; } /* Expand expression EXP, which is a call to the strcat builtin. |