I've added a new define_expand for msp430 to handle "mulhisi", but when testing the changes, some builtin tests (e.g. builtin-arith-overflow-{1,5,p-1}.c) fail.
I've narrowed a test case down to: void foo (unsigned int r, unsigned int y) { __builtin_umul_overflow ((unsigned int) (-1), y, &r); } > msp430-elf-gcc -S tester.c -O0 tester.c: In function 'foo': tester.c:4:1: error: unrecognizable insn: 4 | } | ^ (insn 16 15 17 2 (set (reg:HI 32) (const_int 65535 [0xffff])) "tester.c":3:3 -1 (nil)) during RTL pass: vregs dump file: tester.c.234r.vregs tester.c:4:1: internal compiler error: in extract_insn, at recog.c:2311 This is clearly a very simple instruction that should be handled by "movhi": (define_insn "movhi" [(set (match_operand:HI 0 "msp_nonimmediate_operand" "=r,rYs,rm") (match_operand:HI 1 "msp_general_operand" "N,riYs,rmi"))] "msp_general_operand" is an ior of general_operand and a volatile memory operand. When debugging this I noticed that "general_operand" is returning 0 for (const_int 65535 [0xffff]), i.e. it has not validated this operand: > Breakpoint 3, general_operand (op=op@entry=0x7ffff7309740, > mode=mode@entry=E_HImode) at ../../gcc/recog.c:959 959 { > (gdb) call debug_rtx(op) > (const_int 65535 [0xffff]) > Run till exit from #0 0x0000000000b56da4 in general_operand > (op=op@entry=0x7ffff7309740, mode=<optimised out>, mode@entry=E_HImode) at > ../../gcc/recog.c:974 > 0x0000000001194400 in msp430_general_operand (op=0x7ffff7309740, > mode=mode@entry=E_HImode) at ../../gcc/config/msp430/predicates.md:37 > 37 ; general_operand refuses to match volatile memory refs. > Value returned is $3 = 0 trunc_int_for_mode changes 65535 to -1, which I think is the cause of the problem: > Run till exit from #0 trunc_int_for_mode (c=65535, mode=mode@entry=E_HImode) > at ../../gcc/explow.c:55 > 0x0000000000b56da4 in general_operand (op=op@entry=0x7ffff7309740, > mode=<optimised out>, mode@entry=E_HImode) at ../../gcc/recog.c:974 > 974 && trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op)) > Value returned is $2 = -1 So this results in the following clause evaluating to true and general_operand returning 0: if (CONST_INT_P (op) && mode != VOIDmode && trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op)) return 0; I haven't narrowed down where the (const_int 65535) is being generated. I suspect if MODE was VOIDmode we wouldn't have this problem. I've noticed that normally a constant like would normally show as (const_int -1). I guess the bug is wherever the (const_int 65535) is generated, it should be -1 sign extend to a HWI. That is based on this statement from the docs: Constants generated for modes with fewer bits than in HOST_WIDE_INT must be sign extended to full width (e.g., with gen_int_mode). For constants for modes with more bits than in HOST_WIDE_INT the implied high order bits of that con- stant are copies of the top bit. Note however that values are neither inherently signed nor inherently unsigned; where necessary, signedness is determined by the rtl operation instead. Can anyone offer any further insight? Do I just need to track down what is generating this const_int and fix that? Could it be some edge-case interaction because it is an argument to a builtin? Thanks, Jozef