On Thu, 9 May 2013, Jakub Jelinek wrote: > Hi! > > The bit_rotate: code in fold-const.c handles only a subset of rotates, > and e.g. with C++ FE when sizeof isn't folded early fold_binary often > even isn't called with something that could recognize the rotate pattern, > even if bit_rotate: has been extended. Furthermore, not all the rotate > patterns need to be written in a single statement. > > So, this patch adds a rotate pattern recognizer into forwprop, and handles > several different patterns, the comment above the function shows which ones. > > Bootstrapped/regtested on x86_64-linux and i686-linux. > > On the Botan KASUMI distilled testcase (PR55278 #c6 at -O3) I get 6.3% > speedup on Intel(R) Core(TM) i7-2600 CPU @ 3.40GHz and 9.9% speedup on > Quad-Core AMD Opteron(tm) Processor 8354. > > Ok for trunk?
Ok. Thanks, Richard. > 2013-05-09 Jakub Jelinek <ja...@redhat.com> > > PR tree-optimization/45216 > PR tree-optimization/57157 > * tree-ssa-forwprop.c (simplify_rotate): New function. > (ssa_forward_propagate_and_combine): Call it. > > * c-c++-common/rotate-1.c: New test. > * c-c++-common/rotate-1a.c: New test. > * c-c++-common/rotate-2.c: New test. > * c-c++-common/rotate-2a.c: New test. > * c-c++-common/rotate-3.c: New test. > * c-c++-common/rotate-3a.c: New test. > * c-c++-common/rotate-4.c: New test. > * c-c++-common/rotate-4a.c: New test. > * gcc.target/i386/rotate-1.c: Accept rolb or rorb instruction. > > --- gcc/tree-ssa-forwprop.c.jj 2013-04-22 08:06:41.000000000 +0200 > +++ gcc/tree-ssa-forwprop.c 2013-05-09 15:31:49.350000512 +0200 > @@ -2124,6 +2124,242 @@ simplify_bitwise_binary (gimple_stmt_ite > } > > > +/* Recognize rotation patterns. Return true if a transformation > + applied, otherwise return false. > + > + We are looking for X with unsigned type T with bitsize B, OP being > + +, | or ^, some type T2 wider than T and > + (X << CNT1) OP (X >> CNT2) iff CNT1 + CNT2 > == B > + ((T) ((T2) X << CNT1)) OP ((T) ((T2) X >> CNT2)) iff CNT1 + CNT2 == B > + (X << Y) OP (X >> (B - Y)) > + (X << (int) Y) OP (X >> (int) (B - Y)) > + ((T) ((T2) X << Y)) OP ((T) ((T2) X >> (B - Y))) > + ((T) ((T2) X << (int) Y)) OP ((T) ((T2) X >> (int) (B - Y))) > + (X << Y) OP (X >> ((-Y) & (B - 1))) > + (X << (int) Y) OP (X >> (int) ((-Y) & (B - 1))) > + ((T) ((T2) X << Y)) OP ((T) ((T2) X >> ((-Y) & (B - 1)))) > + ((T) ((T2) X << (int) Y)) OP ((T) ((T2) X >> (int) ((-Y) & (B - 1)))) > + > + and transform these into: > + X r<< CNT1 > + X r<< Y > + > + Note, in the patterns with T2 type, the type of OP operands > + might be even a signed type, but should have precision B. */ > + > +static bool > +simplify_rotate (gimple_stmt_iterator *gsi) > +{ > + gimple stmt = gsi_stmt (*gsi); > + tree arg[2], rtype, rotcnt = NULL_TREE; > + tree def_arg1[2], def_arg2[2]; > + enum tree_code def_code[2]; > + tree lhs; > + int i; > + bool swapped_p = false; > + gimple g; > + > + arg[0] = gimple_assign_rhs1 (stmt); > + arg[1] = gimple_assign_rhs2 (stmt); > + rtype = TREE_TYPE (arg[0]); > + > + /* Only create rotates in complete modes. Other cases are not > + expanded properly. */ > + if (!INTEGRAL_TYPE_P (rtype) > + || TYPE_PRECISION (rtype) != GET_MODE_PRECISION (TYPE_MODE (rtype))) > + return false; > + > + for (i = 0; i < 2; i++) > + defcodefor_name (arg[i], &def_code[i], &def_arg1[i], &def_arg2[i]); > + > + /* Look through narrowing conversions. */ > + if (CONVERT_EXPR_CODE_P (def_code[0]) > + && CONVERT_EXPR_CODE_P (def_code[1]) > + && INTEGRAL_TYPE_P (TREE_TYPE (def_arg1[0])) > + && INTEGRAL_TYPE_P (TREE_TYPE (def_arg1[1])) > + && TYPE_PRECISION (TREE_TYPE (def_arg1[0])) > + == TYPE_PRECISION (TREE_TYPE (def_arg1[1])) > + && TYPE_PRECISION (TREE_TYPE (def_arg1[0])) > TYPE_PRECISION (rtype) > + && has_single_use (arg[0]) > + && has_single_use (arg[1])) > + { > + for (i = 0; i < 2; i++) > + { > + arg[i] = def_arg1[i]; > + defcodefor_name (arg[i], &def_code[i], &def_arg1[i], &def_arg2[i]); > + } > + } > + > + /* One operand has to be LSHIFT_EXPR and one RSHIFT_EXPR. */ > + for (i = 0; i < 2; i++) > + if (def_code[i] != LSHIFT_EXPR && def_code[i] != RSHIFT_EXPR) > + return false; > + else if (!has_single_use (arg[i])) > + return false; > + if (def_code[0] == def_code[1]) > + return false; > + > + /* If we've looked through narrowing conversions before, look through > + widening conversions from unsigned type with the same precision > + as rtype here. */ > + if (TYPE_PRECISION (TREE_TYPE (def_arg1[0])) != TYPE_PRECISION (rtype)) > + for (i = 0; i < 2; i++) > + { > + tree tem; > + enum tree_code code; > + defcodefor_name (def_arg1[i], &code, &tem, NULL); > + if (!CONVERT_EXPR_CODE_P (code) > + || !INTEGRAL_TYPE_P (TREE_TYPE (tem)) > + || TYPE_PRECISION (TREE_TYPE (tem)) != TYPE_PRECISION (rtype)) > + return false; > + def_arg1[i] = tem; > + } > + /* Both shifts have to use the same first operand. */ > + if (TREE_CODE (def_arg1[0]) != SSA_NAME || def_arg1[0] != def_arg1[1]) > + return false; > + if (!TYPE_UNSIGNED (TREE_TYPE (def_arg1[0]))) > + return false; > + > + /* CNT1 + CNT2 == B case above. */ > + if (host_integerp (def_arg2[0], 1) > + && host_integerp (def_arg2[1], 1) > + && (unsigned HOST_WIDE_INT) tree_low_cst (def_arg2[0], 1) > + + tree_low_cst (def_arg2[1], 1) == TYPE_PRECISION (rtype)) > + rotcnt = def_arg2[0]; > + else if (TREE_CODE (def_arg2[0]) != SSA_NAME > + || TREE_CODE (def_arg2[1]) != SSA_NAME) > + return false; > + else > + { > + tree cdef_arg1[2], cdef_arg2[2], def_arg2_alt[2]; > + enum tree_code cdef_code[2]; > + /* Look through conversion of the shift count argument. > + The C/C++ FE cast any shift count argument to integer_type_node. > + The only problem might be if the shift count type maximum value > + is equal or smaller than number of bits in rtype. */ > + for (i = 0; i < 2; i++) > + { > + def_arg2_alt[i] = def_arg2[i]; > + defcodefor_name (def_arg2[i], &cdef_code[i], > + &cdef_arg1[i], &cdef_arg2[i]); > + if (CONVERT_EXPR_CODE_P (cdef_code[i]) > + && INTEGRAL_TYPE_P (TREE_TYPE (cdef_arg1[i])) > + && TYPE_PRECISION (TREE_TYPE (cdef_arg1[i])) > + > floor_log2 (TYPE_PRECISION (rtype)) > + && TYPE_PRECISION (TREE_TYPE (cdef_arg1[i])) > + == GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (cdef_arg1[i])))) > + { > + def_arg2_alt[i] = cdef_arg1[i]; > + defcodefor_name (def_arg2_alt[i], &cdef_code[i], > + &cdef_arg1[i], &cdef_arg2[i]); > + } > + } > + for (i = 0; i < 2; i++) > + /* Check for one shift count being Y and the other B - Y, > + with optional casts. */ > + if (cdef_code[i] == MINUS_EXPR > + && host_integerp (cdef_arg1[i], 0) > + && tree_low_cst (cdef_arg1[i], 0) == TYPE_PRECISION (rtype) > + && TREE_CODE (cdef_arg2[i]) == SSA_NAME) > + { > + tree tem; > + enum tree_code code; > + > + if (cdef_arg2[i] == def_arg2[1 - i] > + || cdef_arg2[i] == def_arg2_alt[1 - i]) > + { > + rotcnt = cdef_arg2[i]; > + break; > + } > + defcodefor_name (cdef_arg2[i], &code, &tem, NULL); > + if (CONVERT_EXPR_CODE_P (code) > + && INTEGRAL_TYPE_P (TREE_TYPE (tem)) > + && TYPE_PRECISION (TREE_TYPE (tem)) > + > floor_log2 (TYPE_PRECISION (rtype)) > + && TYPE_PRECISION (TREE_TYPE (tem)) > + == GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (tem))) > + && (tem == def_arg2[1 - i] > + || tem == def_arg2_alt[1 - i])) > + { > + rotcnt = tem; > + break; > + } > + } > + /* The above sequence isn't safe for Y being 0, > + because then one of the shifts triggers undefined behavior. > + This alternative is safe even for rotation count of 0. > + One shift count is Y and the other (-Y) & (B - 1). */ > + else if (cdef_code[i] == BIT_AND_EXPR > + && host_integerp (cdef_arg2[i], 0) > + && tree_low_cst (cdef_arg2[i], 0) > + == TYPE_PRECISION (rtype) - 1 > + && TREE_CODE (cdef_arg1[i]) == SSA_NAME) > + { > + tree tem; > + enum tree_code code; > + > + defcodefor_name (cdef_arg1[i], &code, &tem, NULL); > + if (CONVERT_EXPR_CODE_P (code) > + && INTEGRAL_TYPE_P (TREE_TYPE (tem)) > + && TYPE_PRECISION (TREE_TYPE (tem)) > + > floor_log2 (TYPE_PRECISION (rtype)) > + && TYPE_PRECISION (TREE_TYPE (tem)) > + == GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (tem)))) > + defcodefor_name (tem, &code, &tem, NULL); > + > + if (code == NEGATE_EXPR) > + { > + if (tem == def_arg2[1 - i] || tem == def_arg2_alt[1 - i]) > + { > + rotcnt = tem; > + break; > + } > + defcodefor_name (tem, &code, &tem, NULL); > + if (CONVERT_EXPR_CODE_P (code) > + && INTEGRAL_TYPE_P (TREE_TYPE (tem)) > + && TYPE_PRECISION (TREE_TYPE (tem)) > + > floor_log2 (TYPE_PRECISION (rtype)) > + && TYPE_PRECISION (TREE_TYPE (tem)) > + == GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (tem))) > + && (tem == def_arg2[1 - i] > + || tem == def_arg2_alt[1 - i])) > + { > + rotcnt = tem; > + break; > + } > + } > + } > + if (rotcnt == NULL_TREE) > + return false; > + swapped_p = i != 1; > + } > + > + if (!useless_type_conversion_p (TREE_TYPE (def_arg2[0]), > + TREE_TYPE (rotcnt))) > + { > + g = gimple_build_assign_with_ops (NOP_EXPR, > + make_ssa_name (TREE_TYPE (def_arg2[0]), > + NULL), > + rotcnt, NULL_TREE); > + gsi_insert_before (gsi, g, GSI_SAME_STMT); > + rotcnt = gimple_assign_lhs (g); > + } > + lhs = gimple_assign_lhs (stmt); > + if (!useless_type_conversion_p (rtype, TREE_TYPE (def_arg1[0]))) > + lhs = make_ssa_name (TREE_TYPE (def_arg1[0]), NULL); > + g = gimple_build_assign_with_ops (((def_code[0] == LSHIFT_EXPR) ^ > swapped_p) > + ? LROTATE_EXPR : RROTATE_EXPR, > + lhs, def_arg1[0], rotcnt); > + if (!useless_type_conversion_p (rtype, TREE_TYPE (def_arg1[0]))) > + { > + gsi_insert_before (gsi, g, GSI_SAME_STMT); > + g = gimple_build_assign_with_ops (NOP_EXPR, gimple_assign_lhs (stmt), > + lhs, NULL_TREE); > + } > + gsi_replace (gsi, g, false); > + return true; > +} > + > /* Perform re-associations of the plus or minus statement STMT that are > always permitted. Returns true if the CFG was changed. */ > > @@ -3114,6 +3350,11 @@ ssa_forward_propagate_and_combine (void) > cfg_changed = true; > changed = did_something != 0; > } > + else if ((code == PLUS_EXPR > + || code == BIT_IOR_EXPR > + || code == BIT_XOR_EXPR) > + && simplify_rotate (&gsi)) > + changed = true; > else if (code == BIT_AND_EXPR > || code == BIT_IOR_EXPR > || code == BIT_XOR_EXPR) > --- gcc/testsuite/c-c++-common/rotate-1.c.jj 2013-05-09 14:56:53.653727175 > +0200 > +++ gcc/testsuite/c-c++-common/rotate-1.c 2013-05-09 15:16:02.768309163 > +0200 > @@ -0,0 +1,389 @@ > +/* Check rotate pattern detection. */ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -fdump-tree-optimized" } */ > +/* { dg-final { scan-tree-dump-times "r\[<>]\[<>]" 64 "optimized" } } */ > +/* { dg-final { cleanup-tree-dump "optimized" } } */ > + > +unsigned int > +f1 (unsigned int x, unsigned int y) > +{ > + return (x << y) | (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - y)); > +} > + > +unsigned int > +f2 (unsigned int x, unsigned long int y) > +{ > + return (x << y) | (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - y)); > +} > + > +unsigned int > +f3 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << 1) | (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - 1)); > +} > + > +unsigned int > +f4 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << (__CHAR_BIT__ * __SIZEOF_INT__ - 1)) | (x >> 1); > +} > + > +unsigned short int > +f5 (unsigned short int x, unsigned int y) > +{ > + return (x << y) | (x >> (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)); > +} > + > +unsigned short int > +f6 (unsigned short int x, unsigned long int y) > +{ > + return (x << y) | (x >> (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)); > +} > + > +unsigned char > +f7 (unsigned char x, unsigned int y) > +{ > + return (x << y) | (x >> (__CHAR_BIT__ - y)); > +} > + > +unsigned char > +f8 (unsigned char x, unsigned long int y) > +{ > + return (x << y) | (x >> (__CHAR_BIT__ - y)); > +} > + > +unsigned int > +f9 (unsigned int x, unsigned int y) > +{ > + return (x << y) | (x >> (__CHAR_BIT__ * sizeof (unsigned int) - y)); > +} > + > +unsigned int > +f10 (unsigned int x, unsigned long int y) > +{ > + return (x << y) | (x >> (__CHAR_BIT__ * sizeof (unsigned int) - y)); > +} > + > +unsigned int > +f11 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << 1) | (x >> (__CHAR_BIT__ * sizeof (unsigned int) - 1)); > +} > + > +unsigned int > +f12 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << (__CHAR_BIT__ * sizeof (unsigned int) - 1)) | (x >> 1); > +} > + > +unsigned short int > +f13 (unsigned short int x, unsigned int y) > +{ > + return (x << y) | (x >> (__CHAR_BIT__ * sizeof (unsigned short) - y)); > +} > + > +unsigned short int > +f14 (unsigned short int x, unsigned long int y) > +{ > + return (x << y) | (x >> (__CHAR_BIT__ * sizeof (unsigned short) - y)); > +} > + > +unsigned char > +f15 (unsigned char x, unsigned int y) > +{ > + return (x << y) | (x >> (__CHAR_BIT__ * sizeof (unsigned char) - y)); > +} > + > +unsigned char > +f16 (unsigned char x, unsigned long int y) > +{ > + return (x << y) | (x >> (__CHAR_BIT__ * sizeof (unsigned char) - y)); > +} > + > +unsigned int > +f17 (unsigned int x, unsigned int y) > +{ > + return (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - y)) ^ (x << y); > +} > + > +unsigned int > +f18 (unsigned int x, unsigned long int y) > +{ > + return (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - y)) ^ (x << y); > +} > + > +unsigned int > +f19 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - 1)) ^ (x << 1); > +} > + > +unsigned int > +f20 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x >> 1) ^ (x << (__CHAR_BIT__ * __SIZEOF_INT__ - 1)); > +} > + > +unsigned short int > +f21 (unsigned short int x, unsigned int y) > +{ > + return (x >> (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)) ^ (x << y); > +} > + > +unsigned short int > +f22 (unsigned short int x, unsigned long int y) > +{ > + return (x >> (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)) ^ (x << y); > +} > + > +unsigned char > +f23 (unsigned char x, unsigned int y) > +{ > + return (x >> (__CHAR_BIT__ - y)) ^ (x << y); > +} > + > +unsigned char > +f24 (unsigned char x, unsigned long int y) > +{ > + return (x >> (__CHAR_BIT__ - y)) ^ (x << y); > +} > + > +unsigned int > +f25 (unsigned int x, unsigned int y) > +{ > + return (x >> (__CHAR_BIT__ * sizeof (unsigned int) - y)) ^ (x << y); > +} > + > +unsigned int > +f26 (unsigned int x, unsigned long int y) > +{ > + return (x >> (__CHAR_BIT__ * sizeof (unsigned int) - y)) ^ (x << y); > +} > + > +unsigned int > +f27 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x >> (__CHAR_BIT__ * sizeof (unsigned int) - 1)) ^ (x << 1); > +} > + > +unsigned int > +f28 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x >> 1) ^ (x << (__CHAR_BIT__ * sizeof (unsigned int) - 1)); > +} > + > +unsigned short int > +f29 (unsigned short int x, unsigned int y) > +{ > + return (x >> (__CHAR_BIT__ * sizeof (unsigned short) - y)) ^ (x << y); > +} > + > +unsigned short int > +f30 (unsigned short int x, unsigned long int y) > +{ > + return (x >> (__CHAR_BIT__ * sizeof (unsigned short) - y)) ^ (x << y); > +} > + > +unsigned char > +f31 (unsigned char x, unsigned int y) > +{ > + return (x >> (__CHAR_BIT__ * sizeof (unsigned char) - y)) ^ (x << y); > +} > + > +unsigned char > +f32 (unsigned char x, unsigned long int y) > +{ > + return (x >> (__CHAR_BIT__ * sizeof (unsigned char) - y)) ^ (x << y); > +} > + > +unsigned int > +f33 (unsigned int x, unsigned int y) > +{ > + return (x >> y) | (x << (__CHAR_BIT__ * __SIZEOF_INT__ - y)); > +} > + > +unsigned int > +f34 (unsigned int x, unsigned long int y) > +{ > + return (x >> y) | (x << (__CHAR_BIT__ * __SIZEOF_INT__ - y)); > +} > + > +unsigned int > +f35 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x >> 1) | (x << (__CHAR_BIT__ * __SIZEOF_INT__ - 1)); > +} > + > +unsigned int > +f36 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - 1)) | (x << 1); > +} > + > +unsigned short int > +f37 (unsigned short int x, unsigned int y) > +{ > + return (x >> y) | (x << (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)); > +} > + > +unsigned short int > +f38 (unsigned short int x, unsigned long int y) > +{ > + return (x >> y) | (x << (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)); > +} > + > +unsigned char > +f39 (unsigned char x, unsigned int y) > +{ > + return (x >> y) | (x << (__CHAR_BIT__ - y)); > +} > + > +unsigned char > +f40 (unsigned char x, unsigned long int y) > +{ > + return (x >> y) | (x << (__CHAR_BIT__ - y)); > +} > + > +unsigned int > +f41 (unsigned int x, unsigned int y) > +{ > + return (x >> y) | (x << (__CHAR_BIT__ * sizeof (unsigned int) - y)); > +} > + > +unsigned int > +f42 (unsigned int x, unsigned long int y) > +{ > + return (x >> y) | (x << (__CHAR_BIT__ * sizeof (unsigned int) - y)); > +} > + > +unsigned int > +f43 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x >> 1) | (x << (__CHAR_BIT__ * sizeof (unsigned int) - 1)); > +} > + > +unsigned int > +f44 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x >> (__CHAR_BIT__ * sizeof (unsigned int) - 1)) | (x << 1); > +} > + > +unsigned short int > +f45 (unsigned short int x, unsigned int y) > +{ > + return (x >> y) | (x << (__CHAR_BIT__ * sizeof (unsigned short) - y)); > +} > + > +unsigned short int > +f46 (unsigned short int x, unsigned long int y) > +{ > + return (x >> y) | (x << (__CHAR_BIT__ * sizeof (unsigned short) - y)); > +} > + > +unsigned char > +f47 (unsigned char x, unsigned int y) > +{ > + return (x >> y) | (x << (__CHAR_BIT__ * sizeof (unsigned char) - y)); > +} > + > +unsigned char > +f48 (unsigned char x, unsigned long int y) > +{ > + return (x >> y) | (x << (__CHAR_BIT__ * sizeof (unsigned char) - y)); > +} > + > +unsigned int > +f49 (unsigned int x, unsigned int y) > +{ > + return (x << (__CHAR_BIT__ * __SIZEOF_INT__ - y)) ^ (x >> y); > +} > + > +unsigned int > +f50 (unsigned int x, unsigned long int y) > +{ > + return (x << (__CHAR_BIT__ * __SIZEOF_INT__ - y)) ^ (x >> y); > +} > + > +unsigned int > +f51 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << (__CHAR_BIT__ * __SIZEOF_INT__ - 1)) ^ (x >> 1); > +} > + > +unsigned int > +f52 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << 1) ^ (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - 1)); > +} > + > +unsigned short int > +f53 (unsigned short int x, unsigned int y) > +{ > + return (x << (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)) ^ (x >> y); > +} > + > +unsigned short int > +f54 (unsigned short int x, unsigned long int y) > +{ > + return (x << (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)) ^ (x >> y); > +} > + > +unsigned char > +f55 (unsigned char x, unsigned int y) > +{ > + return (x << (__CHAR_BIT__ - y)) ^ (x >> y); > +} > + > +unsigned char > +f56 (unsigned char x, unsigned long int y) > +{ > + return (x << (__CHAR_BIT__ - y)) ^ (x >> y); > +} > + > +unsigned int > +f57 (unsigned int x, unsigned int y) > +{ > + return (x << (__CHAR_BIT__ * sizeof (unsigned int) - y)) ^ (x >> y); > +} > + > +unsigned int > +f58 (unsigned int x, unsigned long int y) > +{ > + return (x << (__CHAR_BIT__ * sizeof (unsigned int) - y)) ^ (x >> y); > +} > + > +unsigned int > +f59 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << (__CHAR_BIT__ * sizeof (unsigned int) - 1)) ^ (x >> 1); > +} > + > +unsigned int > +f60 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << 1) ^ (x >> (__CHAR_BIT__ * sizeof (unsigned int) - 1)); > +} > + > +unsigned short int > +f61 (unsigned short int x, unsigned int y) > +{ > + return (x << (__CHAR_BIT__ * sizeof (unsigned short) - y)) ^ (x >> y); > +} > + > +unsigned short int > +f62 (unsigned short int x, unsigned long int y) > +{ > + return (x << (__CHAR_BIT__ * sizeof (unsigned short) - y)) ^ (x >> y); > +} > + > +unsigned char > +f63 (unsigned char x, unsigned int y) > +{ > + return (x << (__CHAR_BIT__ * sizeof (unsigned char) - y)) ^ (x >> y); > +} > + > +unsigned char > +f64 (unsigned char x, unsigned long int y) > +{ > + return (x << (__CHAR_BIT__ * sizeof (unsigned char) - y)) ^ (x >> y); > +} > --- gcc/testsuite/c-c++-common/rotate-1a.c.jj 2013-05-09 15:19:28.179164195 > +0200 > +++ gcc/testsuite/c-c++-common/rotate-1a.c 2013-05-09 15:24:56.786327208 > +0200 > @@ -0,0 +1,44 @@ > +/* { dg-do run } */ > +/* { dg-options "-O2 -Wno-overflow" } */ > + > +extern > +#ifdef __cplusplus > +"C" > +#endif > +void abort (void); > + > +#ifndef ROTATE_N > +#define ROTATE_N "rotate-1.c" > +#endif > + > +#include ROTATE_N > + > +unsigned int expected[] = { > +0x91a2b3c0, 0x91a2b3c0, 0x2468acf0, 0x91a2b3c, 0xb3c2, 0xb3c2, 0xc3, 0xc3, > +0x91a2b3c0, 0x91a2b3c0, 0x2468acf0, 0x91a2b3c, 0xb3c2, 0xb3c2, 0xc3, 0xc3, > +0x91a2b3c0, 0x91a2b3c0, 0x2468acf0, 0x91a2b3c, 0xb3c2, 0xb3c2, 0xc3, 0xc3, > +0x91a2b3c0, 0x91a2b3c0, 0x2468acf0, 0x91a2b3c, 0xb3c2, 0xb3c2, 0xc3, 0xc3, > +0x2468acf, 0x2468acf, 0x91a2b3c, 0x2468acf0, 0xacf, 0xacf, 0xf, 0xf, > +0x2468acf, 0x2468acf, 0x91a2b3c, 0x2468acf0, 0xacf, 0xacf, 0xf, 0xf, > +0x2468acf, 0x2468acf, 0x91a2b3c, 0x2468acf0, 0xacf, 0xacf, 0xf, 0xf, > +0x2468acf, 0x2468acf, 0x91a2b3c, 0x2468acf0, 0xacf, 0xacf, 0xf, 0xf }; > + > +#define F(n) __typeof (f##n) f##n __attribute__((noinline, noclone)); > +#define D(n) F(n##0) F(n##1) F(n##2) F(n##3) F(n##4) F(n##5) F(n##6) F(n##7) > F(n##8) F(n##9) > +#define ALL \ > +F(1) F(2) F(3) F(4) F(5) F(6) F(7) F(8) F(9) \ > +D(1) D(2) D(3) D(4) D(5) F(60) F(61) F(62) F(63) F(64) > +ALL > + > +int > +main () > +{ > +#if __CHAR_BIT__ != 8 || __SIZEOF_SHORT__ != 2 || __SIZEOF_INT__ != 4 > + return 0; > +#else > +#undef F > +#define F(n) if ((unsigned int) f##n (0x12345678U, 3) != expected[n - 1]) > abort (); > + ALL > + return 0; > +#endif > +} > --- gcc/testsuite/c-c++-common/rotate-2.c.jj 2013-05-09 14:56:56.929709134 > +0200 > +++ gcc/testsuite/c-c++-common/rotate-2.c 2013-05-09 15:16:10.429264887 > +0200 > @@ -0,0 +1,389 @@ > +/* Check rotate pattern detection. */ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -fdump-tree-optimized" } */ > +/* { dg-final { scan-tree-dump-times "r\[<>]\[<>]" 64 "optimized" } } */ > +/* { dg-final { cleanup-tree-dump "optimized" } } */ > + > +unsigned int > +f1 (unsigned int x, unsigned int y) > +{ > + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); > +} > + > +unsigned int > +f2 (unsigned int x, unsigned long int y) > +{ > + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); > +} > + > +unsigned int > +f3 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << 1) | (x >> ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); > +} > + > +unsigned int > +f4 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) | (x >> 1); > +} > + > +unsigned short int > +f5 (unsigned short int x, unsigned int y) > +{ > + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))); > +} > + > +unsigned short int > +f6 (unsigned short int x, unsigned long int y) > +{ > + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))); > +} > + > +unsigned char > +f7 (unsigned char x, unsigned int y) > +{ > + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ - 1))); > +} > + > +unsigned char > +f8 (unsigned char x, unsigned long int y) > +{ > + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ - 1))); > +} > + > +unsigned int > +f9 (unsigned int x, unsigned int y) > +{ > + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - > 1))); > +} > + > +unsigned int > +f10 (unsigned int x, unsigned long int y) > +{ > + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - > 1))); > +} > + > +unsigned int > +f11 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << 1) | (x >> ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - > 1))); > +} > + > +unsigned int > +f12 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) | (x >> > 1); > +} > + > +unsigned short int > +f13 (unsigned short int x, unsigned int y) > +{ > + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - > 1))); > +} > + > +unsigned short int > +f14 (unsigned short int x, unsigned long int y) > +{ > + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - > 1))); > +} > + > +unsigned char > +f15 (unsigned char x, unsigned int y) > +{ > + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - > 1))); > +} > + > +unsigned char > +f16 (unsigned char x, unsigned long int y) > +{ > + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - > 1))); > +} > + > +unsigned int > +f17 (unsigned int x, unsigned int y) > +{ > + return (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) ^ (x << y); > +} > + > +unsigned int > +f18 (unsigned int x, unsigned long int y) > +{ > + return (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) ^ (x << y); > +} > + > +unsigned int > +f19 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x >> ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) ^ (x << 1); > +} > + > +unsigned int > +f20 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x >> 1) ^ (x << ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); > +} > + > +unsigned short int > +f21 (unsigned short int x, unsigned int y) > +{ > + return (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) ^ (x << y); > +} > + > +unsigned short int > +f22 (unsigned short int x, unsigned long int y) > +{ > + return (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) ^ (x << y); > +} > + > +unsigned char > +f23 (unsigned char x, unsigned int y) > +{ > + return (x >> ((-y) & (__CHAR_BIT__ - 1))) ^ (x << y); > +} > + > +unsigned char > +f24 (unsigned char x, unsigned long int y) > +{ > + return (x >> ((-y) & (__CHAR_BIT__ - 1))) ^ (x << y); > +} > + > +unsigned int > +f25 (unsigned int x, unsigned int y) > +{ > + return (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) ^ (x << > y); > +} > + > +unsigned int > +f26 (unsigned int x, unsigned long int y) > +{ > + return (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) ^ (x << > y); > +} > + > +unsigned int > +f27 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x >> ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) ^ (x << > 1); > +} > + > +unsigned int > +f28 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x >> 1) ^ (x << ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - > 1))); > +} > + > +unsigned short int > +f29 (unsigned short int x, unsigned int y) > +{ > + return (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) ^ (x > << y); > +} > + > +unsigned short int > +f30 (unsigned short int x, unsigned long int y) > +{ > + return (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) ^ (x > << y); > +} > + > +unsigned char > +f31 (unsigned char x, unsigned int y) > +{ > + return (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) ^ (x << > y); > +} > + > +unsigned char > +f32 (unsigned char x, unsigned long int y) > +{ > + return (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) ^ (x << > y); > +} > + > +unsigned int > +f33 (unsigned int x, unsigned int y) > +{ > + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); > +} > + > +unsigned int > +f34 (unsigned int x, unsigned long int y) > +{ > + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); > +} > + > +unsigned int > +f35 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x >> 1) | (x << ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); > +} > + > +unsigned int > +f36 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x >> ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) | (x << 1); > +} > + > +unsigned short int > +f37 (unsigned short int x, unsigned int y) > +{ > + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))); > +} > + > +unsigned short int > +f38 (unsigned short int x, unsigned long int y) > +{ > + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))); > +} > + > +unsigned char > +f39 (unsigned char x, unsigned int y) > +{ > + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ - 1))); > +} > + > +unsigned char > +f40 (unsigned char x, unsigned long int y) > +{ > + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ - 1))); > +} > + > +unsigned int > +f41 (unsigned int x, unsigned int y) > +{ > + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - > 1))); > +} > + > +unsigned int > +f42 (unsigned int x, unsigned long int y) > +{ > + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - > 1))); > +} > + > +unsigned int > +f43 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x >> 1) | (x << ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - > 1))); > +} > + > +unsigned int > +f44 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x >> ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) | (x << > 1); > +} > + > +unsigned short int > +f45 (unsigned short int x, unsigned int y) > +{ > + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - > 1))); > +} > + > +unsigned short int > +f46 (unsigned short int x, unsigned long int y) > +{ > + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - > 1))); > +} > + > +unsigned char > +f47 (unsigned char x, unsigned int y) > +{ > + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - > 1))); > +} > + > +unsigned char > +f48 (unsigned char x, unsigned long int y) > +{ > + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - > 1))); > +} > + > +unsigned int > +f49 (unsigned int x, unsigned int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) ^ (x >> y); > +} > + > +unsigned int > +f50 (unsigned int x, unsigned long int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) ^ (x >> y); > +} > + > +unsigned int > +f51 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) ^ (x >> 1); > +} > + > +unsigned int > +f52 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << 1) ^ (x >> ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); > +} > + > +unsigned short int > +f53 (unsigned short int x, unsigned int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) ^ (x >> y); > +} > + > +unsigned short int > +f54 (unsigned short int x, unsigned long int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) ^ (x >> y); > +} > + > +unsigned char > +f55 (unsigned char x, unsigned int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ - 1))) ^ (x >> y); > +} > + > +unsigned char > +f56 (unsigned char x, unsigned long int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ - 1))) ^ (x >> y); > +} > + > +unsigned int > +f57 (unsigned int x, unsigned int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) ^ (x >> > y); > +} > + > +unsigned int > +f58 (unsigned int x, unsigned long int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) ^ (x >> > y); > +} > + > +unsigned int > +f59 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) ^ (x >> > 1); > +} > + > +unsigned int > +f60 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << 1) ^ (x >> ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - > 1))); > +} > + > +unsigned short int > +f61 (unsigned short int x, unsigned int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) ^ (x > >> y); > +} > + > +unsigned short int > +f62 (unsigned short int x, unsigned long int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) ^ (x > >> y); > +} > + > +unsigned char > +f63 (unsigned char x, unsigned int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) ^ (x >> > y); > +} > + > +unsigned char > +f64 (unsigned char x, unsigned long int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) ^ (x >> > y); > +} > --- gcc/testsuite/c-c++-common/rotate-2a.c.jj 2013-05-09 15:19:31.617145493 > +0200 > +++ gcc/testsuite/c-c++-common/rotate-2a.c 2013-05-09 15:23:06.388944450 > +0200 > @@ -0,0 +1,6 @@ > +/* { dg-do run } */ > +/* { dg-options "-O2 -Wno-overflow" } */ > + > +#define ROTATE_N "rotate-2.c" > + > +#include "rotate-1a.c" > --- gcc/testsuite/c-c++-common/rotate-3.c.jj 2013-05-09 15:01:15.894264414 > +0200 > +++ gcc/testsuite/c-c++-common/rotate-3.c 2013-05-09 15:16:16.994225808 > +0200 > @@ -0,0 +1,389 @@ > +/* Check rotate pattern detection. */ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -fdump-tree-optimized" } */ > +/* { dg-final { scan-tree-dump-times "r\[<>]\[<>]" 64 "optimized" } } */ > +/* { dg-final { cleanup-tree-dump "optimized" } } */ > + > +unsigned int > +f1 (unsigned int x, int y) > +{ > + return (x << y) | (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - y)); > +} > + > +unsigned int > +f2 (unsigned int x, long int y) > +{ > + return (x << y) | (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - y)); > +} > + > +unsigned int > +f3 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << 1) | (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - 1)); > +} > + > +unsigned int > +f4 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << (__CHAR_BIT__ * __SIZEOF_INT__ - 1)) | (x >> 1); > +} > + > +unsigned short int > +f5 (unsigned short int x, int y) > +{ > + return (x << y) | (x >> (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)); > +} > + > +unsigned short int > +f6 (unsigned short int x, long int y) > +{ > + return (x << y) | (x >> (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)); > +} > + > +unsigned char > +f7 (unsigned char x, int y) > +{ > + return (x << y) | (x >> (__CHAR_BIT__ - y)); > +} > + > +unsigned char > +f8 (unsigned char x, long int y) > +{ > + return (x << y) | (x >> (__CHAR_BIT__ - y)); > +} > + > +unsigned int > +f9 (unsigned int x, int y) > +{ > + return (x << y) | (x >> (__CHAR_BIT__ * sizeof (unsigned int) - y)); > +} > + > +unsigned int > +f10 (unsigned int x, long int y) > +{ > + return (x << y) | (x >> (__CHAR_BIT__ * sizeof (unsigned int) - y)); > +} > + > +unsigned int > +f11 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << 1) | (x >> (__CHAR_BIT__ * sizeof (unsigned int) - 1)); > +} > + > +unsigned int > +f12 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << (__CHAR_BIT__ * sizeof (unsigned int) - 1)) | (x >> 1); > +} > + > +unsigned short int > +f13 (unsigned short int x, int y) > +{ > + return (x << y) | (x >> (__CHAR_BIT__ * sizeof (unsigned short) - y)); > +} > + > +unsigned short int > +f14 (unsigned short int x, long int y) > +{ > + return (x << y) | (x >> (__CHAR_BIT__ * sizeof (unsigned short) - y)); > +} > + > +unsigned char > +f15 (unsigned char x, int y) > +{ > + return (x << y) | (x >> (__CHAR_BIT__ * sizeof (unsigned char) - y)); > +} > + > +unsigned char > +f16 (unsigned char x, long int y) > +{ > + return (x << y) | (x >> (__CHAR_BIT__ * sizeof (unsigned char) - y)); > +} > + > +unsigned int > +f17 (unsigned int x, int y) > +{ > + return (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - y)) ^ (x << y); > +} > + > +unsigned int > +f18 (unsigned int x, long int y) > +{ > + return (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - y)) ^ (x << y); > +} > + > +unsigned int > +f19 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - 1)) ^ (x << 1); > +} > + > +unsigned int > +f20 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x >> 1) ^ (x << (__CHAR_BIT__ * __SIZEOF_INT__ - 1)); > +} > + > +unsigned short int > +f21 (unsigned short int x, int y) > +{ > + return (x >> (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)) ^ (x << y); > +} > + > +unsigned short int > +f22 (unsigned short int x, long int y) > +{ > + return (x >> (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)) ^ (x << y); > +} > + > +unsigned char > +f23 (unsigned char x, int y) > +{ > + return (x >> (__CHAR_BIT__ - y)) ^ (x << y); > +} > + > +unsigned char > +f24 (unsigned char x, long int y) > +{ > + return (x >> (__CHAR_BIT__ - y)) ^ (x << y); > +} > + > +unsigned int > +f25 (unsigned int x, int y) > +{ > + return (x >> (__CHAR_BIT__ * sizeof (unsigned int) - y)) ^ (x << y); > +} > + > +unsigned int > +f26 (unsigned int x, long int y) > +{ > + return (x >> (__CHAR_BIT__ * sizeof (unsigned int) - y)) ^ (x << y); > +} > + > +unsigned int > +f27 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x >> (__CHAR_BIT__ * sizeof (unsigned int) - 1)) ^ (x << 1); > +} > + > +unsigned int > +f28 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x >> 1) ^ (x << (__CHAR_BIT__ * sizeof (unsigned int) - 1)); > +} > + > +unsigned short int > +f29 (unsigned short int x, int y) > +{ > + return (x >> (__CHAR_BIT__ * sizeof (unsigned short) - y)) ^ (x << y); > +} > + > +unsigned short int > +f30 (unsigned short int x, long int y) > +{ > + return (x >> (__CHAR_BIT__ * sizeof (unsigned short) - y)) ^ (x << y); > +} > + > +unsigned char > +f31 (unsigned char x, int y) > +{ > + return (x >> (__CHAR_BIT__ * sizeof (unsigned char) - y)) ^ (x << y); > +} > + > +unsigned char > +f32 (unsigned char x, long int y) > +{ > + return (x >> (__CHAR_BIT__ * sizeof (unsigned char) - y)) ^ (x << y); > +} > + > +unsigned int > +f33 (unsigned int x, int y) > +{ > + return (x >> y) | (x << (__CHAR_BIT__ * __SIZEOF_INT__ - y)); > +} > + > +unsigned int > +f34 (unsigned int x, long int y) > +{ > + return (x >> y) | (x << (__CHAR_BIT__ * __SIZEOF_INT__ - y)); > +} > + > +unsigned int > +f35 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x >> 1) | (x << (__CHAR_BIT__ * __SIZEOF_INT__ - 1)); > +} > + > +unsigned int > +f36 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - 1)) | (x << 1); > +} > + > +unsigned short int > +f37 (unsigned short int x, int y) > +{ > + return (x >> y) | (x << (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)); > +} > + > +unsigned short int > +f38 (unsigned short int x, long int y) > +{ > + return (x >> y) | (x << (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)); > +} > + > +unsigned char > +f39 (unsigned char x, int y) > +{ > + return (x >> y) | (x << (__CHAR_BIT__ - y)); > +} > + > +unsigned char > +f40 (unsigned char x, long int y) > +{ > + return (x >> y) | (x << (__CHAR_BIT__ - y)); > +} > + > +unsigned int > +f41 (unsigned int x, int y) > +{ > + return (x >> y) | (x << (__CHAR_BIT__ * sizeof (unsigned int) - y)); > +} > + > +unsigned int > +f42 (unsigned int x, long int y) > +{ > + return (x >> y) | (x << (__CHAR_BIT__ * sizeof (unsigned int) - y)); > +} > + > +unsigned int > +f43 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x >> 1) | (x << (__CHAR_BIT__ * sizeof (unsigned int) - 1)); > +} > + > +unsigned int > +f44 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x >> (__CHAR_BIT__ * sizeof (unsigned int) - 1)) | (x << 1); > +} > + > +unsigned short int > +f45 (unsigned short int x, int y) > +{ > + return (x >> y) | (x << (__CHAR_BIT__ * sizeof (unsigned short) - y)); > +} > + > +unsigned short int > +f46 (unsigned short int x, long int y) > +{ > + return (x >> y) | (x << (__CHAR_BIT__ * sizeof (unsigned short) - y)); > +} > + > +unsigned char > +f47 (unsigned char x, int y) > +{ > + return (x >> y) | (x << (__CHAR_BIT__ * sizeof (unsigned char) - y)); > +} > + > +unsigned char > +f48 (unsigned char x, long int y) > +{ > + return (x >> y) | (x << (__CHAR_BIT__ * sizeof (unsigned char) - y)); > +} > + > +unsigned int > +f49 (unsigned int x, int y) > +{ > + return (x << (__CHAR_BIT__ * __SIZEOF_INT__ - y)) ^ (x >> y); > +} > + > +unsigned int > +f50 (unsigned int x, long int y) > +{ > + return (x << (__CHAR_BIT__ * __SIZEOF_INT__ - y)) ^ (x >> y); > +} > + > +unsigned int > +f51 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << (__CHAR_BIT__ * __SIZEOF_INT__ - 1)) ^ (x >> 1); > +} > + > +unsigned int > +f52 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << 1) ^ (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - 1)); > +} > + > +unsigned short int > +f53 (unsigned short int x, int y) > +{ > + return (x << (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)) ^ (x >> y); > +} > + > +unsigned short int > +f54 (unsigned short int x, long int y) > +{ > + return (x << (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)) ^ (x >> y); > +} > + > +unsigned char > +f55 (unsigned char x, int y) > +{ > + return (x << (__CHAR_BIT__ - y)) ^ (x >> y); > +} > + > +unsigned char > +f56 (unsigned char x, long int y) > +{ > + return (x << (__CHAR_BIT__ - y)) ^ (x >> y); > +} > + > +unsigned int > +f57 (unsigned int x, int y) > +{ > + return (x << (__CHAR_BIT__ * sizeof (unsigned int) - y)) ^ (x >> y); > +} > + > +unsigned int > +f58 (unsigned int x, long int y) > +{ > + return (x << (__CHAR_BIT__ * sizeof (unsigned int) - y)) ^ (x >> y); > +} > + > +unsigned int > +f59 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << (__CHAR_BIT__ * sizeof (unsigned int) - 1)) ^ (x >> 1); > +} > + > +unsigned int > +f60 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << 1) ^ (x >> (__CHAR_BIT__ * sizeof (unsigned int) - 1)); > +} > + > +unsigned short int > +f61 (unsigned short int x, int y) > +{ > + return (x << (__CHAR_BIT__ * sizeof (unsigned short) - y)) ^ (x >> y); > +} > + > +unsigned short int > +f62 (unsigned short int x, long int y) > +{ > + return (x << (__CHAR_BIT__ * sizeof (unsigned short) - y)) ^ (x >> y); > +} > + > +unsigned char > +f63 (unsigned char x, int y) > +{ > + return (x << (__CHAR_BIT__ * sizeof (unsigned char) - y)) ^ (x >> y); > +} > + > +unsigned char > +f64 (unsigned char x, long int y) > +{ > + return (x << (__CHAR_BIT__ * sizeof (unsigned char) - y)) ^ (x >> y); > +} > --- gcc/testsuite/c-c++-common/rotate-3a.c.jj 2013-05-09 15:23:20.079868427 > +0200 > +++ gcc/testsuite/c-c++-common/rotate-3a.c 2013-05-09 15:23:31.910802207 > +0200 > @@ -0,0 +1,6 @@ > +/* { dg-do run } */ > +/* { dg-options "-O2 -Wno-overflow" } */ > + > +#define ROTATE_N "rotate-4.c" > + > +#include "rotate-1a.c" > --- gcc/testsuite/c-c++-common/rotate-4.c.jj 2013-05-09 15:01:40.210126009 > +0200 > +++ gcc/testsuite/c-c++-common/rotate-4.c 2013-05-09 15:16:24.026187297 > +0200 > @@ -0,0 +1,389 @@ > +/* Check rotate pattern detection. */ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -fdump-tree-optimized" } */ > +/* { dg-final { scan-tree-dump-times "r\[<>]\[<>]" 64 "optimized" } } */ > +/* { dg-final { cleanup-tree-dump "optimized" } } */ > + > +unsigned int > +f1 (unsigned int x, int y) > +{ > + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); > +} > + > +unsigned int > +f2 (unsigned int x, long int y) > +{ > + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); > +} > + > +unsigned int > +f3 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << 1) | (x >> ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); > +} > + > +unsigned int > +f4 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) | (x >> 1); > +} > + > +unsigned short int > +f5 (unsigned short int x, int y) > +{ > + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))); > +} > + > +unsigned short int > +f6 (unsigned short int x, long int y) > +{ > + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))); > +} > + > +unsigned char > +f7 (unsigned char x, int y) > +{ > + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ - 1))); > +} > + > +unsigned char > +f8 (unsigned char x, long int y) > +{ > + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ - 1))); > +} > + > +unsigned int > +f9 (unsigned int x, int y) > +{ > + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - > 1))); > +} > + > +unsigned int > +f10 (unsigned int x, long int y) > +{ > + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - > 1))); > +} > + > +unsigned int > +f11 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << 1) | (x >> ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - > 1))); > +} > + > +unsigned int > +f12 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) | (x >> > 1); > +} > + > +unsigned short int > +f13 (unsigned short int x, int y) > +{ > + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - > 1))); > +} > + > +unsigned short int > +f14 (unsigned short int x, long int y) > +{ > + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - > 1))); > +} > + > +unsigned char > +f15 (unsigned char x, int y) > +{ > + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - > 1))); > +} > + > +unsigned char > +f16 (unsigned char x, long int y) > +{ > + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - > 1))); > +} > + > +unsigned int > +f17 (unsigned int x, int y) > +{ > + return (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) ^ (x << y); > +} > + > +unsigned int > +f18 (unsigned int x, long int y) > +{ > + return (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) ^ (x << y); > +} > + > +unsigned int > +f19 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x >> ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) ^ (x << 1); > +} > + > +unsigned int > +f20 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x >> 1) ^ (x << ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); > +} > + > +unsigned short int > +f21 (unsigned short int x, int y) > +{ > + return (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) ^ (x << y); > +} > + > +unsigned short int > +f22 (unsigned short int x, long int y) > +{ > + return (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) ^ (x << y); > +} > + > +unsigned char > +f23 (unsigned char x, int y) > +{ > + return (x >> ((-y) & (__CHAR_BIT__ - 1))) ^ (x << y); > +} > + > +unsigned char > +f24 (unsigned char x, long int y) > +{ > + return (x >> ((-y) & (__CHAR_BIT__ - 1))) ^ (x << y); > +} > + > +unsigned int > +f25 (unsigned int x, int y) > +{ > + return (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) ^ (x << > y); > +} > + > +unsigned int > +f26 (unsigned int x, long int y) > +{ > + return (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) ^ (x << > y); > +} > + > +unsigned int > +f27 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x >> ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) ^ (x << > 1); > +} > + > +unsigned int > +f28 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x >> 1) ^ (x << ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - > 1))); > +} > + > +unsigned short int > +f29 (unsigned short int x, int y) > +{ > + return (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) ^ (x > << y); > +} > + > +unsigned short int > +f30 (unsigned short int x, long int y) > +{ > + return (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) ^ (x > << y); > +} > + > +unsigned char > +f31 (unsigned char x, int y) > +{ > + return (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) ^ (x << > y); > +} > + > +unsigned char > +f32 (unsigned char x, long int y) > +{ > + return (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) ^ (x << > y); > +} > + > +unsigned int > +f33 (unsigned int x, int y) > +{ > + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); > +} > + > +unsigned int > +f34 (unsigned int x, long int y) > +{ > + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); > +} > + > +unsigned int > +f35 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x >> 1) | (x << ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); > +} > + > +unsigned int > +f36 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x >> ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) | (x << 1); > +} > + > +unsigned short int > +f37 (unsigned short int x, int y) > +{ > + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))); > +} > + > +unsigned short int > +f38 (unsigned short int x, long int y) > +{ > + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))); > +} > + > +unsigned char > +f39 (unsigned char x, int y) > +{ > + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ - 1))); > +} > + > +unsigned char > +f40 (unsigned char x, long int y) > +{ > + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ - 1))); > +} > + > +unsigned int > +f41 (unsigned int x, int y) > +{ > + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - > 1))); > +} > + > +unsigned int > +f42 (unsigned int x, long int y) > +{ > + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - > 1))); > +} > + > +unsigned int > +f43 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x >> 1) | (x << ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - > 1))); > +} > + > +unsigned int > +f44 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x >> ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) | (x << > 1); > +} > + > +unsigned short int > +f45 (unsigned short int x, int y) > +{ > + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - > 1))); > +} > + > +unsigned short int > +f46 (unsigned short int x, long int y) > +{ > + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - > 1))); > +} > + > +unsigned char > +f47 (unsigned char x, int y) > +{ > + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - > 1))); > +} > + > +unsigned char > +f48 (unsigned char x, long int y) > +{ > + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - > 1))); > +} > + > +unsigned int > +f49 (unsigned int x, int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) ^ (x >> y); > +} > + > +unsigned int > +f50 (unsigned int x, long int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) ^ (x >> y); > +} > + > +unsigned int > +f51 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) ^ (x >> 1); > +} > + > +unsigned int > +f52 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << 1) ^ (x >> ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); > +} > + > +unsigned short int > +f53 (unsigned short int x, int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) ^ (x >> y); > +} > + > +unsigned short int > +f54 (unsigned short int x, long int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) ^ (x >> y); > +} > + > +unsigned char > +f55 (unsigned char x, int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ - 1))) ^ (x >> y); > +} > + > +unsigned char > +f56 (unsigned char x, long int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ - 1))) ^ (x >> y); > +} > + > +unsigned int > +f57 (unsigned int x, int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) ^ (x >> > y); > +} > + > +unsigned int > +f58 (unsigned int x, long int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) ^ (x >> > y); > +} > + > +unsigned int > +f59 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) ^ (x >> > 1); > +} > + > +unsigned int > +f60 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << 1) ^ (x >> ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - > 1))); > +} > + > +unsigned short int > +f61 (unsigned short int x, int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) ^ (x > >> y); > +} > + > +unsigned short int > +f62 (unsigned short int x, long int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) ^ (x > >> y); > +} > + > +unsigned char > +f63 (unsigned char x, int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) ^ (x >> > y); > +} > + > +unsigned char > +f64 (unsigned char x, long int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) ^ (x >> > y); > +} > --- gcc/testsuite/c-c++-common/rotate-4a.c.jj 2013-05-09 15:23:20.079868427 > +0200 > +++ gcc/testsuite/c-c++-common/rotate-4a.c 2013-05-09 15:23:24.775841083 > +0200 > @@ -0,0 +1,6 @@ > +/* { dg-do run } */ > +/* { dg-options "-O2 -Wno-overflow" } */ > + > +#define ROTATE_N "rotate-4.c" > + > +#include "rotate-1a.c" > --- gcc/testsuite/gcc.target/i386/rotate-1.c.jj 2008-09-05 > 12:54:23.000000000 +0200 > +++ gcc/testsuite/gcc.target/i386/rotate-1.c 2013-05-09 20:32:42.038756873 > +0200 > @@ -13,4 +13,4 @@ main (void) > return c; > } > > -/* { dg-final { scan-assembler "rolb" } } */ > +/* { dg-final { scan-assembler "ro\[lr]b" } } */ > > Jakub > > -- Richard Biener <rguent...@suse.de> SUSE / SUSE Labs SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746 GF: Jeff Hawn, Jennifer Guild, Felix Imend