--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+unsigned int test1(unsigned int a , unsigned int b)
+{
+ return (a << 2) + (b << 2) == a * 4 + b * 4;
+}
+
+unsigned int test2(unsigned int a , unsigned int b)
+{
+ return (a << 2) + (b << 2) == (a + b) << 2;
+}
+
+unsigned int test3(unsigned int a , unsigned int b)
+{
+ return a * 4 + b * 4 == (a + b) * 4;
+}
+
+unsigned int test4(unsigned int a , unsigned int b)
+{
+ return (a + b) << 2 == (a + b) * 4;
+}
+
+unsigned int test5(unsigned int a , unsigned int b)
+{
+ return (a << 2) + (b << 2) == (a + b) * 4;
+}
+
+unsigned int test6(unsigned int a , unsigned int b)
+{
+ return (a + b) << 2 == a * 4 + b * 4;
+}
+
+/* { dg-final { scan-tree-dump-times "return 1" 6 "optimized" } } */
}
}
break;
+ case LSHIFT_EXPR:
+ /* For X << C, use the value number of X * (1 << C). */
+ if (INTEGRAL_TYPE_P (type)
+ && TYPE_OVERFLOW_WRAPS (type)
+ && !TYPE_SATURATING (type))
+ {
+ tree rhs2 = gimple_assign_rhs2 (stmt);
+ if (TREE_CODE (rhs2) == INTEGER_CST
+ && tree_fits_uhwi_p (rhs2)
+ && tree_to_uhwi (rhs2) < TYPE_PRECISION (type))
+ {
+ wide_int w = wi::set_bit_in_zero (tree_to_uhwi (rhs2),
+ TYPE_PRECISION (type));
+ gimple_match_op match_op (gimple_match_cond::UNCOND,
+ MULT_EXPR, type, rhs1,
+ wide_int_to_tree (type, w));
+ result = vn_nary_build_or_lookup (&match_op);
+ if (result)
+ {
+ bool changed = set_ssa_val_to (lhs, result);
+ vn_nary_op_insert_stmt (stmt, result);
+ return changed;
+ }
+ }
+ }
+ break;
default:
break;
}