This is what I get with your patch and not mine: neg.w r0 ; 7 neghi2/1 mov.w r0,a0 ; 9 zero_extendhipsi2 add.l a0,r3r1 ; 15 addpsi3/3
Somewhere else, it's getting zero-extended when it should be sign-extended. That's why I was trying to use ssizetype in c-common.c Index: expr.c =================================================================== --- expr.c (revision 140759) +++ expr.c (working copy) @@ -8338,14 +8338,18 @@ expand_expr_real_1 (tree exp, rtx target == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subsubexp1, 0)))) && (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (subsubexp0, 0))) == TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (subsubexp1, 0))))) { tree op0type = TREE_TYPE (TREE_OPERAND (subsubexp0, 0)); enum machine_mode innermode = TYPE_MODE (op0type); - bool zextend_p = TYPE_UNSIGNED (op0type); + bool zextend_p; bool sat_p = TYPE_SATURATING (TREE_TYPE (subsubexp0)); + if (code == POINTER_PLUS_EXPR) + zextend_p = false; + else + zextend_p = TYPE_UNSIGNED (op0type); if (sat_p == 0) this_optab = zextend_p ? umadd_widen_optab : smadd_widen_optab; else this_optab = zextend_p ? usmadd_widen_optab : ssmadd_widen_optab; if (mode == GET_MODE_2XWIDER_MODE (innermode)