Index: ipa-prop.c =================================================================== --- ipa-prop.c (revision 218133) +++ ipa-prop.c (working copy) @@ -3939,6 +3939,39 @@ ipa_modify_call_arguments (struct cgraph /* Aggregate arguments can have non-invariant addresses. */ if (!base) { + /* ??? If the original aggregate is passed by value, it may + be not aligned on a unit boundary, in which case taking + directly its address below is forbidden. Unfortunately + get_addr_base_and_unit_offset doesn't differentiate its + two failure modes so we need to get our hands dirty. */ + if (!addrof) + { + tree offset; + HOST_WIDE_INT bitsize, bitpos; + machine_mode mode; + int unsignedp, volatilep = 0; + get_inner_reference (prev_base, &bitsize, &bitpos, + &offset, &mode, &unsignedp, + &volatilep, false); + if (bitpos % BITS_PER_UNIT) + { + tree tmp + = create_tmp_reg (TREE_TYPE (prev_base), NULL); + tree *argp + = gimple_call_arg_ptr (stmt, adj->base_index); + gimple tem = gimple_build_assign (tmp, prev_base); + tree vuse = gimple_vuse (stmt); + tree new_vdef = copy_ssa_name (vuse, tem); + gimple_set_vuse (tem, vuse); + gimple_set_vdef (tem, new_vdef); + SET_USE (gimple_vuse_op (stmt), new_vdef); + /* Insert the temporary ahead of every subsequent + adjustment and replace the argument in the call + in case it is referenced more than once. */ + gsi_insert_after (&prev_gsi, tem, GSI_SAME_STMT); + *argp = prev_base = tmp; + } + } base = build_fold_addr_expr (prev_base); off = build_int_cst (adj->alias_ptr_type, adj->offset / BITS_PER_UNIT);