On Tue, Nov 25, 2014 at 7:04 AM, Richard Biener <richard.guent...@gmail.com> wrote: > On Tue, Nov 25, 2014 at 4:01 PM, Richard Biener > <richard.guent...@gmail.com> wrote: >> On Tue, Nov 25, 2014 at 1:57 PM, H.J. Lu <hongjiu...@intel.com> wrote: >>> Hi, >>> >>> The enclosed testcase fails on x86 when compiled with -Os since we pass >>> a byte parameter with a byte load in caller and read it as an int in >>> callee. The reason it only shows up with -Os is x86 backend encodes >>> a byte load with an int load if -O isn't used. When a byte load is >>> used, the upper 24 bits of the register have random value for none >>> WORD_REGISTER_OPERATIONS targets. >>> >>> It happens because setup_incoming_promotions in combine.c has >>> >>> /* The mode and signedness of the argument before any promotions >>> happen >>> (equal to the mode of the pseudo holding it at that stage). */ >>> mode1 = TYPE_MODE (TREE_TYPE (arg)); >>> uns1 = TYPE_UNSIGNED (TREE_TYPE (arg)); >>> >>> /* The mode and signedness of the argument after any source language >>> and >>> TARGET_PROMOTE_PROTOTYPES-driven promotions. */ >>> mode2 = TYPE_MODE (DECL_ARG_TYPE (arg)); >>> uns3 = TYPE_UNSIGNED (DECL_ARG_TYPE (arg)); >>> >>> /* The mode and signedness of the argument as it is actually passed, >>> after any TARGET_PROMOTE_FUNCTION_ARGS-driven ABI promotions. */ >>> mode3 = promote_function_mode (DECL_ARG_TYPE (arg), mode2, &uns3, >>> TREE_TYPE (cfun->decl), 0); >>> >>> while they are actually passed in register by assign_parm_setup_reg in >>> function.c: >>> >>> /* Store the parm in a pseudoregister during the function, but we may >>> need to do it in a wider mode. Using 2 here makes the result >>> consistent with promote_decl_mode and thus expand_expr_real_1. */ >>> promoted_nominal_mode >>> = promote_function_mode (data->nominal_type, data->nominal_mode, >>> &unsignedp, >>> TREE_TYPE (current_function_decl), 2); >>> >>> where nominal_type and nominal_mode are set up with TREE_TYPE (parm) >>> and TYPE_MODE (nominal_type). TREE_TYPE here is >> >> I think the bug is here, not in combine.c. Can you try going back in history >> for both snippets and see if they matched at some point? > > Oh, and note that I think DECL_ARG_TYPE is sth dangerous - it's meant > to be a source language "ABI" kind-of-thing. Or rather an optimization > hit. For example in C when integral promotions happen to call arguments > this can be used to optimize sign-/zero-extensions in the callee. Unless > something else overrides this (like the target which specifies the real ABI). > IIRC. >
PROMOTE_MODE is a performance hint, not an ABI requirement. i386.h has #define PROMOTE_MODE(MODE, UNSIGNEDP, TYPE) \ do { \ if (((MODE) == HImode && TARGET_PROMOTE_HI_REGS) \ || ((MODE) == QImode && TARGET_PROMOTE_QI_REGS)) \ (MODE) = SImode; \ } while (0) We may promote QI/HI to SI, depending on optimization. On the other hand, TARGET_PROMOTE_FUNCTION_MODE is determined by psABI. I am enclosing the missing ChangeLog entries. -- H.J. --- gcc/ PR rtl-optimization/64037 * combine.c (setup_incoming_promotions): Pass the argument before any promotions happen to promote_function_mode. gcc/testsuite/ PR rtl-optimization/64037 * g++.dg/pr64037.C: New test.