Commit 0edd264d by Aaron Sawdey Committed by Aaron Sawdey

rs6000-protos.h (expand_strn_compare): Add arg.

2017-01-18  Aaron Sawdey  <acsawdey@linux.vnet.ibm.com>
	* config/rs6000/rs6000-protos.h (expand_strn_compare): Add arg.
	* config/rs6000/rs6000.c (expand_strn_compare): Add ability to expand
	strcmp. Fix bug where comparison didn't stop with zero byte. Fix
	case where N arg is SIZE_MAX.
	* config/rs6000/rs6000.md (cmpstrnsi): Args to expand_strn_compare.
	(cmpstrsi): Add pattern.
2017-01-18  Aaron Sawdey  <acsawdey@linux.vnet.ibm.com>
	* gcc.dg/strcmp-1.c: New test.
	* gcc.dg/strncmp-1.c: Add test for a bug that escaped.

From-SVN: r244598
parent 551914b7
2017-01-18 Aaron Sawdey <acsawdey@linux.vnet.ibm.com>
* config/rs6000/rs6000-protos.h (expand_strn_compare): Add arg.
* config/rs6000/rs6000.c (expand_strn_compare): Add ability to expand
strcmp. Fix bug where comparison didn't stop with zero byte. Fix
case where N arg is SIZE_MAX.
* config/rs6000/rs6000.md (cmpstrnsi): Args to expand_strn_compare.
(cmpstrsi): Add pattern.
2017-01-18 Michael Meissner <meissner@linux.vnet.ibm.com> 2017-01-18 Michael Meissner <meissner@linux.vnet.ibm.com>
* config/rs6000/rs6000-c.c (altivec_overloaded_builtins): Add * config/rs6000/rs6000-c.c (altivec_overloaded_builtins): Add
......
...@@ -78,7 +78,7 @@ extern void rs6000_scale_v2df (rtx, rtx, int); ...@@ -78,7 +78,7 @@ extern void rs6000_scale_v2df (rtx, rtx, int);
extern int expand_block_clear (rtx[]); extern int expand_block_clear (rtx[]);
extern int expand_block_move (rtx[]); extern int expand_block_move (rtx[]);
extern bool expand_block_compare (rtx[]); extern bool expand_block_compare (rtx[]);
extern bool expand_strn_compare (rtx[]); extern bool expand_strn_compare (rtx[], int);
extern const char * rs6000_output_load_multiple (rtx[]); extern const char * rs6000_output_load_multiple (rtx[]);
extern bool rs6000_is_valid_mask (rtx, int *, int *, machine_mode); extern bool rs6000_is_valid_mask (rtx, int *, int *, machine_mode);
extern bool rs6000_is_valid_and_mask (rtx, machine_mode); extern bool rs6000_is_valid_and_mask (rtx, machine_mode);
......
...@@ -19355,8 +19355,9 @@ do_load_for_compare (rtx reg, rtx mem, machine_mode mode) ...@@ -19355,8 +19355,9 @@ do_load_for_compare (rtx reg, rtx mem, machine_mode mode)
WORD_MODE_OK indicates using WORD_MODE is allowed, else SImode is WORD_MODE_OK indicates using WORD_MODE is allowed, else SImode is
the largest allowable mode. */ the largest allowable mode. */
static machine_mode static machine_mode
select_block_compare_mode (HOST_WIDE_INT offset, HOST_WIDE_INT bytes, select_block_compare_mode (unsigned HOST_WIDE_INT offset,
HOST_WIDE_INT align, bool word_mode_ok) unsigned HOST_WIDE_INT bytes,
unsigned HOST_WIDE_INT align, bool word_mode_ok)
{ {
/* First see if we can do a whole load unit /* First see if we can do a whole load unit
as that will be more efficient than a larger load + shift. */ as that will be more efficient than a larger load + shift. */
...@@ -19367,7 +19368,7 @@ select_block_compare_mode (HOST_WIDE_INT offset, HOST_WIDE_INT bytes, ...@@ -19367,7 +19368,7 @@ select_block_compare_mode (HOST_WIDE_INT offset, HOST_WIDE_INT bytes,
Do largest chunk possible without violating alignment rules. */ Do largest chunk possible without violating alignment rules. */
/* The most we can read without potential page crossing. */ /* The most we can read without potential page crossing. */
HOST_WIDE_INT maxread = ROUND_UP (bytes, align); unsigned HOST_WIDE_INT maxread = ROUND_UP (bytes, align);
if (word_mode_ok && bytes >= UNITS_PER_WORD) if (word_mode_ok && bytes >= UNITS_PER_WORD)
return word_mode; return word_mode;
...@@ -19408,8 +19409,9 @@ select_block_compare_mode (HOST_WIDE_INT offset, HOST_WIDE_INT bytes, ...@@ -19408,8 +19409,9 @@ select_block_compare_mode (HOST_WIDE_INT offset, HOST_WIDE_INT bytes,
/* Compute the alignment of pointer+OFFSET where the original alignment /* Compute the alignment of pointer+OFFSET where the original alignment
of pointer was BASE_ALIGN. */ of pointer was BASE_ALIGN. */
static HOST_WIDE_INT static unsigned HOST_WIDE_INT
compute_current_alignment (HOST_WIDE_INT base_align, HOST_WIDE_INT offset) compute_current_alignment (unsigned HOST_WIDE_INT base_align,
unsigned HOST_WIDE_INT offset)
{ {
if (offset == 0) if (offset == 0)
return base_align; return base_align;
...@@ -19445,7 +19447,7 @@ expand_block_compare (rtx operands[]) ...@@ -19445,7 +19447,7 @@ expand_block_compare (rtx operands[])
if (!CONST_INT_P (align_rtx)) if (!CONST_INT_P (align_rtx))
return false; return false;
int base_align = INTVAL (align_rtx) / BITS_PER_UNIT; unsigned int base_align = UINTVAL (align_rtx) / BITS_PER_UNIT;
/* SLOW_UNALIGNED_ACCESS -- don't do unaligned stuff */ /* SLOW_UNALIGNED_ACCESS -- don't do unaligned stuff */
if (SLOW_UNALIGNED_ACCESS (word_mode, MEM_ALIGN (orig_src1)) if (SLOW_UNALIGNED_ACCESS (word_mode, MEM_ALIGN (orig_src1))
...@@ -19455,8 +19457,8 @@ expand_block_compare (rtx operands[]) ...@@ -19455,8 +19457,8 @@ expand_block_compare (rtx operands[])
gcc_assert (GET_MODE (target) == SImode); gcc_assert (GET_MODE (target) == SImode);
/* Anything to move? */ /* Anything to move? */
HOST_WIDE_INT bytes = INTVAL (bytes_rtx); unsigned HOST_WIDE_INT bytes = UINTVAL (bytes_rtx);
if (bytes <= 0) if (bytes == 0)
return true; return true;
/* The code generated for p7 and older is not faster than glibc /* The code generated for p7 and older is not faster than glibc
...@@ -19477,14 +19479,14 @@ expand_block_compare (rtx operands[]) ...@@ -19477,14 +19479,14 @@ expand_block_compare (rtx operands[])
/* Strategy phase. How many ops will this take and should we expand it? */ /* Strategy phase. How many ops will this take and should we expand it? */
int offset = 0; unsigned HOST_WIDE_INT offset = 0;
machine_mode load_mode = machine_mode load_mode =
select_block_compare_mode (offset, bytes, base_align, word_mode_ok); select_block_compare_mode (offset, bytes, base_align, word_mode_ok);
int load_mode_size = GET_MODE_SIZE (load_mode); unsigned int load_mode_size = GET_MODE_SIZE (load_mode);
/* We don't want to generate too much code. */ /* We don't want to generate too much code. */
if (ROUND_UP (bytes, load_mode_size) / load_mode_size if (ROUND_UP (bytes, load_mode_size) / load_mode_size
> rs6000_block_compare_inline_limit) > (unsigned HOST_WIDE_INT) rs6000_block_compare_inline_limit)
return false; return false;
bool generate_6432_conversion = false; bool generate_6432_conversion = false;
...@@ -19515,7 +19517,7 @@ expand_block_compare (rtx operands[]) ...@@ -19515,7 +19517,7 @@ expand_block_compare (rtx operands[])
while (bytes > 0) while (bytes > 0)
{ {
int align = compute_current_alignment (base_align, offset); unsigned int align = compute_current_alignment (base_align, offset);
if (TARGET_EFFICIENT_OVERLAPPING_UNALIGNED) if (TARGET_EFFICIENT_OVERLAPPING_UNALIGNED)
load_mode = select_block_compare_mode (offset, bytes, align, load_mode = select_block_compare_mode (offset, bytes, align,
word_mode_ok); word_mode_ok);
...@@ -19528,7 +19530,7 @@ expand_block_compare (rtx operands[]) ...@@ -19528,7 +19530,7 @@ expand_block_compare (rtx operands[])
{ {
/* Move this load back so it doesn't go past the end. /* Move this load back so it doesn't go past the end.
P8/P9 can do this efficiently. */ P8/P9 can do this efficiently. */
int extra_bytes = load_mode_size - bytes; unsigned int extra_bytes = load_mode_size - bytes;
cmp_bytes = bytes; cmp_bytes = bytes;
if (extra_bytes < offset) if (extra_bytes < offset)
{ {
...@@ -19727,29 +19729,43 @@ expand_strncmp_align_check (rtx strncmp_label, rtx src, HOST_WIDE_INT bytes) ...@@ -19727,29 +19729,43 @@ expand_strncmp_align_check (rtx strncmp_label, rtx src, HOST_WIDE_INT bytes)
OPERANDS[0] is the target (result). OPERANDS[0] is the target (result).
OPERANDS[1] is the first source. OPERANDS[1] is the first source.
OPERANDS[2] is the second source. OPERANDS[2] is the second source.
If NO_LENGTH is zero, then:
OPERANDS[3] is the length. OPERANDS[3] is the length.
OPERANDS[4] is the alignment in bytes. */ OPERANDS[4] is the alignment in bytes.
If NO_LENGTH is nonzero, then:
OPERANDS[3] is the alignment in bytes. */
bool bool
expand_strn_compare (rtx operands[]) expand_strn_compare (rtx operands[], int no_length)
{ {
rtx target = operands[0]; rtx target = operands[0];
rtx orig_src1 = operands[1]; rtx orig_src1 = operands[1];
rtx orig_src2 = operands[2]; rtx orig_src2 = operands[2];
rtx bytes_rtx = operands[3]; rtx bytes_rtx, align_rtx;
rtx align_rtx = operands[4]; if (no_length)
HOST_WIDE_INT cmp_bytes = 0; {
bytes_rtx = NULL;
align_rtx = operands[3];
}
else
{
bytes_rtx = operands[3];
align_rtx = operands[4];
}
unsigned HOST_WIDE_INT cmp_bytes = 0;
rtx src1 = orig_src1; rtx src1 = orig_src1;
rtx src2 = orig_src2; rtx src2 = orig_src2;
/* If this is not a fixed size compare, just call strncmp. */ /* If we have a length, it must be constant. This simplifies things
if (!CONST_INT_P (bytes_rtx)) a bit as we don't have to generate code to check if we've exceeded
the length. Later this could be expanded to handle this case. */
if (!no_length && !CONST_INT_P (bytes_rtx))
return false; return false;
/* This must be a fixed size alignment. */ /* This must be a fixed size alignment. */
if (!CONST_INT_P (align_rtx)) if (!CONST_INT_P (align_rtx))
return false; return false;
int base_align = INTVAL (align_rtx); unsigned int base_align = UINTVAL (align_rtx);
int align1 = MEM_ALIGN (orig_src1) / BITS_PER_UNIT; int align1 = MEM_ALIGN (orig_src1) / BITS_PER_UNIT;
int align2 = MEM_ALIGN (orig_src2) / BITS_PER_UNIT; int align2 = MEM_ALIGN (orig_src2) / BITS_PER_UNIT;
...@@ -19760,25 +19776,44 @@ expand_strn_compare (rtx operands[]) ...@@ -19760,25 +19776,44 @@ expand_strn_compare (rtx operands[])
gcc_assert (GET_MODE (target) == SImode); gcc_assert (GET_MODE (target) == SImode);
HOST_WIDE_INT bytes = INTVAL (bytes_rtx);
/* If we have an LE target without ldbrx and word_mode is DImode, /* If we have an LE target without ldbrx and word_mode is DImode,
then we must avoid using word_mode. */ then we must avoid using word_mode. */
int word_mode_ok = !(!BYTES_BIG_ENDIAN && !TARGET_LDBRX int word_mode_ok = !(!BYTES_BIG_ENDIAN && !TARGET_LDBRX
&& word_mode == DImode); && word_mode == DImode);
int word_mode_size = GET_MODE_SIZE (word_mode); unsigned int word_mode_size = GET_MODE_SIZE (word_mode);
unsigned HOST_WIDE_INT offset = 0;
unsigned HOST_WIDE_INT bytes; /* N from the strncmp args if available. */
unsigned HOST_WIDE_INT compare_length; /* How much to compare inline. */
if (no_length)
/* Use this as a standin to determine the mode to use. */
bytes = rs6000_string_compare_inline_limit * word_mode_size;
else
bytes = UINTVAL (bytes_rtx);
int offset = 0;
machine_mode load_mode = machine_mode load_mode =
select_block_compare_mode (offset, bytes, base_align, word_mode_ok); select_block_compare_mode (offset, bytes, base_align, word_mode_ok);
int load_mode_size = GET_MODE_SIZE (load_mode); unsigned int load_mode_size = GET_MODE_SIZE (load_mode);
compare_length = rs6000_string_compare_inline_limit * load_mode_size;
/* We don't want to generate too much code. Also if bytes is /* If we have equality at the end of the last compare and we have not
4096 or larger we always want the library strncmp anyway. */ found the end of the string, we need to call strcmp/strncmp to
int groups = ROUND_UP (bytes, load_mode_size) / load_mode_size; compare the remainder. */
if (bytes >= 4096 || groups > rs6000_string_compare_inline_limit) bool equality_compare_rest = false;
return false;
if (no_length)
{
bytes = compare_length;
equality_compare_rest = true;
}
else
{
if (bytes <= compare_length)
compare_length = bytes;
else
equality_compare_rest = true;
}
rtx result_reg = gen_reg_rtx (word_mode); rtx result_reg = gen_reg_rtx (word_mode);
rtx final_move_label = gen_label_rtx (); rtx final_move_label = gen_label_rtx ();
...@@ -19798,9 +19833,13 @@ expand_strn_compare (rtx operands[]) ...@@ -19798,9 +19833,13 @@ expand_strn_compare (rtx operands[])
bgt cr7,L(pagecross) */ bgt cr7,L(pagecross) */
if (align1 < 8) if (align1 < 8)
expand_strncmp_align_check (strncmp_label, src1, bytes); expand_strncmp_align_check (strncmp_label, src1, compare_length);
if (align2 < 8) if (align2 < 8)
expand_strncmp_align_check (strncmp_label, src2, bytes); expand_strncmp_align_check (strncmp_label, src2, compare_length);
/* After the runtime alignment checks, we can use any alignment we
like as we know there is no 4k boundary crossing. */
base_align = 8;
/* Now generate the following sequence: /* Now generate the following sequence:
- branch to begin_compare - branch to begin_compare
...@@ -19811,7 +19850,7 @@ expand_strn_compare (rtx operands[]) ...@@ -19811,7 +19850,7 @@ expand_strn_compare (rtx operands[])
rtx cmp_ref = gen_rtx_LABEL_REF (VOIDmode, begin_compare_label); rtx cmp_ref = gen_rtx_LABEL_REF (VOIDmode, begin_compare_label);
jmp = emit_jump_insn (gen_rtx_SET (pc_rtx, cmp_ref)); jmp = emit_jump_insn (gen_rtx_SET (pc_rtx, cmp_ref));
JUMP_LABEL(jmp) = begin_compare_label; JUMP_LABEL (jmp) = begin_compare_label;
LABEL_NUSES (begin_compare_label) += 1; LABEL_NUSES (begin_compare_label) += 1;
emit_barrier (); emit_barrier ();
...@@ -19829,14 +19868,21 @@ expand_strn_compare (rtx operands[]) ...@@ -19829,14 +19868,21 @@ expand_strn_compare (rtx operands[])
src2 = replace_equiv_address (src2, src2_reg); src2 = replace_equiv_address (src2, src2_reg);
} }
if (no_length)
emit_library_call_value (gen_rtx_SYMBOL_REF (Pmode, "strcmp"),
target, LCT_NORMAL, GET_MODE (target), 2,
force_reg (Pmode, XEXP (src1, 0)), Pmode,
force_reg (Pmode, XEXP (src2, 0)), Pmode);
else
{
/* -m32 -mpowerpc64 results in word_mode being DImode even /* -m32 -mpowerpc64 results in word_mode being DImode even
though otherwise it is 32-bit. The length arg to strncmp though otherwise it is 32-bit. The length arg to strncmp
is a size_t which will be the same size as pointers. */ is a size_t which will be the same size as pointers. */
rtx len_rtx; rtx len_rtx;
if (TARGET_64BIT) if (TARGET_64BIT)
len_rtx = gen_reg_rtx(DImode); len_rtx = gen_reg_rtx (DImode);
else else
len_rtx = gen_reg_rtx(SImode); len_rtx = gen_reg_rtx (SImode);
emit_move_insn (len_rtx, bytes_rtx); emit_move_insn (len_rtx, bytes_rtx);
...@@ -19845,6 +19891,7 @@ expand_strn_compare (rtx operands[]) ...@@ -19845,6 +19891,7 @@ expand_strn_compare (rtx operands[])
force_reg (Pmode, XEXP (src1, 0)), Pmode, force_reg (Pmode, XEXP (src1, 0)), Pmode,
force_reg (Pmode, XEXP (src2, 0)), Pmode, force_reg (Pmode, XEXP (src2, 0)), Pmode,
len_rtx, GET_MODE (len_rtx)); len_rtx, GET_MODE (len_rtx));
}
rtx fin_ref = gen_rtx_LABEL_REF (VOIDmode, final_label); rtx fin_ref = gen_rtx_LABEL_REF (VOIDmode, final_label);
jmp = emit_jump_insn (gen_rtx_SET (pc_rtx, fin_ref)); jmp = emit_jump_insn (gen_rtx_SET (pc_rtx, fin_ref));
...@@ -19860,10 +19907,12 @@ expand_strn_compare (rtx operands[]) ...@@ -19860,10 +19907,12 @@ expand_strn_compare (rtx operands[])
/* Generate sequence of ld/ldbrx, cmpb to compare out /* Generate sequence of ld/ldbrx, cmpb to compare out
to the length specified. */ to the length specified. */
while (bytes > 0) unsigned HOST_WIDE_INT bytes_to_compare = compare_length;
while (bytes_to_compare > 0)
{ {
/* Compare sequence: /* Compare sequence:
check each 8B with: ld/ld cmpd bne check each 8B with: ld/ld cmpd bne
If equal, use rldicr/cmpb to check for zero byte.
cleanup code at end: cleanup code at end:
cmpb get byte that differs cmpb get byte that differs
cmpb look for zero byte cmpb look for zero byte
...@@ -19875,33 +19924,34 @@ expand_strn_compare (rtx operands[]) ...@@ -19875,33 +19924,34 @@ expand_strn_compare (rtx operands[])
The last compare can branch around the cleanup code if the The last compare can branch around the cleanup code if the
result is zero because the strings are exactly equal. */ result is zero because the strings are exactly equal. */
int align = compute_current_alignment (base_align, offset); unsigned int align = compute_current_alignment (base_align, offset);
if (TARGET_EFFICIENT_OVERLAPPING_UNALIGNED) if (TARGET_EFFICIENT_OVERLAPPING_UNALIGNED)
load_mode = select_block_compare_mode (offset, bytes, align, load_mode = select_block_compare_mode (offset, bytes_to_compare, align,
word_mode_ok); word_mode_ok);
else else
load_mode = select_block_compare_mode (0, bytes, align, word_mode_ok); load_mode = select_block_compare_mode (0, bytes_to_compare, align,
word_mode_ok);
load_mode_size = GET_MODE_SIZE (load_mode); load_mode_size = GET_MODE_SIZE (load_mode);
if (bytes >= load_mode_size) if (bytes_to_compare >= load_mode_size)
cmp_bytes = load_mode_size; cmp_bytes = load_mode_size;
else if (TARGET_EFFICIENT_OVERLAPPING_UNALIGNED) else if (TARGET_EFFICIENT_OVERLAPPING_UNALIGNED)
{ {
/* Move this load back so it doesn't go past the end. /* Move this load back so it doesn't go past the end.
P8/P9 can do this efficiently. */ P8/P9 can do this efficiently. */
int extra_bytes = load_mode_size - bytes; unsigned int extra_bytes = load_mode_size - bytes_to_compare;
cmp_bytes = bytes; cmp_bytes = bytes_to_compare;
if (extra_bytes < offset) if (extra_bytes < offset)
{ {
offset -= extra_bytes; offset -= extra_bytes;
cmp_bytes = load_mode_size; cmp_bytes = load_mode_size;
bytes = cmp_bytes; bytes_to_compare = cmp_bytes;
} }
} }
else else
/* P7 and earlier can't do the overlapping load trick fast, /* P7 and earlier can't do the overlapping load trick fast,
so this forces a non-overlapping load and a shift to get so this forces a non-overlapping load and a shift to get
rid of the extra bytes. */ rid of the extra bytes. */
cmp_bytes = bytes; cmp_bytes = bytes_to_compare;
src1 = adjust_address (orig_src1, load_mode, offset); src1 = adjust_address (orig_src1, load_mode, offset);
src2 = adjust_address (orig_src2, load_mode, offset); src2 = adjust_address (orig_src2, load_mode, offset);
...@@ -19964,37 +20014,45 @@ expand_strn_compare (rtx operands[]) ...@@ -19964,37 +20014,45 @@ expand_strn_compare (rtx operands[])
} }
} }
int remain = bytes - cmp_bytes; /* Cases to handle. A and B are chunks of the two strings.
1: Not end of comparison:
A != B: branch to cleanup code to compute result.
A == B: check for 0 byte, next block if not found.
2: End of the inline comparison:
A != B: branch to cleanup code to compute result.
A == B: check for 0 byte, call strcmp/strncmp
3: compared requested N bytes:
A == B: branch to result 0.
A != B: cleanup code to compute result. */
unsigned HOST_WIDE_INT remain = bytes_to_compare - cmp_bytes;
rtx dst_label; rtx dst_label;
if (remain > 0) if (remain > 0 || equality_compare_rest)
{ {
/* Branch to cleanup code, otherwise fall through to do
more compares. */
if (!cleanup_label) if (!cleanup_label)
cleanup_label = gen_label_rtx (); cleanup_label = gen_label_rtx ();
dst_label = cleanup_label; dst_label = cleanup_label;
} }
else else
/* Branch to end and produce result of 0. */
dst_label = final_move_label; dst_label = final_move_label;
rtx lab_ref = gen_rtx_LABEL_REF (VOIDmode, dst_label); rtx lab_ref = gen_rtx_LABEL_REF (VOIDmode, dst_label);
rtx cond = gen_reg_rtx (CCmode); rtx cond = gen_reg_rtx (CCmode);
if (remain == 0) /* Always produce the 0 result, it is needed if
{ cmpb finds a 0 byte in this chunk. */
/* For the last chunk, subf. also
generates the zero result we need. */
rtx tmp = gen_rtx_MINUS (word_mode, tmp_reg_src1, tmp_reg_src2); rtx tmp = gen_rtx_MINUS (word_mode, tmp_reg_src1, tmp_reg_src2);
rs6000_emit_dot_insn (result_reg, tmp, 1, cond); rs6000_emit_dot_insn (result_reg, tmp, 1, cond);
}
else
emit_move_insn (cond, gen_rtx_COMPARE (CCmode,
tmp_reg_src1, tmp_reg_src2));
rtx cmp_rtx; rtx cmp_rtx;
if (remain > 0) if (remain == 0 && !equality_compare_rest)
cmp_rtx = gen_rtx_NE (VOIDmode, cond, const0_rtx);
else
cmp_rtx = gen_rtx_EQ (VOIDmode, cond, const0_rtx); cmp_rtx = gen_rtx_EQ (VOIDmode, cond, const0_rtx);
else
cmp_rtx = gen_rtx_NE (VOIDmode, cond, const0_rtx);
rtx ifelse = gen_rtx_IF_THEN_ELSE (VOIDmode, cmp_rtx, rtx ifelse = gen_rtx_IF_THEN_ELSE (VOIDmode, cmp_rtx,
lab_ref, pc_rtx); lab_ref, pc_rtx);
...@@ -20002,8 +20060,102 @@ expand_strn_compare (rtx operands[]) ...@@ -20002,8 +20060,102 @@ expand_strn_compare (rtx operands[])
JUMP_LABEL (j) = dst_label; JUMP_LABEL (j) = dst_label;
LABEL_NUSES (dst_label) += 1; LABEL_NUSES (dst_label) += 1;
if (remain > 0 || equality_compare_rest)
{
/* Generate a cmpb to test for a 0 byte and branch
to final result if found. */
rtx cmpb_zero = gen_reg_rtx (word_mode);
rtx lab_ref_fin = gen_rtx_LABEL_REF (VOIDmode, final_move_label);
rtx condz = gen_reg_rtx (CCmode);
rtx zero_reg = gen_reg_rtx (word_mode);
if (word_mode == SImode)
{
emit_insn (gen_movsi (zero_reg, GEN_INT (0)));
emit_insn (gen_cmpbsi3 (cmpb_zero, tmp_reg_src1, zero_reg));
if (cmp_bytes < word_mode_size)
{
/* Don't want to look at zero bytes past end. */
HOST_WIDE_INT mb =
BITS_PER_UNIT * (word_mode_size - cmp_bytes);
rtx mask = GEN_INT (HOST_WIDE_INT_M1U << mb);
emit_insn (gen_andsi3_mask (cmpb_zero, cmpb_zero, mask));
}
}
else
{
emit_insn (gen_movdi (zero_reg, GEN_INT (0)));
emit_insn (gen_cmpbdi3 (cmpb_zero, tmp_reg_src1, zero_reg));
if (cmp_bytes < word_mode_size)
{
/* Don't want to look at zero bytes past end. */
HOST_WIDE_INT mb =
BITS_PER_UNIT * (word_mode_size - cmp_bytes);
rtx mask = GEN_INT (HOST_WIDE_INT_M1U << mb);
emit_insn (gen_anddi3_mask (cmpb_zero, cmpb_zero, mask));
}
}
emit_move_insn (condz, gen_rtx_COMPARE (CCmode, cmpb_zero, zero_reg));
rtx cmpnz_rtx = gen_rtx_NE (VOIDmode, condz, const0_rtx);
rtx ifelse = gen_rtx_IF_THEN_ELSE (VOIDmode, cmpnz_rtx,
lab_ref_fin, pc_rtx);
rtx j2 = emit_jump_insn (gen_rtx_SET (pc_rtx, ifelse));
JUMP_LABEL (j2) = final_move_label;
LABEL_NUSES (final_move_label) += 1;
}
offset += cmp_bytes; offset += cmp_bytes;
bytes -= cmp_bytes; bytes_to_compare -= cmp_bytes;
}
if (equality_compare_rest)
{
/* Update pointers past what has been compared already. */
src1 = adjust_address (orig_src1, load_mode, offset);
src2 = adjust_address (orig_src2, load_mode, offset);
if (!REG_P (XEXP (src1, 0)))
{
rtx src1_reg = copy_addr_to_reg (XEXP (src1, 0));
src1 = replace_equiv_address (src1, src1_reg);
}
set_mem_size (src1, cmp_bytes);
if (!REG_P (XEXP (src2, 0)))
{
rtx src2_reg = copy_addr_to_reg (XEXP (src2, 0));
src2 = replace_equiv_address (src2, src2_reg);
}
set_mem_size (src2, cmp_bytes);
/* Construct call to strcmp/strncmp to compare the rest of the string. */
if (no_length)
emit_library_call_value (gen_rtx_SYMBOL_REF (Pmode, "strcmp"),
target, LCT_NORMAL, GET_MODE (target), 2,
force_reg (Pmode, XEXP (src1, 0)), Pmode,
force_reg (Pmode, XEXP (src2, 0)), Pmode);
else
{
rtx len_rtx;
if (TARGET_64BIT)
len_rtx = gen_reg_rtx (DImode);
else
len_rtx = gen_reg_rtx (SImode);
emit_move_insn (len_rtx, GEN_INT (bytes - compare_length));
emit_library_call_value (gen_rtx_SYMBOL_REF (Pmode, "strncmp"),
target, LCT_NORMAL, GET_MODE (target), 3,
force_reg (Pmode, XEXP (src1, 0)), Pmode,
force_reg (Pmode, XEXP (src2, 0)), Pmode,
len_rtx, GET_MODE (len_rtx));
}
rtx fin_ref = gen_rtx_LABEL_REF (VOIDmode, final_label);
rtx jmp = emit_jump_insn (gen_rtx_SET (pc_rtx, fin_ref));
JUMP_LABEL (jmp) = final_label;
LABEL_NUSES (final_label) += 1;
emit_barrier ();
} }
if (cleanup_label) if (cleanup_label)
...@@ -20027,15 +20179,15 @@ expand_strn_compare (rtx operands[]) ...@@ -20027,15 +20179,15 @@ expand_strn_compare (rtx operands[])
rtx rot_amt = gen_reg_rtx (word_mode); rtx rot_amt = gen_reg_rtx (word_mode);
rtx zero_reg = gen_reg_rtx (word_mode); rtx zero_reg = gen_reg_rtx (word_mode);
rtx rot1_1 = gen_reg_rtx(word_mode); rtx rot1_1 = gen_reg_rtx (word_mode);
rtx rot1_2 = gen_reg_rtx(word_mode); rtx rot1_2 = gen_reg_rtx (word_mode);
rtx rot2_1 = gen_reg_rtx(word_mode); rtx rot2_1 = gen_reg_rtx (word_mode);
rtx rot2_2 = gen_reg_rtx(word_mode); rtx rot2_2 = gen_reg_rtx (word_mode);
if (word_mode == SImode) if (word_mode == SImode)
{ {
emit_insn (gen_cmpbsi3 (cmpb_diff, tmp_reg_src1, tmp_reg_src2)); emit_insn (gen_cmpbsi3 (cmpb_diff, tmp_reg_src1, tmp_reg_src2));
emit_insn (gen_movsi (zero_reg, GEN_INT(0))); emit_insn (gen_movsi (zero_reg, GEN_INT (0)));
emit_insn (gen_cmpbsi3 (cmpb_zero, tmp_reg_src1, zero_reg)); emit_insn (gen_cmpbsi3 (cmpb_zero, tmp_reg_src1, zero_reg));
emit_insn (gen_one_cmplsi2 (cmpb_diff,cmpb_diff)); emit_insn (gen_one_cmplsi2 (cmpb_diff,cmpb_diff));
emit_insn (gen_iorsi3 (cmpb_diff, cmpb_diff, cmpb_zero)); emit_insn (gen_iorsi3 (cmpb_diff, cmpb_diff, cmpb_zero));
...@@ -20043,16 +20195,16 @@ expand_strn_compare (rtx operands[]) ...@@ -20043,16 +20195,16 @@ expand_strn_compare (rtx operands[])
emit_insn (gen_addsi3 (rot_amt, rot_amt, GEN_INT (8))); emit_insn (gen_addsi3 (rot_amt, rot_amt, GEN_INT (8)));
emit_insn (gen_rotlsi3 (rot1_1, tmp_reg_src1, emit_insn (gen_rotlsi3 (rot1_1, tmp_reg_src1,
gen_lowpart (SImode, rot_amt))); gen_lowpart (SImode, rot_amt)));
emit_insn (gen_andsi3_mask (rot1_2, rot1_1, GEN_INT(0xff))); emit_insn (gen_andsi3_mask (rot1_2, rot1_1, GEN_INT (0xff)));
emit_insn (gen_rotlsi3 (rot2_1, tmp_reg_src2, emit_insn (gen_rotlsi3 (rot2_1, tmp_reg_src2,
gen_lowpart (SImode, rot_amt))); gen_lowpart (SImode, rot_amt)));
emit_insn (gen_andsi3_mask (rot2_2, rot2_1, GEN_INT(0xff))); emit_insn (gen_andsi3_mask (rot2_2, rot2_1, GEN_INT (0xff)));
emit_insn (gen_subsi3 (result_reg, rot1_2, rot2_2)); emit_insn (gen_subsi3 (result_reg, rot1_2, rot2_2));
} }
else else
{ {
emit_insn (gen_cmpbdi3 (cmpb_diff, tmp_reg_src1, tmp_reg_src2)); emit_insn (gen_cmpbdi3 (cmpb_diff, tmp_reg_src1, tmp_reg_src2));
emit_insn (gen_movdi (zero_reg, GEN_INT(0))); emit_insn (gen_movdi (zero_reg, GEN_INT (0)));
emit_insn (gen_cmpbdi3 (cmpb_zero, tmp_reg_src1, zero_reg)); emit_insn (gen_cmpbdi3 (cmpb_zero, tmp_reg_src1, zero_reg));
emit_insn (gen_one_cmpldi2 (cmpb_diff,cmpb_diff)); emit_insn (gen_one_cmpldi2 (cmpb_diff,cmpb_diff));
emit_insn (gen_iordi3 (cmpb_diff, cmpb_diff, cmpb_zero)); emit_insn (gen_iordi3 (cmpb_diff, cmpb_diff, cmpb_zero));
...@@ -20060,10 +20212,10 @@ expand_strn_compare (rtx operands[]) ...@@ -20060,10 +20212,10 @@ expand_strn_compare (rtx operands[])
emit_insn (gen_adddi3 (rot_amt, rot_amt, GEN_INT (8))); emit_insn (gen_adddi3 (rot_amt, rot_amt, GEN_INT (8)));
emit_insn (gen_rotldi3 (rot1_1, tmp_reg_src1, emit_insn (gen_rotldi3 (rot1_1, tmp_reg_src1,
gen_lowpart (SImode, rot_amt))); gen_lowpart (SImode, rot_amt)));
emit_insn (gen_anddi3_mask (rot1_2, rot1_1, GEN_INT(0xff))); emit_insn (gen_anddi3_mask (rot1_2, rot1_1, GEN_INT (0xff)));
emit_insn (gen_rotldi3 (rot2_1, tmp_reg_src2, emit_insn (gen_rotldi3 (rot2_1, tmp_reg_src2,
gen_lowpart (SImode, rot_amt))); gen_lowpart (SImode, rot_amt)));
emit_insn (gen_anddi3_mask (rot2_2, rot2_1, GEN_INT(0xff))); emit_insn (gen_anddi3_mask (rot2_2, rot2_1, GEN_INT (0xff)));
emit_insn (gen_subdi3 (result_reg, rot1_2, rot2_2)); emit_insn (gen_subdi3 (result_reg, rot1_2, rot2_2));
} }
...@@ -9102,7 +9102,26 @@ ...@@ -9102,7 +9102,26 @@
(use (match_operand:SI 4))])] (use (match_operand:SI 4))])]
"TARGET_CMPB && (BYTES_BIG_ENDIAN || TARGET_LDBRX)" "TARGET_CMPB && (BYTES_BIG_ENDIAN || TARGET_LDBRX)"
{ {
if (expand_strn_compare (operands)) if (expand_strn_compare (operands, 0))
DONE;
else
FAIL;
})
;; String compare insn.
;; Argument 0 is the target (result)
;; Argument 1 is the destination
;; Argument 2 is the source
;; Argument 3 is the alignment
(define_expand "cmpstrsi"
[(parallel [(set (match_operand:SI 0)
(compare:SI (match_operand:BLK 1)
(match_operand:BLK 2)))
(use (match_operand:SI 3))])]
"TARGET_CMPB && (BYTES_BIG_ENDIAN || TARGET_LDBRX)"
{
if (expand_strn_compare (operands, 1))
DONE; DONE;
else else
FAIL; FAIL;
......
2017-01-18 Aaron Sawdey <acsawdey@linux.vnet.ibm.com>
* gcc.dg/strcmp-1.c: New test.
* gcc.dg/strncmp-1.c: Add test for a bug that escaped.
2017-01-18 David Malcolm <dmalcolm@redhat.com> 2017-01-18 David Malcolm <dmalcolm@redhat.com>
* jit.dg/test-threads.c (dejagnu_pass): Remove decl. * jit.dg/test-threads.c (dejagnu_pass): Remove decl.
......
/* Test strcmp builtin expansion for compilation and proper execution. */
/* { dg-do run } */
/* { dg-options "-O2" } */
/* { dg-require-effective-target ptr32plus } */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define RUN_TEST(SZ, ALIGN) test_strcmp_ ## SZ ## _ ## ALIGN ()
#define DEF_TEST(SZ, ALIGN) \
static void test_strcmp_ ## SZ ## _ ## ALIGN (void) { \
char one[3 * (SZ > 10 ? SZ : 10)]; \
char two[3 * (SZ > 10 ? SZ : 10)]; \
char three[8192] __attribute__ ((aligned (4096))); \
char four[8192] __attribute__ ((aligned (4096))); \
int i,j; \
memset(one,0,sizeof(one)); \
memset(two,0,sizeof(two)); \
memset(three,0,sizeof(three)); \
memset(four,0,sizeof(four)); \
for (i = 0 ; i < SZ ; i++) \
{ \
int r1; \
char *a = one + (i & 1) * ALIGN; \
char *b = two + (i & 1) * ALIGN; \
memset(a, '-', SZ); \
memset(b, '-', SZ); \
a[i] = '1'; \
b[i] = '2'; \
a[SZ] = 0; \
b[SZ] = 0; \
if (!((r1 = strcmp (b, a)) > 0)) \
abort (); \
if (!((r1 = strcmp (a, b)) < 0)) \
abort (); \
b[i] = '1'; \
if (!((r1 = strcmp (a, b)) == 0)) \
abort (); \
for(j = i; j < SZ ; j++) \
{ \
a[j] = '1'; \
b[j] = '2'; \
} \
if (!((r1 = strcmp (b, a)) > 0)) \
abort (); \
if (!((r1 = strcmp (a, b)) < 0)) \
abort (); \
for(j = 0; j < i ; j++) \
{ \
memset(a, '-', SZ); \
memset(b, '-', SZ); \
a[j] = '\0'; \
a[j+1] = '1'; \
b[j] = '\0'; \
b[j+1] = '2'; \
if ((r1 = strcmp (b, a)) != 0) \
abort (); \
} \
a = three + 4096 - (SZ / 2 + (i & 1) * ALIGN); \
b = four + 4096 - (SZ / 2 + (i & 1) * ALIGN); \
memset(a, '-', SZ); \
memset(b, '-', SZ); \
a[i] = '1'; \
b[i] = '2'; \
a[SZ] = 0; \
b[SZ] = 0; \
if (!((r1 = strcmp(b, a)) > 0)) \
abort (); \
if (!((r1 = strcmp(a, b)) < 0)) \
abort (); \
b[i] = '1'; \
if (!((r1 = strcmp(a, b)) == 0)) \
abort (); \
} \
}
#ifdef TEST_ALL
DEF_TEST(1,1)
DEF_TEST(1,2)
DEF_TEST(1,4)
DEF_TEST(1,8)
DEF_TEST(1,16)
DEF_TEST(2,1)
DEF_TEST(2,2)
DEF_TEST(2,4)
DEF_TEST(2,8)
DEF_TEST(2,16)
DEF_TEST(3,1)
DEF_TEST(3,2)
DEF_TEST(3,4)
DEF_TEST(3,8)
DEF_TEST(3,16)
DEF_TEST(4,1)
DEF_TEST(4,2)
DEF_TEST(4,4)
DEF_TEST(4,8)
DEF_TEST(4,16)
DEF_TEST(5,1)
DEF_TEST(5,2)
DEF_TEST(5,4)
DEF_TEST(5,8)
DEF_TEST(5,16)
DEF_TEST(6,1)
DEF_TEST(6,2)
DEF_TEST(6,4)
DEF_TEST(6,8)
DEF_TEST(6,16)
DEF_TEST(7,1)
DEF_TEST(7,2)
DEF_TEST(7,4)
DEF_TEST(7,8)
DEF_TEST(7,16)
DEF_TEST(8,1)
DEF_TEST(8,2)
DEF_TEST(8,4)
DEF_TEST(8,8)
DEF_TEST(8,16)
DEF_TEST(9,1)
DEF_TEST(9,2)
DEF_TEST(9,4)
DEF_TEST(9,8)
DEF_TEST(9,16)
DEF_TEST(10,1)
DEF_TEST(10,2)
DEF_TEST(10,4)
DEF_TEST(10,8)
DEF_TEST(10,16)
DEF_TEST(11,1)
DEF_TEST(11,2)
DEF_TEST(11,4)
DEF_TEST(11,8)
DEF_TEST(11,16)
DEF_TEST(12,1)
DEF_TEST(12,2)
DEF_TEST(12,4)
DEF_TEST(12,8)
DEF_TEST(12,16)
DEF_TEST(13,1)
DEF_TEST(13,2)
DEF_TEST(13,4)
DEF_TEST(13,8)
DEF_TEST(13,16)
DEF_TEST(14,1)
DEF_TEST(14,2)
DEF_TEST(14,4)
DEF_TEST(14,8)
DEF_TEST(14,16)
DEF_TEST(15,1)
DEF_TEST(15,2)
DEF_TEST(15,4)
DEF_TEST(15,8)
DEF_TEST(15,16)
DEF_TEST(16,1)
DEF_TEST(16,2)
DEF_TEST(16,4)
DEF_TEST(16,8)
DEF_TEST(16,16)
DEF_TEST(17,1)
DEF_TEST(17,2)
DEF_TEST(17,4)
DEF_TEST(17,8)
DEF_TEST(17,16)
DEF_TEST(18,1)
DEF_TEST(18,2)
DEF_TEST(18,4)
DEF_TEST(18,8)
DEF_TEST(18,16)
DEF_TEST(19,1)
DEF_TEST(19,2)
DEF_TEST(19,4)
DEF_TEST(19,8)
DEF_TEST(19,16)
DEF_TEST(20,1)
DEF_TEST(20,2)
DEF_TEST(20,4)
DEF_TEST(20,8)
DEF_TEST(20,16)
DEF_TEST(21,1)
DEF_TEST(21,2)
DEF_TEST(21,4)
DEF_TEST(21,8)
DEF_TEST(21,16)
DEF_TEST(22,1)
DEF_TEST(22,2)
DEF_TEST(22,4)
DEF_TEST(22,8)
DEF_TEST(22,16)
DEF_TEST(23,1)
DEF_TEST(23,2)
DEF_TEST(23,4)
DEF_TEST(23,8)
DEF_TEST(23,16)
DEF_TEST(24,1)
DEF_TEST(24,2)
DEF_TEST(24,4)
DEF_TEST(24,8)
DEF_TEST(24,16)
DEF_TEST(25,1)
DEF_TEST(25,2)
DEF_TEST(25,4)
DEF_TEST(25,8)
DEF_TEST(25,16)
DEF_TEST(26,1)
DEF_TEST(26,2)
DEF_TEST(26,4)
DEF_TEST(26,8)
DEF_TEST(26,16)
DEF_TEST(27,1)
DEF_TEST(27,2)
DEF_TEST(27,4)
DEF_TEST(27,8)
DEF_TEST(27,16)
DEF_TEST(28,1)
DEF_TEST(28,2)
DEF_TEST(28,4)
DEF_TEST(28,8)
DEF_TEST(28,16)
DEF_TEST(29,1)
DEF_TEST(29,2)
DEF_TEST(29,4)
DEF_TEST(29,8)
DEF_TEST(29,16)
DEF_TEST(30,1)
DEF_TEST(30,2)
DEF_TEST(30,4)
DEF_TEST(30,8)
DEF_TEST(30,16)
DEF_TEST(31,1)
DEF_TEST(31,2)
DEF_TEST(31,4)
DEF_TEST(31,8)
DEF_TEST(31,16)
DEF_TEST(32,1)
DEF_TEST(32,2)
DEF_TEST(32,4)
DEF_TEST(32,8)
DEF_TEST(32,16)
DEF_TEST(33,1)
DEF_TEST(33,2)
DEF_TEST(33,4)
DEF_TEST(33,8)
DEF_TEST(33,16)
DEF_TEST(34,1)
DEF_TEST(34,2)
DEF_TEST(34,4)
DEF_TEST(34,8)
DEF_TEST(34,16)
DEF_TEST(35,1)
DEF_TEST(35,2)
DEF_TEST(35,4)
DEF_TEST(35,8)
DEF_TEST(35,16)
DEF_TEST(36,1)
DEF_TEST(36,2)
DEF_TEST(36,4)
DEF_TEST(36,8)
DEF_TEST(36,16)
DEF_TEST(37,1)
DEF_TEST(37,2)
DEF_TEST(37,4)
DEF_TEST(37,8)
DEF_TEST(37,16)
DEF_TEST(38,1)
DEF_TEST(38,2)
DEF_TEST(38,4)
DEF_TEST(38,8)
DEF_TEST(38,16)
DEF_TEST(39,1)
DEF_TEST(39,2)
DEF_TEST(39,4)
DEF_TEST(39,8)
DEF_TEST(39,16)
DEF_TEST(40,1)
DEF_TEST(40,2)
DEF_TEST(40,4)
DEF_TEST(40,8)
DEF_TEST(40,16)
DEF_TEST(41,1)
DEF_TEST(41,2)
DEF_TEST(41,4)
DEF_TEST(41,8)
DEF_TEST(41,16)
DEF_TEST(42,1)
DEF_TEST(42,2)
DEF_TEST(42,4)
DEF_TEST(42,8)
DEF_TEST(42,16)
DEF_TEST(43,1)
DEF_TEST(43,2)
DEF_TEST(43,4)
DEF_TEST(43,8)
DEF_TEST(43,16)
DEF_TEST(44,1)
DEF_TEST(44,2)
DEF_TEST(44,4)
DEF_TEST(44,8)
DEF_TEST(44,16)
DEF_TEST(45,1)
DEF_TEST(45,2)
DEF_TEST(45,4)
DEF_TEST(45,8)
DEF_TEST(45,16)
DEF_TEST(46,1)
DEF_TEST(46,2)
DEF_TEST(46,4)
DEF_TEST(46,8)
DEF_TEST(46,16)
DEF_TEST(47,1)
DEF_TEST(47,2)
DEF_TEST(47,4)
DEF_TEST(47,8)
DEF_TEST(47,16)
DEF_TEST(48,1)
DEF_TEST(48,2)
DEF_TEST(48,4)
DEF_TEST(48,8)
DEF_TEST(48,16)
DEF_TEST(49,1)
DEF_TEST(49,2)
DEF_TEST(49,4)
DEF_TEST(49,8)
DEF_TEST(49,16)
DEF_TEST(100,1)
DEF_TEST(100,2)
DEF_TEST(100,4)
DEF_TEST(100,8)
DEF_TEST(100,16)
#else
DEF_TEST(3,1)
DEF_TEST(4,1)
DEF_TEST(4,2)
DEF_TEST(4,4)
DEF_TEST(5,1)
DEF_TEST(6,1)
DEF_TEST(7,1)
DEF_TEST(8,1)
DEF_TEST(8,2)
DEF_TEST(8,4)
DEF_TEST(8,8)
DEF_TEST(9,1)
DEF_TEST(16,1)
DEF_TEST(16,2)
DEF_TEST(16,4)
DEF_TEST(16,8)
DEF_TEST(16,16)
DEF_TEST(32,1)
DEF_TEST(32,2)
DEF_TEST(32,4)
DEF_TEST(32,8)
DEF_TEST(32,16)
DEF_TEST(100,1)
DEF_TEST(100,2)
DEF_TEST(100,4)
DEF_TEST(100,8)
DEF_TEST(100,16)
#endif
int
main(int argc, char **argv)
{
#ifdef TEST_ALL
RUN_TEST(1,1);
RUN_TEST(1,2);
RUN_TEST(1,4);
RUN_TEST(1,8);
RUN_TEST(1,16);
RUN_TEST(2,1);
RUN_TEST(2,2);
RUN_TEST(2,4);
RUN_TEST(2,8);
RUN_TEST(2,16);
RUN_TEST(3,1);
RUN_TEST(3,2);
RUN_TEST(3,4);
RUN_TEST(3,8);
RUN_TEST(3,16);
RUN_TEST(4,1);
RUN_TEST(4,2);
RUN_TEST(4,4);
RUN_TEST(4,8);
RUN_TEST(4,16);
RUN_TEST(5,1);
RUN_TEST(5,2);
RUN_TEST(5,4);
RUN_TEST(5,8);
RUN_TEST(5,16);
RUN_TEST(6,1);
RUN_TEST(6,2);
RUN_TEST(6,4);
RUN_TEST(6,8);
RUN_TEST(6,16);
RUN_TEST(7,1);
RUN_TEST(7,2);
RUN_TEST(7,4);
RUN_TEST(7,8);
RUN_TEST(7,16);
RUN_TEST(8,1);
RUN_TEST(8,2);
RUN_TEST(8,4);
RUN_TEST(8,8);
RUN_TEST(8,16);
RUN_TEST(9,1);
RUN_TEST(9,2);
RUN_TEST(9,4);
RUN_TEST(9,8);
RUN_TEST(9,16);
RUN_TEST(10,1);
RUN_TEST(10,2);
RUN_TEST(10,4);
RUN_TEST(10,8);
RUN_TEST(10,16);
RUN_TEST(11,1);
RUN_TEST(11,2);
RUN_TEST(11,4);
RUN_TEST(11,8);
RUN_TEST(11,16);
RUN_TEST(12,1);
RUN_TEST(12,2);
RUN_TEST(12,4);
RUN_TEST(12,8);
RUN_TEST(12,16);
RUN_TEST(13,1);
RUN_TEST(13,2);
RUN_TEST(13,4);
RUN_TEST(13,8);
RUN_TEST(13,16);
RUN_TEST(14,1);
RUN_TEST(14,2);
RUN_TEST(14,4);
RUN_TEST(14,8);
RUN_TEST(14,16);
RUN_TEST(15,1);
RUN_TEST(15,2);
RUN_TEST(15,4);
RUN_TEST(15,8);
RUN_TEST(15,16);
RUN_TEST(16,1);
RUN_TEST(16,2);
RUN_TEST(16,4);
RUN_TEST(16,8);
RUN_TEST(16,16);
RUN_TEST(17,1);
RUN_TEST(17,2);
RUN_TEST(17,4);
RUN_TEST(17,8);
RUN_TEST(17,16);
RUN_TEST(18,1);
RUN_TEST(18,2);
RUN_TEST(18,4);
RUN_TEST(18,8);
RUN_TEST(18,16);
RUN_TEST(19,1);
RUN_TEST(19,2);
RUN_TEST(19,4);
RUN_TEST(19,8);
RUN_TEST(19,16);
RUN_TEST(20,1);
RUN_TEST(20,2);
RUN_TEST(20,4);
RUN_TEST(20,8);
RUN_TEST(20,16);
RUN_TEST(21,1);
RUN_TEST(21,2);
RUN_TEST(21,4);
RUN_TEST(21,8);
RUN_TEST(21,16);
RUN_TEST(22,1);
RUN_TEST(22,2);
RUN_TEST(22,4);
RUN_TEST(22,8);
RUN_TEST(22,16);
RUN_TEST(23,1);
RUN_TEST(23,2);
RUN_TEST(23,4);
RUN_TEST(23,8);
RUN_TEST(23,16);
RUN_TEST(24,1);
RUN_TEST(24,2);
RUN_TEST(24,4);
RUN_TEST(24,8);
RUN_TEST(24,16);
RUN_TEST(25,1);
RUN_TEST(25,2);
RUN_TEST(25,4);
RUN_TEST(25,8);
RUN_TEST(25,16);
RUN_TEST(26,1);
RUN_TEST(26,2);
RUN_TEST(26,4);
RUN_TEST(26,8);
RUN_TEST(26,16);
RUN_TEST(27,1);
RUN_TEST(27,2);
RUN_TEST(27,4);
RUN_TEST(27,8);
RUN_TEST(27,16);
RUN_TEST(28,1);
RUN_TEST(28,2);
RUN_TEST(28,4);
RUN_TEST(28,8);
RUN_TEST(28,16);
RUN_TEST(29,1);
RUN_TEST(29,2);
RUN_TEST(29,4);
RUN_TEST(29,8);
RUN_TEST(29,16);
RUN_TEST(30,1);
RUN_TEST(30,2);
RUN_TEST(30,4);
RUN_TEST(30,8);
RUN_TEST(30,16);
RUN_TEST(31,1);
RUN_TEST(31,2);
RUN_TEST(31,4);
RUN_TEST(31,8);
RUN_TEST(31,16);
RUN_TEST(32,1);
RUN_TEST(32,2);
RUN_TEST(32,4);
RUN_TEST(32,8);
RUN_TEST(32,16);
RUN_TEST(33,1);
RUN_TEST(33,2);
RUN_TEST(33,4);
RUN_TEST(33,8);
RUN_TEST(33,16);
RUN_TEST(34,1);
RUN_TEST(34,2);
RUN_TEST(34,4);
RUN_TEST(34,8);
RUN_TEST(34,16);
RUN_TEST(35,1);
RUN_TEST(35,2);
RUN_TEST(35,4);
RUN_TEST(35,8);
RUN_TEST(35,16);
RUN_TEST(36,1);
RUN_TEST(36,2);
RUN_TEST(36,4);
RUN_TEST(36,8);
RUN_TEST(36,16);
RUN_TEST(37,1);
RUN_TEST(37,2);
RUN_TEST(37,4);
RUN_TEST(37,8);
RUN_TEST(37,16);
RUN_TEST(38,1);
RUN_TEST(38,2);
RUN_TEST(38,4);
RUN_TEST(38,8);
RUN_TEST(38,16);
RUN_TEST(39,1);
RUN_TEST(39,2);
RUN_TEST(39,4);
RUN_TEST(39,8);
RUN_TEST(39,16);
RUN_TEST(40,1);
RUN_TEST(40,2);
RUN_TEST(40,4);
RUN_TEST(40,8);
RUN_TEST(40,16);
RUN_TEST(41,1);
RUN_TEST(41,2);
RUN_TEST(41,4);
RUN_TEST(41,8);
RUN_TEST(41,16);
RUN_TEST(42,1);
RUN_TEST(42,2);
RUN_TEST(42,4);
RUN_TEST(42,8);
RUN_TEST(42,16);
RUN_TEST(43,1);
RUN_TEST(43,2);
RUN_TEST(43,4);
RUN_TEST(43,8);
RUN_TEST(43,16);
RUN_TEST(44,1);
RUN_TEST(44,2);
RUN_TEST(44,4);
RUN_TEST(44,8);
RUN_TEST(44,16);
RUN_TEST(45,1);
RUN_TEST(45,2);
RUN_TEST(45,4);
RUN_TEST(45,8);
RUN_TEST(45,16);
RUN_TEST(46,1);
RUN_TEST(46,2);
RUN_TEST(46,4);
RUN_TEST(46,8);
RUN_TEST(46,16);
RUN_TEST(47,1);
RUN_TEST(47,2);
RUN_TEST(47,4);
RUN_TEST(47,8);
RUN_TEST(47,16);
RUN_TEST(48,1);
RUN_TEST(48,2);
RUN_TEST(48,4);
RUN_TEST(48,8);
RUN_TEST(48,16);
RUN_TEST(49,1);
RUN_TEST(49,2);
RUN_TEST(49,4);
RUN_TEST(49,8);
RUN_TEST(49,16);
#else
RUN_TEST(3,1);
RUN_TEST(4,1);
RUN_TEST(4,2);
RUN_TEST(4,4);
RUN_TEST(5,1);
RUN_TEST(6,1);
RUN_TEST(7,1);
RUN_TEST(8,1);
RUN_TEST(8,2);
RUN_TEST(8,4);
RUN_TEST(8,8);
RUN_TEST(9,1);
RUN_TEST(16,1);
RUN_TEST(16,2);
RUN_TEST(16,4);
RUN_TEST(16,8);
RUN_TEST(16,16);
RUN_TEST(32,1);
RUN_TEST(32,2);
RUN_TEST(32,4);
RUN_TEST(32,8);
RUN_TEST(32,16);
#endif
return 0;
}
/* Test memcmp builtin expansion for compilation and proper execution. */ /* Test strncmp builtin expansion for compilation and proper execution. */
/* { dg-do run } */ /* { dg-do run } */
/* { dg-options "-O2" } */ /* { dg-options "-O2" } */
/* { dg-require-effective-target ptr32plus } */ /* { dg-require-effective-target ptr32plus } */
...@@ -32,29 +32,30 @@ static void test_strncmp_ ## SZ ## _ ## ALIGN (void) { \ ...@@ -32,29 +32,30 @@ static void test_strncmp_ ## SZ ## _ ## ALIGN (void) { \
a[SZ] = 0; \ a[SZ] = 0; \
b[SZ] = 0; \ b[SZ] = 0; \
if (!((r1 = strncmp (b, a, SZ)) > 0)) \ if (!((r1 = strncmp (b, a, SZ)) > 0)) \
{ \
abort (); \ abort (); \
} \
if (!((r1 = strncmp (a, b, SZ)) < 0)) \ if (!((r1 = strncmp (a, b, SZ)) < 0)) \
{ \
abort (); \ abort (); \
} \
b[i] = '1'; \ b[i] = '1'; \
if (!((r1 = strncmp (a, b, SZ)) == 0)) \ if (!((r1 = strncmp (a, b, SZ)) == 0)) \
{ \
abort (); \ abort (); \
} \
for(j = i; j < SZ ; j++) \ for(j = i; j < SZ ; j++) \
{ \ { \
a[j] = '1'; \ a[j] = '1'; \
b[j] = '2'; \ b[j] = '2'; \
} \ } \
if (!((r1 = strncmp(b, a, SZ)) > 0)) \ if (!((r1 = strncmp (b, a, SZ)) > 0)) \
{ \
abort (); \ abort (); \
} \ if (!((r1 = strncmp (a, b, SZ)) < 0)) \
if (!((r1 = strncmp(a, b, SZ)) < 0)) \ abort (); \
for(j = 0; j < i ; j++) \
{ \ { \
memset(a, '-', SZ); \
memset(b, '-', SZ); \
a[j] = '\0'; \
a[j+1] = '1'; \
b[j] = '\0'; \
b[j+1] = '2'; \
if ((r1 = strncmp (b, a, SZ)) != 0) \
abort (); \ abort (); \
} \ } \
a = three + 4096 - (SZ / 2 + (i & 1) * ALIGN); \ a = three + 4096 - (SZ / 2 + (i & 1) * ALIGN); \
...@@ -66,19 +67,13 @@ static void test_strncmp_ ## SZ ## _ ## ALIGN (void) { \ ...@@ -66,19 +67,13 @@ static void test_strncmp_ ## SZ ## _ ## ALIGN (void) { \
a[SZ] = 0; \ a[SZ] = 0; \
b[SZ] = 0; \ b[SZ] = 0; \
if (!((r1 = strncmp(b, a, SZ)) > 0)) \ if (!((r1 = strncmp(b, a, SZ)) > 0)) \
{ \
abort (); \ abort (); \
} \
if (!((r1 = strncmp(a, b, SZ)) < 0)) \ if (!((r1 = strncmp(a, b, SZ)) < 0)) \
{ \
abort (); \ abort (); \
} \
b[i] = '1'; \ b[i] = '1'; \
if (!((r1 = strncmp(a, b, SZ)) == 0)) \ if (!((r1 = strncmp(a, b, SZ)) == 0)) \
{ \
abort (); \ abort (); \
} \ } \
} \
} }
#ifdef TEST_ALL #ifdef TEST_ALL
...@@ -327,6 +322,11 @@ DEF_TEST(49,2) ...@@ -327,6 +322,11 @@ DEF_TEST(49,2)
DEF_TEST(49,4) DEF_TEST(49,4)
DEF_TEST(49,8) DEF_TEST(49,8)
DEF_TEST(49,16) DEF_TEST(49,16)
DEF_TEST(100,1)
DEF_TEST(100,2)
DEF_TEST(100,4)
DEF_TEST(100,8)
DEF_TEST(100,16)
#else #else
DEF_TEST(3,1) DEF_TEST(3,1)
DEF_TEST(4,1) DEF_TEST(4,1)
...@@ -350,6 +350,11 @@ DEF_TEST(32,2) ...@@ -350,6 +350,11 @@ DEF_TEST(32,2)
DEF_TEST(32,4) DEF_TEST(32,4)
DEF_TEST(32,8) DEF_TEST(32,8)
DEF_TEST(32,16) DEF_TEST(32,16)
DEF_TEST(100,1)
DEF_TEST(100,2)
DEF_TEST(100,4)
DEF_TEST(100,8)
DEF_TEST(100,16)
#endif #endif
int int
......
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