Ok, here's where it's getting expanded: #12 0x081e2805 in convert_modes (mode=PSImode, oldmode=HImode, x=0xb7f63450, unsignedp=1) at ../../gcc/gcc/expr.c:859 #13 0x0831f83a in expand_binop_directly (mode=945, binoptab=0x8824de0, op0=0xb7f63410, op1=0xb7f63450, target=0xb7f63440, unsignedp=<value optimized out>, methods=OPTAB_LIB_WIDEN, last=0xb7ef16c0) at ../../gcc/gcc/optabs.c:1488 #14 0x0831aa62 in expand_binop (mode=PSImode, binoptab=0x8824de0, op0=0xb7f63410, op1=0xb7f63450, target=0xb7f63440, unsignedp=1, methods=OPTAB_LIB_WIDEN) at ../../gcc/gcc/optabs.c:1601 #15 0x0821cb22 in expand_expr_real_1 (exp=0xb7ef160c, target=0xb7f63440, tmode=PSImode, modifier=EXPAND_NORMAL, alt_rtl=0x0) at ../../gcc/gcc/expr.c:9452
At #15 the type of the target is used to decide if the math is signed or unsigned, so adding a signed HI to an unsigned PSI results in a zero extend. The patch you added was for the multiply-and-add case, such as "int *p += 1" but it's skipped if there's no multiply (char *p).