diff --git a/gcc/testsuite/gcc.c-torture/execute/pr109778.c b/gcc/testsuite/gcc.c-torture/execute/pr109778.c new file mode 100644 index 0000000000000000000000000000000000000000..309fbf413e019c60f6c8dc823d450e8f5813eae4 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr109778.c @@ -0,0 +1,26 @@ +/* PR tree-optimization/109778 */ + +int a, b, c, d, *e = &c; + +static inline unsigned +foo (unsigned char x) +{ + x = 1 | x << 1; + x = x >> 4 | x << 4; + return x; +} + +static inline void +bar (unsigned x) +{ + *e = 8 > foo (x + 86) - 86; +} + +int +main () +{ + d = a && b; + bar (d + 4); + if (c != 1) + __builtin_abort (); +} diff --git a/gcc/tree-ssa-ccp.cc b/gcc/tree-ssa-ccp.cc index 03a984f2adfd0834f00393855061cfaa99a11714..2e552b330b741a25174caaf490658f5640a808ba 100644 --- a/gcc/tree-ssa-ccp.cc +++ b/gcc/tree-ssa-ccp.cc @@ -1552,6 +1552,8 @@ bit_value_binop (enum tree_code code, signop sgn, int width, *mask = wi::lrotate (r1mask, shift, width); *val = wi::lrotate (r1val, shift, width); } + *mask = wi::ext (*mask, width, sgn); + *val = wi::ext (*val, width, sgn); } } else if (wi::ltu_p (r2val | r2mask, width) @@ -1593,8 +1595,8 @@ bit_value_binop (enum tree_code code, signop sgn, int width, /* Accumulate the result. */ res_mask |= tmp_mask | (res_val ^ tmp_val); } - *val = wi::bit_and_not (res_val, res_mask); - *mask = res_mask; + *val = wi::ext (wi::bit_and_not (res_val, res_mask), width, sgn); + *mask = wi::ext (res_mask, width, sgn); } break; diff --git a/gcc/wide-int.h b/gcc/wide-int.h index a450a744c9f27b1807a26a1b5e84067f193b9c67..8c1c14f641f8ca6e66a23af3482b5dc492627ba6 100644 --- a/gcc/wide-int.h +++ b/gcc/wide-int.h @@ -3185,9 +3185,11 @@ wi::lrotate (const T1 &x, const T2 &y, unsigned int width) width = precision; WI_UNARY_RESULT (T2) ymod = umod_trunc (y, width); WI_UNARY_RESULT (T1) left = wi::lshift (x, ymod); - WI_UNARY_RESULT (T1) right = wi::lrshift (x, wi::sub (width, ymod)); + WI_UNARY_RESULT (T1) right + = wi::lrshift (width != precision ? wi::zext (x, width) : x, + wi::sub (width, ymod)); if (width != precision) - return wi::zext (left, width) | wi::zext (right, width); + return wi::zext (left, width) | right; return left | right; } @@ -3202,10 +3204,11 @@ wi::rrotate (const T1 &x, const T2 &y, unsigned int width) if (width == 0) width = precision; WI_UNARY_RESULT (T2) ymod = umod_trunc (y, width); - WI_UNARY_RESULT (T1) right = wi::lrshift (x, ymod); + WI_UNARY_RESULT (T1) right + = wi::lrshift (width != precision ? wi::zext (x, width) : x, ymod); WI_UNARY_RESULT (T1) left = wi::lshift (x, wi::sub (width, ymod)); if (width != precision) - return wi::zext (left, width) | wi::zext (right, width); + return wi::zext (left, width) | right; return left | right; }