Commit 523a59ff by Qing Zhao Committed by Qing Zhao

Give up the inlining expansion for strcmp/strncmp/memcmp on a target where the...


Give up the inlining expansion for strcmp/strncmp/memcmp on a target 
where the type of the call has same or narrower presicion than unsigned
char.
Change char to unsigned char for strcmp/strncmp when expand them to
a sequence of byte comparisons.
 
Due to C standard section 7.24.4:

The sign of a nonzero value returned by the comparison functions memcmp,
strcmp, and strncmp is determined by the sign of the difference between 
the values of the first pair of characters (both interpreted as unsigned 
char) that differ in the objects being compared.

bootstraped and tested on both X86 and Aarch64. no regression.

From-SVN: r262907
parent cba563f7
2018-07-20 Qing Zhao <qing.zhao@oracle.com>
* builtins.c (expand_builtin_memcmp): Delete the last parameter for
call to inline_expand_builtin_string_cmp.
(expand_builtin_strcmp): Likewise.
(expand_builtin_strncmp): Likewise.
(inline_string_cmp): Delete the last parameter, change char_type_node
to unsigned_char_type_node for strcmp/strncmp, add conversions to the
two operands.
(inline_expand_builtin_string_cmp): Delete the last parameter, give up
the inlining expansion on target where the type of the call has same or
narrower precision than unsigned char.
2018-07-20 David Malcolm <dmalcolm@redhat.com> 2018-07-20 David Malcolm <dmalcolm@redhat.com>
* Makefile.in (OBJS): Add json.o and optinfo-emit-json.o. * Makefile.in (OBJS): Add json.o and optinfo-emit-json.o.
......
...@@ -119,7 +119,7 @@ static rtx expand_builtin_next_arg (void); ...@@ -119,7 +119,7 @@ static rtx expand_builtin_next_arg (void);
static rtx expand_builtin_va_start (tree); static rtx expand_builtin_va_start (tree);
static rtx expand_builtin_va_end (tree); static rtx expand_builtin_va_end (tree);
static rtx expand_builtin_va_copy (tree); static rtx expand_builtin_va_copy (tree);
static rtx inline_expand_builtin_string_cmp (tree, rtx, bool); static rtx inline_expand_builtin_string_cmp (tree, rtx);
static rtx expand_builtin_strcmp (tree, rtx); static rtx expand_builtin_strcmp (tree, rtx);
static rtx expand_builtin_strncmp (tree, rtx, machine_mode); static rtx expand_builtin_strncmp (tree, rtx, machine_mode);
static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, scalar_int_mode); static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, scalar_int_mode);
...@@ -4472,7 +4472,7 @@ expand_builtin_memcmp (tree exp, rtx target, bool result_eq) ...@@ -4472,7 +4472,7 @@ expand_builtin_memcmp (tree exp, rtx target, bool result_eq)
if (!result_eq && fcode != BUILT_IN_BCMP && no_overflow) if (!result_eq && fcode != BUILT_IN_BCMP && no_overflow)
{ {
result = inline_expand_builtin_string_cmp (exp, target, true); result = inline_expand_builtin_string_cmp (exp, target);
if (result) if (result)
return result; return result;
} }
...@@ -4551,7 +4551,7 @@ expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target) ...@@ -4551,7 +4551,7 @@ expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target)
/* Due to the performance benefit, always inline the calls first. */ /* Due to the performance benefit, always inline the calls first. */
rtx result = NULL_RTX; rtx result = NULL_RTX;
result = inline_expand_builtin_string_cmp (exp, target, false); result = inline_expand_builtin_string_cmp (exp, target);
if (result) if (result)
return result; return result;
...@@ -4670,7 +4670,7 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target, ...@@ -4670,7 +4670,7 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
/* Due to the performance benefit, always inline the calls first. */ /* Due to the performance benefit, always inline the calls first. */
rtx result = NULL_RTX; rtx result = NULL_RTX;
result = inline_expand_builtin_string_cmp (exp, target, false); result = inline_expand_builtin_string_cmp (exp, target);
if (result) if (result)
return result; return result;
...@@ -6764,22 +6764,24 @@ expand_builtin_goacc_parlevel_id_size (tree exp, rtx target, int ignore) ...@@ -6764,22 +6764,24 @@ expand_builtin_goacc_parlevel_id_size (tree exp, rtx target, int ignore)
to: (assume const_str_n is 2, i.e., arg2 is a constant string) to: (assume const_str_n is 2, i.e., arg2 is a constant string)
target = var_str[0] - const_str[0]; target = (int) (unsigned char) var_str[0]
- (int) (unsigned char) const_str[0];
if (target != 0) if (target != 0)
goto ne_label; goto ne_label;
... ...
target = var_str[length - 2] - const_str[length - 2]; target = (int) (unsigned char) var_str[length - 2]
- (int) (unsigned char) const_str[length - 2];
if (target != 0) if (target != 0)
goto ne_label; goto ne_label;
target = var_str[length - 1] - const_str[length - 1]; target = (int) (unsigned char) var_str[length - 1]
- (int) (unsigned char) const_str[length - 1];
ne_label: ne_label:
*/ */
static rtx static rtx
inline_string_cmp (rtx target, tree var_str, const char *const_str, inline_string_cmp (rtx target, tree var_str, const char *const_str,
unsigned HOST_WIDE_INT length, unsigned HOST_WIDE_INT length,
int const_str_n, machine_mode mode, int const_str_n, machine_mode mode)
bool is_memcmp)
{ {
HOST_WIDE_INT offset = 0; HOST_WIDE_INT offset = 0;
rtx var_rtx_array rtx var_rtx_array
...@@ -6788,7 +6790,7 @@ inline_string_cmp (rtx target, tree var_str, const char *const_str, ...@@ -6788,7 +6790,7 @@ inline_string_cmp (rtx target, tree var_str, const char *const_str,
rtx const_rtx = NULL_RTX; rtx const_rtx = NULL_RTX;
rtx result = target ? target : gen_reg_rtx (mode); rtx result = target ? target : gen_reg_rtx (mode);
rtx_code_label *ne_label = gen_label_rtx (); rtx_code_label *ne_label = gen_label_rtx ();
tree unit_type_node = is_memcmp ? unsigned_char_type_node : char_type_node; tree unit_type_node = unsigned_char_type_node;
scalar_int_mode unit_mode scalar_int_mode unit_mode
= as_a <scalar_int_mode> TYPE_MODE (unit_type_node); = as_a <scalar_int_mode> TYPE_MODE (unit_type_node);
...@@ -6802,8 +6804,10 @@ inline_string_cmp (rtx target, tree var_str, const char *const_str, ...@@ -6802,8 +6804,10 @@ inline_string_cmp (rtx target, tree var_str, const char *const_str,
rtx op0 = (const_str_n == 1) ? const_rtx : var_rtx; rtx op0 = (const_str_n == 1) ? const_rtx : var_rtx;
rtx op1 = (const_str_n == 1) ? var_rtx : const_rtx; rtx op1 = (const_str_n == 1) ? var_rtx : const_rtx;
op0 = convert_modes (mode, unit_mode, op0, 1);
op1 = convert_modes (mode, unit_mode, op1, 1);
result = expand_simple_binop (mode, MINUS, op0, op1, result = expand_simple_binop (mode, MINUS, op0, op1,
result, is_memcmp ? 1 : 0, OPTAB_WIDEN); result, 1, OPTAB_WIDEN);
if (i < length - 1) if (i < length - 1)
emit_cmp_and_jump_insns (result, CONST0_RTX (mode), NE, NULL_RTX, emit_cmp_and_jump_insns (result, CONST0_RTX (mode), NE, NULL_RTX,
mode, true, ne_label); mode, true, ne_label);
...@@ -6822,7 +6826,7 @@ inline_string_cmp (rtx target, tree var_str, const char *const_str, ...@@ -6822,7 +6826,7 @@ inline_string_cmp (rtx target, tree var_str, const char *const_str,
TARGET if that's convenient. TARGET if that's convenient.
If the call is not been inlined, return NULL_RTX. */ If the call is not been inlined, return NULL_RTX. */
static rtx static rtx
inline_expand_builtin_string_cmp (tree exp, rtx target, bool is_memcmp) inline_expand_builtin_string_cmp (tree exp, rtx target)
{ {
tree fndecl = get_callee_fndecl (exp); tree fndecl = get_callee_fndecl (exp);
enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
...@@ -6833,6 +6837,12 @@ inline_expand_builtin_string_cmp (tree exp, rtx target, bool is_memcmp) ...@@ -6833,6 +6837,12 @@ inline_expand_builtin_string_cmp (tree exp, rtx target, bool is_memcmp)
|| fcode == BUILT_IN_STRNCMP || fcode == BUILT_IN_STRNCMP
|| fcode == BUILT_IN_MEMCMP); || fcode == BUILT_IN_MEMCMP);
/* On a target where the type of the call (int) has same or narrower presicion
than unsigned char, give up the inlining expansion. */
if (TYPE_PRECISION (unsigned_char_type_node)
>= TYPE_PRECISION (TREE_TYPE (exp)))
return NULL_RTX;
tree arg1 = CALL_EXPR_ARG (exp, 0); tree arg1 = CALL_EXPR_ARG (exp, 0);
tree arg2 = CALL_EXPR_ARG (exp, 1); tree arg2 = CALL_EXPR_ARG (exp, 1);
tree len3_tree = is_ncmp ? CALL_EXPR_ARG (exp, 2) : NULL_TREE; tree len3_tree = is_ncmp ? CALL_EXPR_ARG (exp, 2) : NULL_TREE;
...@@ -6879,7 +6889,7 @@ inline_expand_builtin_string_cmp (tree exp, rtx target, bool is_memcmp) ...@@ -6879,7 +6889,7 @@ inline_expand_builtin_string_cmp (tree exp, rtx target, bool is_memcmp)
/* Now, start inline expansion the call. */ /* Now, start inline expansion the call. */
return inline_string_cmp (target, (const_str_n == 1) ? arg2 : arg1, return inline_string_cmp (target, (const_str_n == 1) ? arg2 : arg1,
(const_str_n == 1) ? src_str1 : src_str2, length, (const_str_n == 1) ? src_str1 : src_str2, length,
const_str_n, mode, is_memcmp); const_str_n, mode);
} }
/* Expand an expression EXP that calls a built-in function, /* Expand an expression EXP that calls a built-in function,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment