Paolo Bonzini schrieb:
> On 10/29/2010 06:18 PM, Georg Lay wrote:
>> (define_split
>>    [(set (match_operand:SI 0 "register_operand"           "")
>>          (and:SI (match_operand:SI 1 "register_operand"   "")
>>                  (match_operand:SI 2 "const_int_operand"  "")))
>>     (clobber (match_operand:SI 3 "register_operand" ""))]
>>    "..."
>>    [(set (match_dup 3)
>>          (and:SI (match_dup 1)
>>                  (match_dup 4)))
>>     (set (match_dup 0)
>>          (xor:SI (match_dup 3)
>>                  (match_dup 1)))]
> 
> Again, it's not really my field but I think this should be written as
> 
> (define_split
>    [(set (match_operand:SI 0 "register_operand"           "")
>          (and:SI (match_operand:SI 1 "register_operand"   "")
>                  (match_operand:SI 2 "const_int_operand"  "")))
>     (clobber (match_scratch:SI 3 ""))]
>    ""
>    [(set (match_dup 3)
>          (and:SI (match_dup 1)
>                  (match_dup 4)))
>     (set (match_dup 0)
>          (xor:SI (match_dup 3)
>                  (match_dup 1)))]
> 
> and the define_insn should also use match_scratch.  

That would produce
  (set (scratch:SI)
       (and:SI ...

which cannot work.

> I'm looking at config/i386/i386.md, pattern 
> fix_trunc<mode>_i387_fisttp_with_temp and the two following splits.

This pattern doesn't have to get a pseudo. assign_386_stack_local just produces
a stack slot for the intermediate.

> If you do it pre-reload, register allocation should not have any problem
> allocating operands 0 and 3 to the same register.  It sounds to me like
> you're doing your own register allocation using peepholes. :)

This solution works:

Generating a named insn in andsi3-expander as

(define_insn_and_split  "..."
  [(set (match_operand:SI 0 "register_operand"           "")
        (and:SI (match_operand:SI 1 "register_operand"   "")
                (match_operand:SI 2 "const_int_operand"  "")))
   (clobber (match_operand:SI 3 "register_operand"       ""))]
  "...
   && !reload_completed
   && !reload_in_progress"
  {
    gcc_unreachable();
  }
  "&& 1"
  [(set (match_dup 3)
        (and:SI (match_dup 1)
                (match_dup 4)))
   (set (match_dup 0)
        (xor:SI (match_dup 3)
                (match_dup 1)))]
  {
    ...
  })

The insn passes combine unchanged and gets split in split1 as expected :-)

What I do not understand is *why* this works.
The internals "16.16 How to Split Instructions" mention two flavours of insn
splitting: One after reload for the scheduler and one during combine stage, the
latter just doing single_set --> 2 * single_set splits for insns that do *not*
match during combine stage.

However, this insn matches. So the combiner does'n split in accordance with
internals doc. But the opportunity to use split1 is neither mentioned nor
described in the internals.

I observed that the insn gets split in split1 even if the splitter produces more
than two insns and also if optimization is off.

That's nice but can I rely on that behaviour? (As far as -O0 is concerned, I
will emit the special insn just if optimization is turned on, but nevertheless
it would be interesting to know why this works smooth with -O0 as I expected to
run in unrecognizable insn or something like that during reload).

Georg

Reply via email to