Hi all, This patch adds the plumbing for unit testing of the store merging pass. It also adds some initial tests of some of the helpers used in encode_tree_to_bitpos to manipulate byte arrays. They caught an off-by-one error bug that is fixed in patch [1/2].
Bootstrapped and tested on x86_64 and aarch64. Ok for trunk? Thanks, Kyrill 2016-11-08 Kyrylo Tkachov <kyrylo.tkac...@arm.com> * gimple-ssa-store-merging.c: Include selftest.h (verify_array_eq): New function. (verify_shift_bytes_in_array): Likewise. (verify_shift_bytes_in_array_right): Likewise. (verify_clear_bit_region): Likewise. (verify_clear_bit_region_be): Likewise. (store_merging_c_tests): Likewise. * selftest.h (store_merging_c_tests): Declare prototype. * selftest-run-tests.c (selftest::run_tests): Run store_merging_c_tests.
diff --git a/gcc/gimple-ssa-store-merging.c b/gcc/gimple-ssa-store-merging.c index 46f92ba2d2f4e85c4256be11be5c8b1d40c21499..7b59f81e26423c60f8bf1c975281d3904315b306 100644 --- a/gcc/gimple-ssa-store-merging.c +++ b/gcc/gimple-ssa-store-merging.c @@ -126,6 +126,7 @@ #include "tree-eh.h" #include "target.h" #include "gimplify-me.h" +#include "selftest.h" /* The maximum size (in bits) of the stores this pass should generate. */ #define MAX_STORE_BITSIZE (BITS_PER_WORD) @@ -1499,3 +1500,141 @@ make_pass_store_merging (gcc::context *ctxt) { return new pass_store_merging (ctxt); } + +#if CHECKING_P + +namespace selftest { + +/* Selftests for store merging helpers. */ + +/* Assert that all elements of the byte arrays X and Y, both of length N + are equal. */ + +static void +verify_array_eq (unsigned char *x, unsigned char *y, unsigned int n) +{ + for (unsigned int i = 0; i < n; i++) + { + if (x[i] != y[i]) + { + fprintf (stderr, "Arrays do not match. X:\n"); + dump_char_array (stderr, x, n); + fprintf (stderr, "Y:\n"); + dump_char_array (stderr, y, n); + } + ASSERT_EQ (x[i], y[i]); + } +} + +/* Test shift_bytes_in_array and that it carries bits across between + bytes correctly. */ + +static void +verify_shift_bytes_in_array (void) +{ + /* byte 1 | byte 0 + 00011111 | 11100000. */ + unsigned char orig[2] = { 0xe0, 0x1f }; + unsigned char in[2]; + memcpy (in, orig, sizeof orig); + + unsigned char expected[2] = { 0x80, 0x7f }; + shift_bytes_in_array (in, sizeof (in), 2); + verify_array_eq (in, expected, sizeof (in)); + + memcpy (in, orig, sizeof orig); + memcpy (expected, orig, sizeof orig); + /* Check that shifting by zero doesn't change anything. */ + shift_bytes_in_array (in, sizeof (in), 0); + verify_array_eq (in, expected, sizeof (in)); + +} + +/* Test shift_bytes_in_array_right and that it carries bits across between + bytes correctly. */ + +static void +verify_shift_bytes_in_array_right (void) +{ + /* byte 1 | byte 0 + 00011111 | 11100000. */ + unsigned char orig[2] = { 0x1f, 0xe0}; + unsigned char in[2]; + memcpy (in, orig, sizeof orig); + unsigned char expected[2] = { 0x07, 0xf8}; + shift_bytes_in_array_right (in, sizeof (in), 2); + verify_array_eq (in, expected, sizeof (in)); + + memcpy (in, orig, sizeof orig); + memcpy (expected, orig, sizeof orig); + /* Check that shifting by zero doesn't change anything. */ + shift_bytes_in_array_right (in, sizeof (in), 0); + verify_array_eq (in, expected, sizeof (in)); +} + +/* Test clear_bit_region that it clears exactly the bits asked and + nothing more. */ + +static void +verify_clear_bit_region (void) +{ + /* Start with all bits set and test clearing various patterns in them. */ + unsigned char orig[3] = { 0xff, 0xff, 0xff}; + unsigned char in[3]; + unsigned char expected[3]; + memcpy (in, orig, sizeof in); + + /* Check zeroing out all the bits. */ + clear_bit_region (in, 0, 3 * BITS_PER_UNIT); + expected[0] = expected[1] = expected[2] = 0; + verify_array_eq (in, expected, sizeof in); + + memcpy (in, orig, sizeof in); + /* Leave the first and last bits intact. */ + clear_bit_region (in, 1, 3 * BITS_PER_UNIT - 2); + expected[0] = 0x1; + expected[1] = 0; + expected[2] = 0x80; + verify_array_eq (in, expected, sizeof in); +} + +/* Test verify_clear_bit_region_be that it clears exactly the bits asked and + nothing more. */ + +static void +verify_clear_bit_region_be (void) +{ + /* Start with all bits set and test clearing various patterns in them. */ + unsigned char orig[3] = { 0xff, 0xff, 0xff}; + unsigned char in[3]; + unsigned char expected[3]; + memcpy (in, orig, sizeof in); + + /* Check zeroing out all the bits. */ + clear_bit_region_be (in, BITS_PER_UNIT - 1, 3 * BITS_PER_UNIT); + expected[0] = expected[1] = expected[2] = 0; + verify_array_eq (in, expected, sizeof in); + + memcpy (in, orig, sizeof in); + /* Leave the first and last bits intact. */ + clear_bit_region_be (in, BITS_PER_UNIT - 2, 3 * BITS_PER_UNIT - 2); + expected[0] = 0x80; + expected[1] = 0; + expected[2] = 0x1; + verify_array_eq (in, expected, sizeof in); +} + + +/* Run all of the selftests within this file. */ + +void +store_merging_c_tests (void) +{ + verify_shift_bytes_in_array (); + verify_shift_bytes_in_array_right (); + verify_clear_bit_region (); + verify_clear_bit_region_be (); +} + +} // namespace selftest +#endif /* CHECKING_P. */ diff --git a/gcc/selftest-run-tests.c b/gcc/selftest-run-tests.c index 54a9b0f6c7ebc79881f9cb33b0a4c3d97c59c405..a796e07a856076c96cf97805a8ea831dd5a21045 100644 --- a/gcc/selftest-run-tests.c +++ b/gcc/selftest-run-tests.c @@ -77,6 +77,8 @@ selftest::run_tests () /* This one relies on most of the above. */ function_tests_c_tests (); + store_merging_c_tests (); + /* Run any lang-specific selftests. */ lang_hooks.run_lang_selftests (); diff --git a/gcc/selftest.h b/gcc/selftest.h index 845eb01b12511e3667e5a83dd69e5fbcd888b808..dcce474be6e1899e46f7a9c0d1560e0b7eb60369 100644 --- a/gcc/selftest.h +++ b/gcc/selftest.h @@ -179,6 +179,7 @@ extern void selftest_c_tests (); extern void spellcheck_c_tests (); extern void spellcheck_tree_c_tests (); extern void sreal_c_tests (); +extern void store_merging_c_tests (); extern void typed_splay_tree_c_tests (); extern void tree_c_tests (); extern void tree_cfg_c_tests ();