[LLVMdev] Passing return values on the stack & storing arbitrary sized integers

Eli Friedman eli.friedman at gmail.com
Tue Aug 21 02:19:11 PDT 2012


On Tue, Aug 21, 2012 at 1:25 AM, Fabian Scheler
<fabian.scheler at gmail.com> wrote:
> 2012/8/20 Eli Friedman <eli.friedman at gmail.com>:
>> On Mon, Aug 20, 2012 at 12:01 AM, Fabian Scheler
>> <fabian.scheler at gmail.com> wrote:
>>> Hi Eli,
>>>
>>>>>>> 2. Storing arbitrary sized integers
>>>>>>>
>>>>>>> The testcase "test/CodeGen/Generic/APIntLoadStore.ll" checks for
>>>>>>> loading/storing e.g. i33 integers from/into global variable. The
>>>>>>> questions are the same as regarding feature 1: How important is this
>>>>>>> feature? Is it save to ignore it? Is there some guide how to implement
>>>>>>> this?
>>>>>>
>>>>>> If you're using the LLVM CodeGen infrastructure and have everything
>>>>>> else implemented correctly, this should be taken care of for you.  We
>>>>>> have infrastructure generally referred to as "legalization" that will
>>>>>> transform this into something sane for your target automatically.  I
>>>>>> would suggest not ignoring this because the optimizers will
>>>>>> occasionally generate unusual loads and stores.
>>>>>
>>>>> Hm, my problem is that the TriCore does not really support i64 only
>>>>> paired 32.bit registers, but I need such a register class as some
>>>>> instructions require them. So, the Legalizer thinks i64-instructions
>>>>> are legal and integer types above i32 are not legalized automatically.
>>>>> For the most operations I used setOperationAction, setLoadExtAction,
>>>>> ... and now I have to handle loads/stores for i33. Maybe you can guide
>>>>> me, where I shall look at inside LLVM how to do that.
>>>>
>>>> I'm not entirely sure why, but this seems to be a very frequent
>>>> mistake: don't mark i64 legal unless you actually have i64 registers.
>>>> Lying to the legalizer creates extra work for your target, and you're
>>>> using codepaths which aren't well tested.  There are better ways to
>>>> model a pair of i32 registers; if you have some case you're having
>>>> trouble modeling, please ask.
>>>
>>> well, I did not implement the back-end at first, I am currently only
>>> adapting it to LLVM 3.1, so I don't know if it was possible to model
>>> the TriCore ISA in a better way. The TriCore supports register pairs
>>> of two adjacent (even,odd) registers forming one 64-bit registers. A
>>> few operation of the TriCore exploit these register pairs:
>>> multiplication, for instance, places its result in on of those
>>> register pairs, it it possible to load/store such register pairs
>>> directly from/to memory and the calling conventions take them into
>>> account, too. Everything else has to be done using 32-bit registers
>>> and instructions.
>>>
>>> In the first place, these registers pairs were only present in the
>>> tablegen descriptions and were only used to define the
>>> multiplication-instruction. Furthermore, the calling conventions were
>>> tweaked to be compatible to those specified by the TriCore EABI
>>> (64-bit arguments have to passed in an appropriate register pair).
>>> Everything worked quite fine. When moving to LLVM 3.1, however, the
>>> generic code generation framework complained that it knew nothing
>>> about those registers pairs that were only described in tablegen when
>>> selecting the multiplication-instruction. So, I found no other
>>> solution than to add these register pairs as i64-registers.
>>>
>>> If there is a more convenient solution for this setup, I would be
>>> really glad to learn about it :-)
>>
>> Not sure exactly what's going wrong, but if the Tablegen selection
>> code doesn't work correctly for a few unusual instructions, you can
>> write out the code by hand in your target's implementation of
>> SelectionDAGISel::Select.
>
> OK, I rechecked my problem and I hope I can now describe it more precisely:
>
> 1. The TriCore supports register pairs forming 64.bit registers. These
> 64-bit registers are defined like this and form the "ER" register
> class:
>
> def E0  : TriCoreRegWithSubregs<0,  "e0",  [D0,  D1]>,  DwarfRegNum<[32]>;
> ...
> def E14 : TriCoreRegWithSubregs<14, "e14", [D14, D15]>, DwarfRegNum<[39]>;
>
> 2. The TriCore has some instructions that make use of an arbitrary
> register pair, for example integer division (consisting of a single
> DVINIT and several DVSTEPs):
>
> def DVINIT_Urr  : RrInstr<0x4b, 0x0a, (outs ER:$c), (ins DR:$a,
> DR:$b), "dvinit.u\t$c, $a, $b",  []>;
> def DVSTEP_Urrr : RrrInstr<0x6b, 0x0e, (outs ER:$c), (ins ER:$d,
> DR:$b), "dvstep.u\t$c, $d, $b", []>;
>
> def : Pat<(sdiv DR:$a, DR:$b),
>               (EXTRACT_SUBREG
>                 (DVSTEPrrr
>                   (DVSTEPrrr
>                     (DVSTEPrrr
>                       (DVSTEPrrr (DVINITrr DR:$a, DR:$b), DR:$b),
>                       DR:$b),
>                     DR:$b),
>                   DR:$b),
>                 sub_even)>;
>
> 3. These are selected in a simple testcase:
>
> define i32 @div(i32 %a, i32 %b) nounwind readnone {
> entry:
>   %div = sdiv i32 %a, %b                          ; <i32> [#uses=1]
>   ret i32 %div
> }
>
> 4. Instruction Scheduling calls GetCostForDef (in
> ScheduleDAGRRList.cpp) when hitting the EXTRACT_SUBREG-Node introduced
> by the Pattern above.
>
> 5. GetCostForDef crashes here, as getRepRegClassFor(VT /* == MVT::i64
> */) returns NULL:
>
> RegClass = TLI->getRepRegClassFor(VT)->getID();

This isn't really my area of expertise, but I think you're messing up
your RegisterClass definition.  Look at how ARM defines DTriple.

-Eli



More information about the llvm-dev mailing list