public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* Replacing certain operations with function calls
@ 2009-09-01 14:27 Jean Christophe Beyler
  2009-09-01 16:35 ` Ian Lance Taylor
  0 siblings, 1 reply; 10+ messages in thread
From: Jean Christophe Beyler @ 2009-09-01 14:27 UTC (permalink / raw)
  To: gcc

Dear all,

I have been also been looking into how to generate a function call for
certain operations. I've looked at various other targets for a similar
problem/solution but have not seen anything. On my target
architecture, we have certain optimized versions of the multiplication
for example.

I wanted to replace certain mutliplications with a function call. The
solution I found was to do perform a FAIL on the define_expand of the
multiplication for these cases. This forces the compiler to generate a
function call to __multdi3.

I then go in the define_expand of the function call and check the
symbol_ref to see what function is called. I can then modify the call
at that point.

My question is: is this a good approach or is there another solution
that you would use?

Thanks again for your time,
Jean Christophe Beyler

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Replacing certain operations with function calls
  2009-09-01 14:27 Replacing certain operations with function calls Jean Christophe Beyler
@ 2009-09-01 16:35 ` Ian Lance Taylor
  2009-09-01 18:31   ` Jean Christophe Beyler
  0 siblings, 1 reply; 10+ messages in thread
From: Ian Lance Taylor @ 2009-09-01 16:35 UTC (permalink / raw)
  To: Jean Christophe Beyler; +Cc: gcc

Jean Christophe Beyler <jean.christophe.beyler@gmail.com> writes:

> I have been also been looking into how to generate a function call for
> certain operations. I've looked at various other targets for a similar
> problem/solution but have not seen anything. On my target
> architecture, we have certain optimized versions of the multiplication
> for example.
>
> I wanted to replace certain mutliplications with a function call. The
> solution I found was to do perform a FAIL on the define_expand of the
> multiplication for these cases. This forces the compiler to generate a
> function call to __multdi3.
>
> I then go in the define_expand of the function call and check the
> symbol_ref to see what function is called. I can then modify the call
> at that point.
>
> My question is: is this a good approach or is there another solution
> that you would use?

I think that what you describe will work.  I would probably generate a
call to a builtin function in the define_expand.  Look for the way
targets use init_builtins and expand_builtin.  Normally expand_builtin
expands to some target-specific RTL, but it can expand to a function
call too.

Ian

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Replacing certain operations with function calls
  2009-09-01 16:35 ` Ian Lance Taylor
@ 2009-09-01 18:31   ` Jean Christophe Beyler
  2009-09-01 22:20     ` Jean Christophe Beyler
  0 siblings, 1 reply; 10+ messages in thread
From: Jean Christophe Beyler @ 2009-09-01 18:31 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc

I have looked at how other targest use the
init_builtins/expand_builtins. Of course, I don't understand
everything there but it seems indeed to be more for generating a
series of instructions instead of a function call. I haven't seen
anything resembling what I want to do.

I had also first thought of going directly in the define_expand and
expanding to the function call I would want. The problem I have is
that it is unclear to me how to handle (set-up) the arguments of the
builtin_function I am trying to define.

To go from no function call to :

- Potentially spill output registers
- Potentially spill scratch registers

- Setup output registers with the operands
- Perform function call
- Copy return to output operand

- Potentially restore scratch registers
- Potentially restore output registers

Seems a bit difficult to do at the define_expand level and might not
generate good code. I guess I could potentially perform a pass in the
tree representation to do what I am looking for but I am not sure that
that is the best solution either.

For the moment, I will continue looking at what you suggest and also
see if my solution works. I see that, for example, the compiler will
not always generate the call I need to change. Therefore, it does seem
that I need another solution than the one I propose.

I'm more and more considering a pass in the middle-end to get what I
need. Do you think this is better?

Thanks for your input,
Jc

On Tue, Sep 1, 2009 at 12:34 PM, Ian Lance Taylor<iant@google.com> wrote:
> Jean Christophe Beyler <jean.christophe.beyler@gmail.com> writes:
>
>> I have been also been looking into how to generate a function call for
>> certain operations. I've looked at various other targets for a similar
>> problem/solution but have not seen anything. On my target
>> architecture, we have certain optimized versions of the multiplication
>> for example.
>>
>> I wanted to replace certain mutliplications with a function call. The
>> solution I found was to do perform a FAIL on the define_expand of the
>> multiplication for these cases. This forces the compiler to generate a
>> function call to __multdi3.
>>
>> I then go in the define_expand of the function call and check the
>> symbol_ref to see what function is called. I can then modify the call
>> at that point.
>>
>> My question is: is this a good approach or is there another solution
>> that you would use?
>
> I think that what you describe will work.  I would probably generate a
> call to a builtin function in the define_expand.  Look for the way
> targets use init_builtins and expand_builtin.  Normally expand_builtin
> expands to some target-specific RTL, but it can expand to a function
> call too.
>
> Ian
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Replacing certain operations with function calls
  2009-09-01 18:31   ` Jean Christophe Beyler
@ 2009-09-01 22:20     ` Jean Christophe Beyler
  2009-09-01 22:26       ` Ian Lance Taylor
  2009-09-02 15:34       ` Richard Henderson
  0 siblings, 2 replies; 10+ messages in thread
From: Jean Christophe Beyler @ 2009-09-01 22:20 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc

Actually, what I've done is probably something in between what you
were suggesting and what I was initially doing. If we consider the
multiplication, I've modified the define_expand for example to:

(define_expand "muldi3"
  [(set (match_operand:DI 0 "register_operand" "")
        (mult:DI (match_operand:DI 1 "register_operand" "")
                 (match_operand:DI 2 "register_operand" "")))]
 ""
 "
 {
        emit_function_call_2args (DImode, DImode, DImode,
\"my_version_of_mull\", operands[0], operands[1], operands[2]);
        DONE;
 }")

and my emit function is:

void
emit_function_call_2args (
                                enum machine_mode return_mode,
                                enum machine_mode arg1_mode,
                                enum machine_mode arg2_mode,
                                const char *fname,
                                rtx op0,
                                rtx op1,
                                rtx op2)
{
     tree id;
     rtx insn;

     /* Move arguments */
     emit_move_insn (gen_rtx_REG (arg1_mode, GP_ARG_FIRST), op1);
     emit_move_insn (gen_rtx_REG (arg2_mode, GP_ARG_FIRST + 1), op2);

     /* Get name */
     id = get_identifier (fname);

     /* Generate call value */
     insn = gen_call_value (
                        gen_rtx_REG (return_mode, 6),
                        gen_rtx_MEM (DImode,
                           gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (id))),
                        GEN_INT (64),
                        NULL
                        );

     /* Annotate the call to say we are using both argument registers */
     use_reg (&CALL_INSN_FUNCTION_USAGE (insn), gen_rtx_REG
(arg1_mode, GP_ARG_FIRST));
     use_reg (&CALL_INSN_FUNCTION_USAGE (insn), gen_rtx_REG
(arg1_mode, GP_ARG_FIRST + 1));

     /* Emit call */
     emit_call_insn (insn);

     /* Set back return to op0 */
     emit_move_insn (op0, gen_rtx_REG (return_mode, GP_RETURN));
}

First off: does this seem correct?

Second, I have a bit of a worry in the case where, if we consider this C code :

bar (a * b, c * d);

it is possible that the compiler would have normally generated this :

mult output1, a, b
mult output2, c, d
call bar

Which would be problematic for my expand system since this would expand into:

mov output1, a
mov output2, b
call internal_mult
mov output1, return_reg

mov output1, c   #Rewriting on output1...
mov output2, d
call internal_mult
mov output2, return_reg

call bar


However, I am unsure this is possible in the expand stage, would the
expand stage automatically have this instead:

mult tmp1, a, b
mult tmp2, c, d

mov output1, tmp1
mov output2, tmp2
call bar

in which case, I know I can do what I am currently doing.

Thanks again for your help and I apologize for these basic questions...
Jc


On Tue, Sep 1, 2009 at 2:30 PM, Jean Christophe
Beyler<jean.christophe.beyler@gmail.com> wrote:
> I have looked at how other targest use the
> init_builtins/expand_builtins. Of course, I don't understand
> everything there but it seems indeed to be more for generating a
> series of instructions instead of a function call. I haven't seen
> anything resembling what I want to do.
>
> I had also first thought of going directly in the define_expand and
> expanding to the function call I would want. The problem I have is
> that it is unclear to me how to handle (set-up) the arguments of the
> builtin_function I am trying to define.
>
> To go from no function call to :
>
> - Potentially spill output registers
> - Potentially spill scratch registers
>
> - Setup output registers with the operands
> - Perform function call
> - Copy return to output operand
>
> - Potentially restore scratch registers
> - Potentially restore output registers
>
> Seems a bit difficult to do at the define_expand level and might not
> generate good code. I guess I could potentially perform a pass in the
> tree representation to do what I am looking for but I am not sure that
> that is the best solution either.
>
> For the moment, I will continue looking at what you suggest and also
> see if my solution works. I see that, for example, the compiler will
> not always generate the call I need to change. Therefore, it does seem
> that I need another solution than the one I propose.
>
> I'm more and more considering a pass in the middle-end to get what I
> need. Do you think this is better?
>
> Thanks for your input,
> Jc
>
> On Tue, Sep 1, 2009 at 12:34 PM, Ian Lance Taylor<iant@google.com> wrote:
>> Jean Christophe Beyler <jean.christophe.beyler@gmail.com> writes:
>>
>>> I have been also been looking into how to generate a function call for
>>> certain operations. I've looked at various other targets for a similar
>>> problem/solution but have not seen anything. On my target
>>> architecture, we have certain optimized versions of the multiplication
>>> for example.
>>>
>>> I wanted to replace certain mutliplications with a function call. The
>>> solution I found was to do perform a FAIL on the define_expand of the
>>> multiplication for these cases. This forces the compiler to generate a
>>> function call to __multdi3.
>>>
>>> I then go in the define_expand of the function call and check the
>>> symbol_ref to see what function is called. I can then modify the call
>>> at that point.
>>>
>>> My question is: is this a good approach or is there another solution
>>> that you would use?
>>
>> I think that what you describe will work.  I would probably generate a
>> call to a builtin function in the define_expand.  Look for the way
>> targets use init_builtins and expand_builtin.  Normally expand_builtin
>> expands to some target-specific RTL, but it can expand to a function
>> call too.
>>
>> Ian
>>
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Replacing certain operations with function calls
  2009-09-01 22:20     ` Jean Christophe Beyler
@ 2009-09-01 22:26       ` Ian Lance Taylor
  2009-09-01 22:35         ` Jean Christophe Beyler
  2009-09-02 15:34       ` Richard Henderson
  1 sibling, 1 reply; 10+ messages in thread
From: Ian Lance Taylor @ 2009-09-01 22:26 UTC (permalink / raw)
  To: Jean Christophe Beyler; +Cc: gcc

Jean Christophe Beyler <jean.christophe.beyler@gmail.com> writes:

> First off: does this seem correct?

Awkward though it is, it may be more reliable to build a small tree here
and pass it to expand_call.  This assumes that you want to use the
standard ABI when calling this function.

Then your second issue would go away.

Ian

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Replacing certain operations with function calls
  2009-09-01 22:26       ` Ian Lance Taylor
@ 2009-09-01 22:35         ` Jean Christophe Beyler
  2009-09-01 22:42           ` Jean Christophe Beyler
  2009-09-01 22:44           ` Ian Lance Taylor
  0 siblings, 2 replies; 10+ messages in thread
From: Jean Christophe Beyler @ 2009-09-01 22:35 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc

I don't think I quite understand what you're meaning. I want to use
the standard ABI, basically I want to transform certain operations
into function calls.

In regard to what you said, do you mean I should build the tree before
the expand pass, by writing a new pass that will work on the trees
instead of rtx?

Otherwise, I fail to see how that is different to what I'm already
doing. Would you have an example?

Thanks,
Jc

PS: Although when I look at what GCC generates at the expand stage, it
really does seem that he first generates the calculation of the
parameters in pseudo-registers and then moves them to the actual
output registers. It's the next phases that will combine the two to
save a move.

On Tue, Sep 1, 2009 at 6:26 PM, Ian Lance Taylor<iant@google.com> wrote:
> Jean Christophe Beyler <jean.christophe.beyler@gmail.com> writes:
>
>> First off: does this seem correct?
>
> Awkward though it is, it may be more reliable to build a small tree here
> and pass it to expand_call.  This assumes that you want to use the
> standard ABI when calling this function.
>
> Then your second issue would go away.
>
> Ian
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Replacing certain operations with function calls
  2009-09-01 22:35         ` Jean Christophe Beyler
@ 2009-09-01 22:42           ` Jean Christophe Beyler
  2009-09-01 22:44           ` Ian Lance Taylor
  1 sibling, 0 replies; 10+ messages in thread
From: Jean Christophe Beyler @ 2009-09-01 22:42 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc

Finally, I guess the one thing I can do is simply generate
pseudo_registers and copy all my registers into the pseudos before the
call I make.

Then I do my expand like I showed above.

And finally, move everything back.

Later passes will remove anything that was not needed, anything that
was will be kept. This could be a solution to the second issue but
I'll wait to understand what you meant first.

Jc

On Tue, Sep 1, 2009 at 6:35 PM, Jean Christophe
Beyler<jean.christophe.beyler@gmail.com> wrote:
> I don't think I quite understand what you're meaning. I want to use
> the standard ABI, basically I want to transform certain operations
> into function calls.
>
> In regard to what you said, do you mean I should build the tree before
> the expand pass, by writing a new pass that will work on the trees
> instead of rtx?
>
> Otherwise, I fail to see how that is different to what I'm already
> doing. Would you have an example?
>
> Thanks,
> Jc
>
> PS: Although when I look at what GCC generates at the expand stage, it
> really does seem that he first generates the calculation of the
> parameters in pseudo-registers and then moves them to the actual
> output registers. It's the next phases that will combine the two to
> save a move.
>
> On Tue, Sep 1, 2009 at 6:26 PM, Ian Lance Taylor<iant@google.com> wrote:
>> Jean Christophe Beyler <jean.christophe.beyler@gmail.com> writes:
>>
>>> First off: does this seem correct?
>>
>> Awkward though it is, it may be more reliable to build a small tree here
>> and pass it to expand_call.  This assumes that you want to use the
>> standard ABI when calling this function.
>>
>> Then your second issue would go away.
>>
>> Ian
>>
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Replacing certain operations with function calls
  2009-09-01 22:35         ` Jean Christophe Beyler
  2009-09-01 22:42           ` Jean Christophe Beyler
@ 2009-09-01 22:44           ` Ian Lance Taylor
  1 sibling, 0 replies; 10+ messages in thread
From: Ian Lance Taylor @ 2009-09-01 22:44 UTC (permalink / raw)
  To: Jean Christophe Beyler; +Cc: gcc

Jean Christophe Beyler <jean.christophe.beyler@gmail.com> writes:

> In regard to what you said, do you mean I should build the tree before
> the expand pass, by writing a new pass that will work on the trees
> instead of rtx?

Oh, sorry, I'm an idiot.  I forgot that you only have RTL at this point.

I would go with what you wrote and see what happens.

Ian

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Replacing certain operations with function calls
  2009-09-01 22:20     ` Jean Christophe Beyler
  2009-09-01 22:26       ` Ian Lance Taylor
@ 2009-09-02 15:34       ` Richard Henderson
  2009-09-02 19:38         ` Jean Christophe Beyler
  1 sibling, 1 reply; 10+ messages in thread
From: Richard Henderson @ 2009-09-02 15:34 UTC (permalink / raw)
  To: Jean Christophe Beyler; +Cc: Ian Lance Taylor, gcc

On 09/01/2009 03:20 PM, Jean Christophe Beyler wrote:
> First off: does this seem correct?

Yes.  Though I do wonder why you are avoiding using the normal libcall 
machinery.  If all you really care about is changing the function name, 
then all you need to do is modify the appropriate optab.  See, for 
instance, arm_init_libfuncs.

But if you need slightly different calling conventions, then this will 
work just fine.  Compare this to the Alpha TFmode routines generated by 
alpha_emit_xfloating_libcall.

> However, I am unsure this is possible in the expand stage, would the
> expand stage automatically have this instead:
>
> mult tmp1, a, b
> mult tmp2, c, d
>
> mov output1, tmp1
> mov output2, tmp2
> call bar

Yes, this is exactly what expand_call does.


r~

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Replacing certain operations with function calls
  2009-09-02 15:34       ` Richard Henderson
@ 2009-09-02 19:38         ` Jean Christophe Beyler
  0 siblings, 0 replies; 10+ messages in thread
From: Jean Christophe Beyler @ 2009-09-02 19:38 UTC (permalink / raw)
  To: Richard Henderson; +Cc: Ian Lance Taylor, gcc

> Yes.  Though I do wonder why you are avoiding using the normal libcall
> machinery.  If all you really care about is changing the function name, then
> all you need to do is modify the appropriate optab.  See, for instance,
> arm_init_libfuncs.

I guess both could work. I had seen the TARGET_INIT_LIB but, when I
had tried playing with it, I got a segmentation fault in the
emit_unop_insn function (for some reason, pat = GEN_FCN (icode) (temp,
op0) was returning NULL). I guessed that either I had another problem
in my MD file that was posing a problem or that I didn't define
everything needed for the libcall system.

This solution worked relatively straight away and is open enough to
allow me to change the implementation later down the road.

When things stabilize, I might go back and move the real function
calls back to the libcall machinery.

>> mult tmp1, a, b
>> mult tmp2, c, d
>>
>> mov output1, tmp1
>> mov output2, tmp2
>> call bar

Ok then I don't foresee a problem with the way I do it.

Thanks again all of you,
Jc

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2009-09-02 19:38 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-09-01 14:27 Replacing certain operations with function calls Jean Christophe Beyler
2009-09-01 16:35 ` Ian Lance Taylor
2009-09-01 18:31   ` Jean Christophe Beyler
2009-09-01 22:20     ` Jean Christophe Beyler
2009-09-01 22:26       ` Ian Lance Taylor
2009-09-01 22:35         ` Jean Christophe Beyler
2009-09-01 22:42           ` Jean Christophe Beyler
2009-09-01 22:44           ` Ian Lance Taylor
2009-09-02 15:34       ` Richard Henderson
2009-09-02 19:38         ` Jean Christophe Beyler

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).