[PATCH] D11438: Fix x86_64 fp128 calling convention
Xinliang David Li via llvm-commits
llvm-commits at lists.llvm.org
Mon Oct 19 16:23:23 PDT 2015
Your newly proposed change for getCommonSubClass looks cleaner to me -- it
does not change the hasType guarantee of the existing implementation.
David
On Fri, Oct 16, 2015 at 4:54 PM, Chih-hung Hsieh <chh at google.com> wrote:
> Somehow a few previous emails were not seen athttp://reviews.llvm.org/D11438
> Does anyone know the cause of that?
>
>
> As promised in my previous email, I gave more thought about changing
> getCommonSubClass instead of InstrEmitter.cpp. The problem was that
> getCommonSubClass returns FR128 register class as the common sub class
> with VR128. But FR128 does not contain v16i8 and 128-bit vector types.
> I tried to add 128-bit vector types into FR128. That caused many other
> errors that I doubt is the right direction.
>
> Hence, it seems to me that my best solution now is to take care of
> getCommonSubClass inside EmitCopyFromReg of InstrEmitter.cpp,
> but not to change other users of getCommonSubClass.
> The other users do not look like having clear requirement of
> something like ComRC->hasType(VT).
>
> The best alternative I have to my current patch is shown bellow.
> (1) Almost no change to InstrEmitter.cpp, which just passes the VT.SimpleTy
> to getCommonSubClass, which should then guarantee that returned
> ComRC will have type VT.
> (2) Change getCommonSubclass to take one more parameter with default
> value. So other callers do not need any change. When the extra
> parameter is not MVT::SimpleValueType::Any, returns found
> common sub class only if it contains the given SimpleValueType.
> (3) getCommonSubclass calls firstCommonClass but it's not the only caller.
> So change firstCommonClass similarly.
>
> Well, this is actually more change than my current patch.
> So, I am still in favor of my current patch.
>
>
> Index: lib/CodeGen/SelectionDAG/InstrEmitter.cpp
> ===================================================================
> --- lib/CodeGen/SelectionDAG/InstrEmitter.cpp (revision 247905)
> +++ lib/CodeGen/SelectionDAG/InstrEmitter.cpp (working copy)
> @@ -139,7 +139,7 @@
> UseRC = RC;
> else if (RC) {
> const TargetRegisterClass *ComRC =
> - TRI->getCommonSubClass(UseRC, RC);
> + TRI->getCommonSubClass(UseRC, RC, VT.SimpleTy);
> // If multiple uses expect disjoint register classes, we emit
> // copies in AddRegisterOperand.
> if (ComRC)
>
> Index: include/llvm/Target/TargetRegisterInfo.h
> ===================================================================
> --- include/llvm/Target/TargetRegisterInfo.h (revision 247905)
> +++ include/llvm/Target/TargetRegisterInfo.h (working copy)
> @@ -620,10 +620,13 @@
> }
>
> /// getCommonSubClass - find the largest common subclass of A and B. Return
> - /// NULL if there is no common subclass.
> + /// NULL if there is no common subclass. The common subclass should contain
> + /// simple value type SVT if it is not the Any type.
> const TargetRegisterClass *
> getCommonSubClass(const TargetRegisterClass *A,
> - const TargetRegisterClass *B) const;
> + const TargetRegisterClass *B,
> + const MVT::SimpleValueType SVT =
> + MVT::SimpleValueType::Any) const;
>
> /// getPointerRegClass - Returns a TargetRegisterClass used for pointer
> /// values. If a target supports multiple different pointer register classes,
>
> Index: lib/CodeGen/TargetRegisterInfo.cpp
> ===================================================================
> --- lib/CodeGen/TargetRegisterInfo.cpp (revision 247905)
> +++ lib/CodeGen/TargetRegisterInfo.cpp (working copy)
> @@ -166,16 +166,24 @@
> static inline
> const TargetRegisterClass *firstCommonClass(const uint32_t *A,
> const uint32_t *B,
> - const TargetRegisterInfo *TRI) {
> + const TargetRegisterInfo *TRI,
> + const MVT::SimpleValueType SVT =
> + MVT::SimpleValueType::Any) {
> + const MVT VT(SVT);
> for (unsigned I = 0, E = TRI->getNumRegClasses(); I < E; I += 32)
> - if (unsigned Common = *A++ & *B++)
> - return TRI->getRegClass(I + countTrailingZeros(Common));
> + if (unsigned Common = *A++ & *B++) {
> + const TargetRegisterClass *RC =
> + TRI->getRegClass(I + countTrailingZeros(Common));
> + if (SVT == MVT::SimpleValueType::Any || RC->hasType(VT))
> + return RC;
> + }
> return nullptr;
> }
>
> const TargetRegisterClass *
> TargetRegisterInfo::getCommonSubClass(const TargetRegisterClass *A,
> - const TargetRegisterClass *B) const {
> + const TargetRegisterClass *B,
> + const MVT::SimpleValueType SVT) const {
> // First take care of the trivial cases.
> if (A == B)
> return A;
> @@ -184,7 +192,7 @@
>
> // Register classes are ordered topologically, so the largest common
> // sub-class it the common sub-class with the smallest ID.
> - return firstCommonClass(A->getSubClassMask(), B->getSubClassMask(), this);
> + return firstCommonClass(A->getSubClassMask(), B->getSubClassMask(), this, SVT);
> }
>
> const TargetRegisterClass *
>
>
>
> On Tue, Oct 13, 2015 at 4:51 PM, Chih-hung Hsieh <chh at google.com> wrote:
>
>> On Tue, Oct 13, 2015 at 9:21 AM, Quentin Colombet <qcolombet at apple.com>
>> wrote:
>>
>>>
>>> This is interesting observation: fp128 gets split into 2-64-bit
>>> registers.
>>> Looks like we could go incrementally here.
>>> What about:
>>> 1. Changing the android ABI to pass the fp128 via xmm registers, but let
>>> the values live wherever they currently live in the meantime.
>>> 2. Fixing the AsmPrinter.
>>> 3. Fixing the split of the value into 2-64bit registers.
>>>
>>>
>> 2. is probably the simplest and independent part that can go in before
>> the others. The change is only in lib/Target/X86/X86MCInstLower.cpp. If it
>> is left out, llvm can compile libm, but abort on -g in some cases.
>>
>> 1. was what I wanted at the beginning and I don't mind using 2 64-bit
>> registers in other operations if that is possible.
>>
>> However, after I made the following changes for calling convention:
>> lib/Target/X86/X86RegisterInfo.td
>> lib/Target/X86/X86CallingConv.td
>> lib/Target/X86/X86InstrInfo.td
>> I found missing instructions to handle fp128 values load/store in xmm
>> registers, although there were many to process vectors in xmm.
>> So we need some extra load/store instructions in
>> lib/Target/X86/X86InstrSSE.td
>> Once f128 is 'legal' in register, it seemed easier for llvm to pass it
>> around than converting back-and-forth between 128-bit and 2x64-bit
>> registers.
>> In fact since almost all f128 operations are handled by library
>> functions, the values are mostly passed around and in f128 registers.
>>
>> I didn't try it but I think it would probably require more twist of
>> current llvm code to keep f128 in 2 64-bit registers and pass in xmm.
>> Anyway, if anyone knows how to configure llvm easily, we can try that.
>>
>> Actually most of the changes were required to compile libm, which uses
>> unions to access floating point bits as integers. We need instructions to
>> handle i128 vs f128 issues. Hence, the need of only "partial" logic in
>> LegalizeFloatTypes.cpp.
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20151019/129fb179/attachment.html>
More information about the llvm-commits
mailing list