returning a double in two registers

I have started to add support for FP in the ARM backend.

According to the ABI, 32 bit floating point numbers should be returned
in R0 and 64bit ones in R0/R1.

I have solved the 32 bit case by inserting bit_converts in LowerRET.
For the 64bit case I considered two options:

1) Creating two nodes. fp_lo and fp_hi. I could then select fmrdh and fmrdl with
(set IntRegs:$dst (bitconvert (fp_hi DFPRegs:$src))) and
(set IntRegs:$dst (bitconvert (fp_lo DFPRegs:$src)))

2) Create a node similar to copytoreg that has two results. This has
the advantage that it is possible to select fmrrd.

I am currently trying to implement 2, but I am not sure how to declare
an instruction that has two results. There are some combined mod/rem
instruction like idivl, but they have fixed defs (EAX, EDX).

I have just committed a partial version that doesn't declare fmrrd as
defining its two integer arguments. Currently this is only used during
returns and the function is marked as defining R0 and R1, so this
shouldn't be a problem,

How can I fix the declaration of fmrrd so that it can be used in other contexts?

Thanks,
Rafael

I have started to add support for FP in the ARM backend.

cool.

According to the ABI, 32 bit floating point numbers should be returned
in R0 and 64bit ones in R0/R1.

Ok.

I have solved the 32 bit case by inserting bit_converts in LowerRET.

Yep.

For the 64bit case I considered two options:

1) Creating two nodes. fp_lo and fp_hi. I could then select fmrdh and fmrdl with
(set IntRegs:$dst (bitconvert (fp_hi DFPRegs:$src))) and
(set IntRegs:$dst (bitconvert (fp_lo DFPRegs:$src)))

Alternatively, you could merge bitconvert into the fp_hi/lo flags. That would make the pattern simpler, and eliminate the need to have to match a bare fp_hi/fp_lo node without the bitconvert.

2) Create a node similar to copytoreg that has two results. This has
the advantage that it is possible to select fmrrd.

I am currently trying to implement 2, but I am not sure how to declare
an instruction that has two results. There are some combined mod/rem
instruction like idivl, but they have fixed defs (EAX, EDX).

Unfortunately, you can't do this elegantly in tblgen. You'd want to create an arm-local node at lowering time, then use custom C++ code to match it. The X86 backend has some examples of how to write the custom matching code, but it's not for the faint of heart.

Extending tblgen to support instructions with multiple results is on the long term todo list, but we probably won't get to it in the near future.

I have just committed a partial version that doesn't declare fmrrd as
defining its two integer arguments. Currently this is only used during
returns and the function is marked as defining R0 and R1, so this
shouldn't be a problem,

How can I fix the declaration of fmrrd so that it can be used in other contexts?

You defined your armfmmrd node as taking three inputs: two integer and one double. Shouldn't it produce two outputs and take one input? If so, you need to write custom c++ matching code. Alternatively, you can avoid this by doing the two pieces separately, as you describe in 1).

-Chris

Alternatively, you could merge bitconvert into the fp_hi/lo flags. That
would make the pattern simpler, and eliminate the need to have to match a
bare fp_hi/fp_lo node without the bitconvert.

good point!

Unfortunately, you can't do this elegantly in tblgen. You'd want to
create an arm-local node at lowering time, then use custom C++ code to
match it. The X86 backend has some examples of how to write the custom
matching code, but it's not for the faint of heart.

I will have a look at it.

Extending tblgen to support instructions with multiple results is on the
long term todo list, but we probably won't get to it in the near future.

You defined your armfmmrd node as taking three inputs: two integer and one
double. Shouldn't it produce two outputs and take one input? If so, you
need to write custom c++ matching code. Alternatively, you can avoid this
by doing the two pieces separately, as you describe in 1).

It should. I have cheated to be able to use tblgen. Since the
instruction is only used with a flag connecting it to a return, I was
hoping that the hack was "safe".

-Chris

Rafael

Probably not. You're depending on the whims of the register allocator here. :slight_smile: Try -regalloc=simple, it will probably break the code.

-Chris