On Sun, Aug 5, 2012 at 12:47 AM, Richard Sandiford <rdsandif...@googlemail.com> wrote: > For the record, I can't approve this, but... > > "H.J. Lu" <hjl.to...@gmail.com> writes: >> i386,md has >> >> (define_expand "extzv" >> [(set (match_operand:SI 0 "register_operand") >> (zero_extract:SI (match_operand 1 "ext_register_operand") >> (match_operand:SI 2 "const8_operand") >> (match_operand:SI 3 "const8_operand")))] >> "" >> >> and mode_for_extraction picks word_mode for operand 1 since >> its mode is VOIDmode. This patch changes mode_for_extraction >> to return the mode of operand 1 if the pattern accepts any mode. >> I added *jcc_btsi_mask_2 since combine now tries a different >> pattern, which leads to test failures on gcc.target/i386/bt-mask-1.c >> and gcc.target/i386/bt-mask-2. I didn't update *jcc_btsi_mask_1 >> instead since I am not sure if it is used elsewhere. Tested on >> Linux/x86-64 and Linux/x32. OK for trunk? > > the mode of the extraction operand is defined to be word_mode > for registers (see md.texi), so that at least would need to > be updated. But I'm not convinced that the wanted_inner_mode here: > > if (! in_dest && unsignedp > - && mode_for_extraction (EP_extzv, -1) != MAX_MACHINE_MODE) > + && mode_for_extraction (EP_extzv, -1, VOIDmode) != MAX_MACHINE_MODE) > { > - wanted_inner_reg_mode = mode_for_extraction (EP_extzv, 1); > - pos_mode = mode_for_extraction (EP_extzv, 3); > - extraction_mode = mode_for_extraction (EP_extzv, 0); > + wanted_inner_reg_mode = mode_for_extraction (EP_extzv, 1, > + inner_mode); > + pos_mode = mode_for_extraction (EP_extzv, 3, VOIDmode); > + extraction_mode = mode_for_extraction (EP_extzv, 0, VOIDmode); > } > > is right. inner_mode is the mode of the thing we're extracting, > which doesn't ncessarily have anything to do with what the ext* > patterns support. > > FWIW, in reply to your force_to_mode message, gen_lowpart_for_combine > looks a bit odd: > > if (omode == imode) > return x; > > /* Return identity if this is a CONST or symbolic reference. */ > if (omode == Pmode > && (GET_CODE (x) == CONST > || GET_CODE (x) == SYMBOL_REF > || GET_CODE (x) == LABEL_REF)) > return x; > > So if we know the modes are different, we nevertheless return the > original mode for CONST, SYMBOL_REF or LABEL_REF. Surely the caller > isn't going to be expecting that? If we're not prepared to change > the mode to the one that the caller asked for then I think we should > goto fail instead. > > I don't know if you're hitting that or not. > > Richard
Yes, I did Breakpoint 5, gen_lowpart_for_combine (omode=DImode, x=0x7ffff1b03440) at /export/gnu/import/git/gcc-misc/gcc/combine.c:10778 10778 { (const:SI (plus:SI (symbol_ref:SI ("tmp2") <var_decl 0x7ffff1997140 tmp2>) (const_int 99452 [0x1847c]))) (gdb) c Continuing. Breakpoint 5, gen_lowpart_for_combine (omode=DImode, x=0x7ffff1b03440) at /export/gnu/import/git/gcc-misc/gcc/combine.c:10778 10778 { (const:SI (plus:SI (symbol_ref:SI ("tmp2") <var_decl 0x7ffff1997140 tmp2>) (const_int 99452 [0x1847c]))) (gdb) bt #0 gen_lowpart_for_combine (omode=DImode, x=0x7ffff1b03440) at /export/gnu/import/git/gcc-misc/gcc/combine.c:10778 #1 0x0000000000c83805 in gen_lowpart_or_truncate (x=0x7ffff1b03440, mode=DImode) at /export/gnu/import/git/gcc-misc/gcc/combine.c:8110 #2 force_to_mode (x=0x7ffff1b02cd8, mode=DImode, mask=<optimized out>, just_select=<optimized out>) at /export/gnu/import/git/gcc-misc/gcc/combine.c:8389 #3 0x0000000000c8458a in make_extraction (mode=SImode, inner=0x7ffff1b02cd8, pos=2, pos_rtx=<optimized out>, len=2, unsignedp=1, in_dest=<optimized out>, in_compare=0) at /export/gnu/import/git/gcc-misc/gcc/combine.c:7480 #4 0x0000000000c86f9c in make_compound_operation (x=x@entry=0x7ffff1b02d68, in_code=in_code@entry=SET) at /export/gnu/import/git/gcc-misc/gcc/combine.c:7863 #5 0x0000000000c89924 in simplify_set (x=0x7ffff1af7c78) at /export/gnu/import/git/gcc-misc/gcc/combine.c:6539 #6 combine_simplify_rtx (x=0x7ffff1af7c78, op0_mode=VOIDmode, in_dest=in_dest@entry=0, in_cond=in_cond@entry=0) at /export/gnu/import/git/gcc-misc/gcc/combine.c:5971 #7 0x0000000000c8bd1b in subst (x=<optimized out>, from=<optimized out>, to=<optimized out>, in_dest=0, in_cond=0, unique_copy=0) at /export/gnu/import/git/gcc-misc/gcc/combine.c:5301 #8 0x0000000000c8b8ab in subst (x=0x7ffff1aea870, from=0x7ffff1afc880, ---Type <return> to continue, or q <return> to quit--- to=0x7ffff1b02cd8, in_dest=0, in_cond=0, unique_copy=0) at /export/gnu/import/git/gcc-misc/gcc/combine.c:5165 #9 0x0000000000c8f875 in try_combine (i3=i3@entry=0x7ffff1afe5a0, i2=i2@entry=0x7ffff1afe558, i1=<optimized out>, i0=<optimized out>, i0@entry=0x0, new_direct_jump_p=new_direct_jump_p@entry=0x7fffffffdb64, last_combined_insn=last_combined_insn@entry=0x7ffff1afe5a0) at /export/gnu/import/git/gcc-misc/gcc/combine.c:3260 #10 0x0000000000c94673 in combine_instructions (nregs=<optimized out>, f=<optimized out>) at /export/gnu/import/git/gcc-misc/gcc/combine.c:1265 #11 rest_of_handle_combine () at /export/gnu/import/git/gcc-misc/gcc/combine.c:13948 #12 0x0000000000824755 in execute_one_pass ( pass=pass@entry=0x135aae0 <pass_combine>) at /export/gnu/import/git/gcc-misc/gcc/passes.c:2158 #13 0x0000000000824b15 in execute_pass_list (pass=0x135aae0 <pass_combine>) at /export/gnu/import/git/gcc-misc/gcc/passes.c:2213 #14 0x0000000000824b27 in execute_pass_list ( pass=0x1355d20 <pass_rest_of_compilation>) at /export/gnu/import/git/gcc-misc/gcc/passes.c:2214 #15 0x0000000000610fb8 in expand_function (node=0x7ffff1995750) at /export/gnu/import/git/gcc-misc/gcc/cgraphunit.c:1610 #16 0x0000000000612df4 in expand_all_functions () at /export/gnu/import/git/gcc-misc/gcc/cgraphunit.c:1715 ---Type <return> to continue, or q <return> to quit--- #17 compile () at /export/gnu/import/git/gcc-misc/gcc/cgraphunit.c:2013 #18 0x00000000006133b5 in finalize_compilation_unit () at /export/gnu/import/git/gcc-misc/gcc/cgraphunit.c:2090 #19 0x0000000000506b90 in c_write_global_declarations () at /export/gnu/import/git/gcc-misc/gcc/c/c-decl.c:10116 #20 0x00000000008c5325 in compile_file () at /export/gnu/import/git/gcc-misc/gcc/toplev.c:560 #21 0x00000000008c6eb8 in do_compile () at /export/gnu/import/git/gcc-misc/gcc/toplev.c:1863 #22 toplev_main (argc=17, argv=0x7fffffffdde8) at /export/gnu/import/git/gcc-misc/gcc/toplev.c:1939 #23 0x0000003c88221735 in __libc_start_main () from /lib64/libc.so.6 #24 0x00000000004e9f41 in _start () This patch: diff --git a/gcc/combine.c b/gcc/combine.c index a07c046..b9a3589 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -10784,12 +10784,30 @@ gen_lowpart_for_combine (enum machine_mode omode, rtx x) if (omode == imode) return x; - /* Return identity if this is a CONST or symbolic reference. */ - if (omode == Pmode - && (GET_CODE (x) == CONST - || GET_CODE (x) == SYMBOL_REF - || GET_CODE (x) == LABEL_REF)) - return x; + if (omode == Pmode) + { + /* Return identity if this is a symbolic reference. */ + if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF) + return x; + + /* Return identity for CONST unless this is a PLUS of 2 constant + operands. */ + if (GET_CODE (x) == CONST) + { + rtx y = XEXP (x, 0); + if (GET_CODE (y) == PLUS + && ((CONST_INT_P (XEXP (y, 1)) + && (GET_CODE (XEXP (y, 0)) == CONST + || GET_CODE (XEXP (y, 0)) == SYMBOL_REF + || GET_CODE (XEXP (y, 0)) == LABEL_REF)) + || (CONST_INT_P (XEXP (y, 1)) + && (GET_CODE (XEXP (y, 0)) == CONST + || GET_CODE (XEXP (y, 0)) == SYMBOL_REF + || GET_CODE (XEXP (y, 0)) == LABEL_REF)))) + goto fail; + return x; + } + } /* We can only support MODE being wider than a word if X is a constant integer or has a mode the same size. */ works for the testcase. -- H.J.