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