gcc/c/ 2016-07-01 Jan Beulich <jbeul...@suse.com> * c-fold.c (c_fully_fold_internal): Also emit shift count warnings for vector types. * c-typeck.c (build_binary_op): Likewise.
gcc/testsuite/ 2016-07-01 Jan Beulich <jbeul...@suse.com> * gcc.dg/vshift-6.c, gcc.dg/vshift-7.c: New. --- 2016-06-30/gcc/c/c-fold.c +++ 2016-06-30/gcc/c/c-fold.c @@ -320,8 +320,6 @@ c_fully_fold_internal (tree expr, bool i if ((code == LSHIFT_EXPR || code == RSHIFT_EXPR) && TREE_CODE (orig_op1) != INTEGER_CST && TREE_CODE (op1) == INTEGER_CST - && (TREE_CODE (TREE_TYPE (orig_op0)) == INTEGER_TYPE - || TREE_CODE (TREE_TYPE (orig_op0)) == FIXED_POINT_TYPE) && TREE_CODE (TREE_TYPE (orig_op1)) == INTEGER_TYPE && c_inhibit_evaluation_warnings == 0) { @@ -330,13 +328,23 @@ c_fully_fold_internal (tree expr, bool i (code == LSHIFT_EXPR ? G_("left shift count is negative") : G_("right shift count is negative"))); - else if (compare_tree_int (op1, - TYPE_PRECISION (TREE_TYPE (orig_op0))) - >= 0) + else if ((TREE_CODE (TREE_TYPE (orig_op0)) == INTEGER_TYPE + || TREE_CODE (TREE_TYPE (orig_op0)) == FIXED_POINT_TYPE) + && compare_tree_int (op1, + TYPE_PRECISION (TREE_TYPE (orig_op0))) + >= 0) warning_at (loc, OPT_Wshift_count_overflow, (code == LSHIFT_EXPR ? G_("left shift count >= width of type") : G_("right shift count >= width of type"))); + else if (TREE_CODE (TREE_TYPE (orig_op0)) == VECTOR_TYPE + && compare_tree_int (op1, + TYPE_PRECISION (TREE_TYPE (TREE_TYPE (orig_op0)))) + >= 0) + warning_at (loc, OPT_Wshift_count_overflow, + code == LSHIFT_EXPR + ? G_("left shift count >= width of vector element") + : G_("right shift count >= width of vector element")); } if (code == LSHIFT_EXPR /* If either OP0 has been folded to INTEGER_CST... */ --- 2016-06-30/gcc/c/c-typeck.c +++ 2016-06-30/gcc/c/c-typeck.c @@ -10985,21 +10985,16 @@ build_binary_op (location_t location, en Also set SHORT_SHIFT if shifting rightward. */ case RSHIFT_EXPR: - if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE - && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE) - { - result_type = type0; - converted = 1; - } - else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE - && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE - && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE - && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1)) + if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE + && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE + && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE + && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1)) { result_type = type0; converted = 1; } - else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE) + else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE + || code0 == VECTOR_TYPE) && code1 == INTEGER_TYPE) { doing_shift = true; @@ -11012,6 +11007,18 @@ build_binary_op (location_t location, en warning_at (location, OPT_Wshift_count_negative, "right shift count is negative"); } + else if (code0 == VECTOR_TYPE) + { + if (compare_tree_int (op1, + TYPE_PRECISION (TREE_TYPE (type0))) + >= 0) + { + int_const = false; + if (c_inhibit_evaluation_warnings == 0) + warning_at (location, OPT_Wshift_count_overflow, + "right shift count >= width of vector element"); + } + } else { if (!integer_zerop (op1)) @@ -11035,21 +11042,16 @@ build_binary_op (location_t location, en break; case LSHIFT_EXPR: - if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE - && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE) - { - result_type = type0; - converted = 1; - } - else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE - && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE - && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE - && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1)) + if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE + && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE + && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE + && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1)) { result_type = type0; converted = 1; } - else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE) + else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE + || code0 == VECTOR_TYPE) && code1 == INTEGER_TYPE) { doing_shift = true; @@ -11073,6 +11075,18 @@ build_binary_op (location_t location, en warning_at (location, OPT_Wshift_count_negative, "left shift count is negative"); } + else if (code0 == VECTOR_TYPE) + { + if (compare_tree_int (op1, + TYPE_PRECISION (TREE_TYPE (type0))) + >= 0) + { + int_const = false; + if (c_inhibit_evaluation_warnings == 0) + warning_at (location, OPT_Wshift_count_overflow, + "left shift count >= width of vector element"); + } + } else if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0) { int_const = false; --- 2016-06-30/gcc/testsuite/gcc.dg/vshift-6.c +++ 2016-06-30/gcc/testsuite/gcc.dg/vshift-6.c @@ -0,0 +1,42 @@ +/* { dg-do compile } */ +/* { dg-options "-Wshift-count-negative -Wshift-count-overflow" } */ + +typedef unsigned int v1qi_t __attribute__((mode(QI), vector_size(1))); +typedef unsigned int v1hi_t __attribute__((mode(HI), vector_size(2))); +typedef unsigned int v1si_t __attribute__((mode(SI), vector_size(4))); + +v1qi_t test1qi(v1qi_t x, int c) { + switch(c) { + case 0: return x << -1; /* { dg-warning "shift count is negative" } */ + case 1: return x << 7; + case 2: return x << 8; /* { dg-warning "shift count >= width" } */ + case ~0: return x >> -1; /* { dg-warning "shift count is negative" } */ + case ~1: return x >> 7; + case ~2: return x >> 8; /* { dg-warning "shift count >= width" } */ + } + return c < 0 ? x >> -c : x << c; +} + +v1hi_t test1hi(v1hi_t x, int c) { + switch(c) { + case 0: return x << -1; /* { dg-warning "shift count is negative" } */ + case 1: return x << 15; + case 2: return x << 16; /* { dg-warning "shift count >= width" } */ + case ~0: return x >> -1; /* { dg-warning "shift count is negative" } */ + case ~1: return x >> 15; + case ~2: return x >> 16; /* { dg-warning "shift count >= width" } */ + } + return c < 0 ? x >> -c : x << c; +} + +v1si_t test1si(v1si_t x, int c) { + switch(c) { + case 0: return x << -1; /* { dg-warning "shift count is negative" } */ + case 1: return x << 31; + case 2: return x << 32; /* { dg-warning "shift count >= width" } */ + case ~0: return x >> -1; /* { dg-warning "shift count is negative" } */ + case ~1: return x >> 31; + case ~2: return x >> 32; /* { dg-warning "shift count >= width" } */ + } + return c < 0 ? x >> -c : x << c; +} --- 2016-06-30/gcc/testsuite/gcc.dg/vshift-7.c +++ 2016-06-30/gcc/testsuite/gcc.dg/vshift-7.c @@ -0,0 +1,47 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -Wshift-count-negative -Wshift-count-overflow" } */ + +typedef unsigned int v1qi_t __attribute__((mode(QI), vector_size(1))); +typedef unsigned int v1hi_t __attribute__((mode(HI), vector_size(2))); +typedef unsigned int v1si_t __attribute__((mode(SI), vector_size(4))); + +static const signed shift_neg = -1; +static const unsigned shift_qi = 8; +static const unsigned shift_hi = 16; +static const unsigned shift_si = 32; + +v1qi_t test1qi(v1qi_t x, int c) { + switch(c) { + case 0: return x << shift_neg; /* { dg-warning "shift count is negative" } */ + case 1: return x << (shift_qi - 1); + case 2: return x << shift_qi; /* { dg-warning "shift count >= width" } */ + case ~0: return x >> shift_neg; /* { dg-warning "shift count is negative" } */ + case ~1: return x >> (shift_qi - 1); + case ~2: return x >> shift_qi; /* { dg-warning "shift count >= width" } */ + } + return c < 0 ? x >> -c : x << c; +} + +v1hi_t test1hi(v1hi_t x, int c) { + switch(c) { + case 0: return x << shift_neg; /* { dg-warning "shift count is negative" } */ + case 1: return x << (shift_hi - 1); + case 2: return x << shift_hi; /* { dg-warning "shift count >= width" } */ + case ~0: return x >> shift_neg; /* { dg-warning "shift count is negative" } */ + case ~1: return x >> (shift_hi - 1); + case ~2: return x >> shift_hi; /* { dg-warning "shift count >= width" } */ + } + return c < 0 ? x >> -c : x << c; +} + +v1si_t test1si(v1si_t x, int c) { + switch(c) { + case 0: return x << shift_neg; /* { dg-warning "shift count is negative" } */ + case 1: return x << (shift_si - 1); + case 2: return x << shift_si; /* { dg-warning "shift count >= width" } */ + case ~0: return x >> shift_neg; /* { dg-warning "shift count is negative" } */ + case ~1: return x >> (shift_si - 1); + case ~2: return x >> shift_si; /* { dg-warning "shift count >= width" } */ + } + return c < 0 ? x >> -c : x << c; +}