This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: Replacing certain operations with function calls
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
>>
>