[llvm-dev] [LLVMdev] TableGen Register Class not matching for MI in 3.6

Ryan Taylor via llvm-dev
Tue, 25 Aug 2015 00:58:11 -0000

Quentin,

 This is the issue. Somewhere prior to the constrainRegClass, it's
assigning the GPRBase sub class of GPR to the MOV instruction, so it can't
constrain it to Base and hence has to add the COPY. Now I just need to find
out why it is ignoring the TableGen defined GPRBase for the MOV MI in favor
of it's sub class GPR.

Thanks.

On Mon, Aug 24, 2015 at 8:34 PM, Ryan Taylor <ryta1203 at gmail.com>
wrote:

> Quentin,
>
>   It looks like firstCommonClass is returning a nullptr, which is odd
> since the MOV should be using GPRBase (GPR and Base) and the NewVReg class
> is Base. Maybe the ISel has decided to select the sub class GPR from
> GPRBase  and hence GPR != Base and so the constrainRegClass is failing.
>
>   Using the MI Op's reg class and comparing it directly to the NewVReg
> class would eliminate this possible issue and should produce more accurate
> results?
>
> Thanks.
>
> On Mon, Aug 24, 2015 at 8:08 PM, Quentin Colombet <qcolombet at
apple.com>
> wrote:
>
>>
>> On Aug 24, 2015, at 4:46 PM, Ryan Taylor <ryta1203 at gmail.com>
wrote:
>>
>> Here is the snippet that matters:
>>
>> void
>> InstrEmitter::AddRegisterOperand(MachineInstrBuilder &MIB,
>>                                  SDValue Op,
>>                                  unsigned IIOpNum,
>>                                  const MCInstrDesc *II,
>>                                  DenseMap<SDValue, unsigned>
&VRBaseMap,
>>                                  bool IsDebug, bool IsClone, bool
>> IsCloned) {
>>   //llvm::errs() << "Op = ";
>>   //Op.dump();
>>   assert(Op.getValueType() != MVT::Other &&
>>          Op.getValueType() != MVT::Glue &&
>>          "Chain and glue operands should occur at end of operand
list!");
>>   // Get/emit the operand.
>>   unsigned VReg = getVR(Op, VRBaseMap);
>>   assert(TargetRegisterInfo::isVirtualRegister(VReg) &&
"Not a vreg?");
>>   const MCInstrDesc &MCID = MIB->getDesc();
>>   bool isOptDef = IIOpNum < MCID.getNumOperands() &&
>>     MCID.OpInfo[IIOpNum].isOptionalDef();
>>   // If the instruction requires a register in a different class,
create
>>   // a new virtual register and copy the value into it, but first
attempt
>> to
>>   // shrink VReg's register class within reason.  For example, if
VReg =>> GR32
>>   // and II requires a GR32_NOSP, just constrain VReg to GR32_NOSP.
>>   if (II) {
>>     const TargetRegisterClass *DstRC = nullptr;
>>     if (IIOpNum < II->getNumOperands())
>>       DstRC >>
TRI->getAllocatableClass(TII->getRegClass(*II,IIOpNum,TRI,*MF));
>>     if (DstRC && !MRI->constrainRegClass(VReg, DstRC,
MinRCSize)) {
>>       unsigned NewVReg = MRI->createVirtualRegister(DstRC);
>>       if (TRI->getCommonSubClass(DstRC,
>>           TRI->getRegClass(II->OpInfo[IIOpNum].RegClass))
>>
>>
>> What I was saying was this II->OpInfo[IIOpNum].RegClass looks to
return
>> DstRC at first glance.
>> What you want is TRI->getRegClass(VReg).
>>
>> BTW, now with the full snippet, I see your mistake. You are passing a
>> RegClass to a method that expect a virtual register (your call is to
>> TargetRegisterInfo::getRegClass I believe, not
>> MCRegisterInfo::getRegClass). So you end up with the regclass of a
virtual
>> register numbered RegClass.
>>
>> Anyway, if we cannot constrain VReg on DstRC (i.e., what we try in the
>> previous if), this means that getCommonSubClass will fail or will
return a
>> class that is likely too small to be reasonable (i.e., below
MinRCSize).
>>
>> Cheers,
>> -Quentin
>>
>>
>>             == DstRC) {
>>         MRI->setRegClass(VReg, DstRC);
>>       }
>>       else {
>>         BuildMI(*MBB, InsertPos, Op.getNode()->getDebugLoc(),
>>               TII->get(TargetOpcode::COPY), NewVReg).addReg(VReg);
>>         VReg = NewVReg;
>>       }
>>     }
>>   }
>>
>> This does not work. The logic seems sound though, you are checking an
RC
>> (DstRC) and the MI's operand's RegClass, get the common sub,
which should
>> either be or not be DstRC, right?
>>
>> Thanks.
>>
>> On Mon, Aug 24, 2015 at 4:44 PM, Quentin Colombet <qcolombet at
apple.com>
>> wrote:
>>
>>>
>>> On Aug 24, 2015, at 1:30 PM, Ryan Taylor <ryta1203 at
gmail.com> wrote:
>>>
>>> I'm trying to do something like this:
>>>
>>> // Dst = NewVReg's reg class
>>> // *II = MCInstrDesc
>>> // IIOpNum = II Operand Num
>>>
>>> if (TRI->getCommonSubClass(DstRC,
>>> TRI->getRegClass(II->OpInfo[IIOpNum].RegClass)) == DstRC)
>>>      MRI->setRegClass(VReg, DstRC);
>>> else
>>>      BuildMI(... TargetOpcode::COPY...)
>>>
>>> The condition is trying to reset the reg class if the DstRC reg
class is
>>> valid for the operand num of the machine instruction. If the
NewVReg
>>> register class is not valid for that operand of the machine
instruction I
>>> want to generate a COPY instruction (as it does now all the time).
This
>>> condition should check for intersection, right?
>>>
>>>
>>> Yes, that’s right.
>>>
>>> It should find the common subclass of the new register class and
the
>>> valid reg class of the operand for that machine instruction.
>>>
>>> Unfortunately it looks like that condition is always being set to
true
>>> (or I'm getting a TON of false positives).
>>>
>>>
>>> Where does II come from?
>>> From the snippet, I am guessing it is the instruction that uses
NewVReg,
>>> i.e., you are checking that the class for NewVReg matches the class
for
>>> NewVReg… which by construction is always true!
>>>
>>> You want to check "common subclass” of DstRC and SrcRC.
>>>
>>> Cheers,
>>> Q.
>>>
>>>
>>> Thanks.
>>>
>>> On Mon, Aug 24, 2015 at 2:09 PM, Quentin Colombet <qcolombet at
apple.com>
>>> wrote:
>>>
>>>>
>>>> On Aug 22, 2015, at 9:10 AM, Ryan Taylor <ryta1203 at
gmail.com> wrote:
>>>>
>>>> One last question regarding this please.
>>>>
>>>> Why aren't we simply changing the register class in
AddRegisterOperand
>>>> instead of building a new COPY? I admit I haven't thought
this out but for
>>>> my test cases so far this works just fine and reduces the
number of ASM mov
>>>> instructions that are being produced.
>>>>
>>>> For example, instead of BuildMI(...,
TII->get(TargetOpcode::COPY),
>>>> NewVReg).addReg(VReg), use something like
MRI->setRegClass(VReg,
>>>> MRI->getRegClass(NewVReg)) ?
>>>>
>>>>
>>>> The problem is that the old register class and the new one may
not
>>>> intersect. I do not know exactly what makes us create a new
vreg w.r.t.,
>>>> but probably if the class is not identical we create one. You
can try to
>>>> use contraintsRegClass to get the intersection.
>>>>
>>>> Q.
>>>>
>>>>
>>>> What is the reasoning behind adding the extra instruction
instead of
>>>> changing the reg class?
>>>>
>>>> On Wed, Aug 19, 2015 at 2:04 PM, Ryan Taylor <ryta1203 at
gmail.com>
>>>> wrote:
>>>>
>>>>> Yes, you're probably right about the ID. The odd part
is that I have
>>>>> other simpler instructions that use the same type of
superset and it
>>>>> always, so far, matches correctly (it doesn't just pick
GPRRegs all the
>>>>> time).
>>>>>
>>>>> Like I said, we can just 'fill in the gaps' with
new MIs but that sure
>>>>> seems like a brush off solution. The td files would be so
much cleaner if
>>>>> you could have a superset reg class that actually matched
the correct reg
>>>>> usage (which it sort of does in AddRegisterOperand when it
adds the extra
>>>>> COPY.... not sure why it does this instead of just checking
the original MI
>>>>> and seeing if the reg class needed is in the list and then
just changing
>>>>> the vreg reg class for the original MI, that seems like a
better solution?)
>>>>> It's like it's actually picking some reg class
first and then trying to fix
>>>>> it's error by adding MORE instructions instead of
finding the right reg
>>>>> class the first time.
>>>>>
>>>>> Thanks.
>>>>>
>>>>> On Wed, Aug 19, 2015 at 1:32 PM, Quentin Colombet
<qcolombet at apple.com
>>>>> > wrote:
>>>>>
>>>>>>
>>>>>> On Aug 19, 2015, at 9:42 AM, Ryan Taylor <ryta1203
at gmail.com> wrote:
>>>>>>
>>>>>> It seems the problem arises from using multiple reg
classes for one
>>>>>> MI in the td file, I guess.
>>>>>>
>>>>>>
>>>>>> Probably, that does not sound something used widely :).
>>>>>>
>>>>>>
>>>>>> I'm not sure it takes first available, if I swap
the reg classes in
>>>>>> the list it does not change and if I replace the GPR
reg class with
>>>>>> something different than it picks the base reg class
fine, potentially it
>>>>>> is using the reg class with most available? idk.
>>>>>>
>>>>>>
>>>>>> My guess is it would take the register class that come
first in the
>>>>>> register class IDs (not the list on the instruction
itself), but I am just
>>>>>> guessing.
>>>>>>
>>>>>>
>>>>>> I just need to create MIs for every possible case I
guess.
>>>>>> Thanks for the help! :)
>>>>>>
>>>>>> On Wed, Aug 19, 2015 at 12:04 PM, Quentin Colombet <
>>>>>> qcolombet at apple.com> wrote:
>>>>>>
>>>>>>> Hi Ryan,
>>>>>>>
>>>>>>> On Aug 19, 2015, at 6:35 AM, Ryan Taylor via
llvm-dev <
>>>>>>> llvm-dev at lists.llvm.org> wrote:
>>>>>>>
>>>>>>> Essentially it doesn't appear that the reg
class assignment is based
>>>>>>> on uses and is instead inserting an extra COPY for
this. Is this accurate?
>>>>>>> If so, why?
>>>>>>>
>>>>>>>
>>>>>>> We match the instructions bottom-up and I believe
that copy are
>>>>>>> automatically inserted when the register classes do
not match.
>>>>>>> That seems strange to me that the isel logs are
exactly the same but
>>>>>>> still you are seeing a different result of
instruction selection.
>>>>>>>
>>>>>>>
>>>>>>> In this above example, I'm getting an extra
"mov %r0, $b1" (this is
>>>>>>> an MI::COPY) even though "mov @a, %b1"
(this is an MI::MOV) is entirely
>>>>>>> acceptable since both GPRRegs and BaseRegs are in
the reg class list..
>>>>>>>
>>>>>>> If the heuristic is simply picking the first
available reg class or
>>>>>>> the reg class with the most available, for example,
instead of picking the
>>>>>>> reg class based on uses, I will have to change this
heuristic to reduce
>>>>>>> code bloat, or we'll have to add backend passes
to reduce the code bloat.
>>>>>>>
>>>>>>>
>>>>>>> I think the current approach is rather simple and
we just match the
>>>>>>> type for the first available reg class (assuming
your selection dag
>>>>>>> patterns are not choosing something different).
There are not per say
>>>>>>> passes to reduce this "code bloat” since we
never encounter this problem in
>>>>>>> practice. The peephole optimizer has some logic to
avoid this move and
>>>>>>> CodeGenPrepare also does a few transformation to
avoid some of that.
>>>>>>>
>>>>>>> Anyhow, I’d say debug the isel process (probably
the InstrEmitter
>>>>>>> part) to see where the problem arise.
>>>>>>>
>>>>>>> Cheers,
>>>>>>> -Quentin
>>>>>>>
>>>>>>>
>>>>>>> Thanks.
>>>>>>>
>>>>>>> On Mon, Aug 17, 2015 at 7:00 PM, Ryan Taylor
<ryta1203 at gmail.com>
>>>>>>> wrote:
>>>>>>>
>>>>>>>>
>>>>>>>> ---------- Forwarded message ----------
>>>>>>>> From: Ryan Taylor <ryta1203 at gmail.com>
>>>>>>>> Date: Mon, Aug 17, 2015 at 6:59 PM
>>>>>>>> Subject: Re: [LLVMdev] TableGen Register Class
not matching for MI
>>>>>>>> in 3.6
>>>>>>>> To: Quentin Colombet <qcolombet at
apple.com>
>>>>>>>> Cc: "llvmdev at cs.uiuc.edu"
<llvmdev at cs.uiuc.edu>
>>>>>>>>
>>>>>>>>
>>>>>>>> The isel logs are exactly the same, nothing
changed, it's matching
>>>>>>>> the same instructions just the reg classes are
different.
>>>>>>>>
>>>>>>>> Where in the SelectionDAG is the code that adds
an extra MI COPY?
>>>>>>>> I'll have to set a breakpoint and debug
backwards from there to see what's
>>>>>>>> going on. It's only happening with the
GPRRegs class, for example if I use
>>>>>>>> another reg class instead along with the base
regs than it matches the base
>>>>>>>> reg just fine, it's like GPR is overriding
any other reg class matching.
>>>>>>>>
>>>>>>>> Thanks.
>>>>>>>>
>>>>>>>> On Fri, Jul 31, 2015 at 1:21 PM, Quentin
Colombet <
>>>>>>>> qcolombet at apple.com> wrote:
>>>>>>>>
>>>>>>>>>
>>>>>>>>> On Jul 31, 2015, at 10:14 AM, Ryan Taylor
<ryta1203 at gmail.com>
>>>>>>>>> wrote:
>>>>>>>>>
>>>>>>>>> Quentin,
>>>>>>>>>
>>>>>>>>>  It's in the instruction selection,
sorry I forgot to mention
>>>>>>>>> that. The Vreg class is GPR and an extra
COPY is generated to copy from the
>>>>>>>>> GPR to the Base Reg, even though my
'mov' instruction has Base in the
>>>>>>>>> Register class list.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Then, I suggest you use -debug-only=isel to
check what changed in
>>>>>>>>> your selection instruction process. I do
not see off-hand what could have
>>>>>>>>> caused.
>>>>>>>>>
>>>>>>>>> Sorry for not being more helpful here.
>>>>>>>>>
>>>>>>>>> Q.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> On Fri, Jul 31, 2015 at 12:50 PM, Quentin
Colombet <
>>>>>>>>> qcolombet at apple.com> wrote:
>>>>>>>>>
>>>>>>>>>> Hi Ryan,
>>>>>>>>>>
>>>>>>>>>> Could you check where those moves come
from?
>>>>>>>>>>
>>>>>>>>>> In particular, is this the product of
the instruction selection
>>>>>>>>>> process?
>>>>>>>>>>
>>>>>>>>>> You use -print-machineinstrs to see
when it is inserted.
>>>>>>>>>>
>>>>>>>>>> Thanks,
>>>>>>>>>> -Quentin
>>>>>>>>>>
>>>>>>>>>> > On Jul 30, 2015, at 2:02 PM, Ryan
Taylor <ryta1203 at gmail.com>
>>>>>>>>>> wrote:
>>>>>>>>>> >
>>>>>>>>>> > In LLVM 3.6,
>>>>>>>>>> >
>>>>>>>>>> >  We have an instruction that uses
a register class that is
>>>>>>>>>> defined of several different reg
classes. In 3.4 this works fine but in 3.6
>>>>>>>>>> this is broken.
>>>>>>>>>> >
>>>>>>>>>> > For example, I have a mov
instruction. mov can be executed
>>>>>>>>>> between different register types (ie
gpr, index, base, etc..)
>>>>>>>>>> >
>>>>>>>>>> > In 3.4, we would get something
like this:
>>>>>>>>>> >
>>>>>>>>>> > mov @a, %b1 // moving this
immediate to a base register, which
>>>>>>>>>> is what we want
>>>>>>>>>> >
>>>>>>>>>> > In 3.6, we now get this:
>>>>>>>>>> >
>>>>>>>>>> > mov @a, %r0  // r0 = gpr
>>>>>>>>>> > mov %r0, %b1 // b1 = base reg
>>>>>>>>>> >
>>>>>>>>>> > The register class looks like
this:
>>>>>>>>>> >
>>>>>>>>>> > def ARegs :
RegisterClass<"us", [i16], i16, (add GPRRegs,
>>>>>>>>>> IndexRegs, BaseRegs)>;
>>>>>>>>>> >
>>>>>>>>>> > I have absolutely no idea why this
is not matching any longer?
>>>>>>>>>> >
>>>>>>>>>> > The fix here is to define an MI
with explicit single register
>>>>>>>>>> class (ie it only allows PTRRegs as the
destination).
>>>>>>>>>> >
>>>>>>>>>> > This must be an issue with
something else and not the tablegen
>>>>>>>>>> but if that was the case I'm not
sure. Anyway help would be great, what
>>>>>>>>>> should I be looking at here?
>>>>>>>>>> >
>>>>>>>>>> > Thanks.
>>>>>>>>>> >
_______________________________________________
>>>>>>>>>> > LLVM Developers mailing list
>>>>>>>>>> > LLVMdev at cs.uiuc.edu
http://llvm.cs.uiuc.edu
>>>>>>>>>>
<https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.cs.uiuc.edu_&d=BQMFaQ&c=eEvniauFctOgLOKGJOplqw&r=Kar_gr4lUTX9iRgFLHyIPCR7VD3VlB3-02h_Q5v9oWk&m=7VQTHNyB_IcF4I86741RzVduPmdgCRL_mHUfuUmnL0Y&s=fK8KXlXNFjX9EyldRbiY4GwaxZBFjvTYEXwRJuFLJvg&e=>
>>>>>>>>>> >
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>>>>>>>>>>
<https://urldefense.proofpoint.com/v2/url?u=http-3A__lists.cs.uiuc.edu_mailman_listinfo_llvmdev&d=BQMFaQ&c=eEvniauFctOgLOKGJOplqw&r=Kar_gr4lUTX9iRgFLHyIPCR7VD3VlB3-02h_Q5v9oWk&m=7VQTHNyB_IcF4I86741RzVduPmdgCRL_mHUfuUmnL0Y&s=TAPJBdWJfY-53g2FEN-kOKTo2nDJxcpEGNpqpgcrN9U&e=>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>> _______________________________________________
>>>>>>> LLVM Developers mailing list
>>>>>>> llvm-dev at lists.llvm.org
>>>>>>>
>>>>>>>
https://urldefense.proofpoint.com/v2/url?u=http-3A__lists.llvm.org_cgi-2Dbin_mailman_listinfo_llvm-2Ddev&d=BQIGaQ&c=eEvniauFctOgLOKGJOplqw&r=Kar_gr4lUTX9iRgFLHyIPCR7VD3VlB3-02h_Q5v9oWk&m=7VQTHNyB_IcF4I86741RzVduPmdgCRL_mHUfuUmnL0Y&s=N0TOaZZSrDVRpbh_uMG5DV5ZZ2_KVMcBWtK9vGIaByY&e>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>>
>>>>
>>>
>>>
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://lists.llvm.org/pipermail/llvm-dev/attachments/20150824/50cbae17/attachment.html>