Problem with `unspec' construct
Zack Weinberg
zack@codesourcery.com
Wed Apr 28 20:12:00 GMT 2004
Nitin Jain <nitinj@cse.iitb.ac.in> writes:
> Dear Sir,
>
> Thanks for your reply. It clarify some of my doubt but still i have some
> doubt.
>
> o What i understand is that UNSPEC is used for such operation for which
> there is no direct construct (operation) available in GCC.
Correct.
> o Following is an example of UNSPEC uses. From i386.md
> (define_insn "*cmpfp_2_sf_1"
> [(set (match_operand:HI 0 "register_operand" "=a")
> (unspec:HI
> [(compare:CCFP
> (match_operand:SF 1 "register_operand" "f")
> (match_operand:SF 2 "nonimmediate_operand" "fm"))] 9))]
>
> Here operation corresponding to unspec (9) is `fnstsw' which
> store the FPU status register into a 16 bit memory location or
> the ax register.
>
> But `cmpfp_2_sf_1' is not an standard operation name with
> respect to GCC so there should be some `define_expand' for this
> `define_expr'.
Or a define_split, or a define_peephole2, or an expectation that the
language-independent optimizers will try to merge two other insns and
produce this one. I don't have gcc 3.2 to hand, but in 3.3 this *is*
paired with a define_expand ... not the one you think, though. You're
right that the "cmpsf" expander is involved, but you didn't quote a
very important bit:
{
ix86_compare_op0 = operands[0];
ix86_compare_op1 = operands[1];
DONE;
})
(Code may look slightly different in 3.2.) This is a common idiom for
dealing with compare-and-branch sequences on "non-cc0" targets. All
the cmpsf expander does is save its operands. The DONE; means "don't
emit any insns for this expander." Later, one of the conditional
branch expanders gets called: for instance
(define_expand "beq"
[(set (pc)
(if_then_else (match_dup 1)
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"ix86_expand_branch (EQ, operands[0]); DONE;")
This calls ix86_expand_branch, which does all the work. That function
is in i386.c, and if you look there you will see that it calls
ix86_expand_compare, which calls ix86_expand_fp_compare, which may
construct an insn pattern that will match *cmpfp_2_sf_1. (It does
this by hand. The code could probably be simplified by taking the *
off the name of this pattern and then using gen_cmpfp_2_sf_1.)
...
> Reason behind the confusion is that the syntax of `define_expr' and
> `define_expand' is different. Please clarify this.
Yes, the syntax is different. I'm not sure what you mean here.
> o This doubt is not directly related to the UNSPEC stuff. In a reply to
> one of my doubt, somebody wrote that some `define_insn' in .md file
> have standard name like `addsi3' but rest have non-standard name.
That is correct.
> There is again a distinction between the second class of `define_insn'.
> Names which start with `*' and without `*'. Difference between two is
> that the name of `define_insn' whose name start with `*' is dumped in
> the intermediate code.
That is not correct. All names get dumped in the intermediate code.
The difference between names with an "*" prefix and names without, is
that insns whose names don't start with "*" correspond to
(automatically generated) functions in insn-emit.c, which
machine-dependent code may call. For instance, gen_x86_sahf_1 is
called from ix86_expand_fp_compare.
Insns whose names *do* start with "*" exist solely to match patterns
generated by expanders that don't use DONE; - or splitters - or
peepholes - or machine-independent optimization passes. None of these
use gen_* functions.
zw
More information about the Gcc
mailing list