https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65084
Richard Biener <rguenth at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |NEW Last reconfirmed| |2015-02-17 Ever confirmed|0 |1 --- Comment #2 from Richard Biener <rguenth at gcc dot gnu.org> --- Confirmed. Btw, this is just the lack of shorten_* on the GIMPLE level. For your match.pd pattern it is a matter of simplifying/changing it slightly: Index: match.pd =================================================================== --- match.pd (revision 220751) +++ match.pd (working copy) @@ -1031,31 +1031,22 @@ (define_operator_list CBRT BUILT_IN_CBRT operation and convert the result to the desired type. */ (for op (plus minus) (simplify - (convert (op (convert@2 @0) (convert@3 @1))) + (convert (op:c@4 (convert@2 @0) (convert?@3 @1))) (if (INTEGRAL_TYPE_P (type) - /* We check for type compatibility between @0 and @1 below, - so there's no need to check that @1/@3 are integral types. */ && INTEGRAL_TYPE_P (TREE_TYPE (@0)) - && INTEGRAL_TYPE_P (TREE_TYPE (@2)) + && INTEGRAL_TYPE_P (TREE_TYPE (@4)) /* The precision of the type of each operand must match the precision of the mode of each operand, similarly for the result. */ && (TYPE_PRECISION (TREE_TYPE (@0)) == GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (@0)))) - && (TYPE_PRECISION (TREE_TYPE (@1)) - == GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (@1)))) - && TYPE_PRECISION (type) == GET_MODE_PRECISION (TYPE_MODE (type)) /* The inner conversion must be a widening conversion. */ && TYPE_PRECISION (TREE_TYPE (@2)) > TYPE_PRECISION (TREE_TYPE (@0)) - && ((GENERIC - && (TYPE_MAIN_VARIANT (TREE_TYPE (@0)) - == TYPE_MAIN_VARIANT (TREE_TYPE (@1))) - && (TYPE_MAIN_VARIANT (TREE_TYPE (@0)) - == TYPE_MAIN_VARIANT (type))) - || (GIMPLE - && types_compatible_p (TREE_TYPE (@0), TREE_TYPE (@1)) - && types_compatible_p (TREE_TYPE (@0), type)))) + /* The final precision should match that of operand @0. */ + && TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (@0)) + /* Make sure the wide operation is dead after the transform. */ + && (TREE_CODE (@4) != SSA_NAME || has_single_use (@4))) (if (TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0))) - (convert (op @0 @1))) + (convert (op @0 (convert @1)))) (with { tree utype = unsigned_type_for (TREE_TYPE (@0)); } (convert (op (convert:utype @0) (convert:utype @1))))))) to allow for constant @1 (where the convert would be folded into the constant itself). And we then get before vectorization: <bb 3>: # i_17 = PHI <i_13(4), 0(2)> # ivtmp_30 = PHI <ivtmp_29(4), 1024(2)> _5 = a[i_17]; _6 = (char) _5; _7 = (unsigned short) _6; _9 = b[i_17]; _3 = (unsigned short) _9; _14 = _3 + 17; _10 = _7 + _14; _11 = (short int) _10; a[i_17] = _11; i_13 = i_17 + 1; ivtmp_29 = ivtmp_30 - 1; if (ivtmp_29 != 0) goto <bb 4>; and much better code. I've added a single-use restriction to the arithmetic result and allow the commutated form to match so we also get at (short)((long long)x + ((long long)y + 12))).