[llvm-dev] [RFC] llvm-mca: a static performance analysis tool

Matthias Braun via llvm-dev llvm-dev at lists.llvm.org
Sun Mar 4 12:51:10 PST 2018



> On Mar 2, 2018, at 9:30 AM, Andrew Trick <atrick at apple.com> wrote:
> 
> +Matthias
> 
>> On Mar 2, 2018, at 6:42 AM, Andrea Di Biagio <andrea.dibiagio at gmail.com <mailto:andrea.dibiagio at gmail.com>> wrote:
>> 
>>> Known limitations on X86 processors
>>> -----------------------------------
>>> 
>>> 1) Partial register updates versus full register updates.
>>> <snip>
>> 
>> MachineOperand handles this. You just need to create the machine instrs.
>> 
>> Interesting. I couldn't find how to do it. It would be great if somebody helps me on this.
> 
> 
> I was thinking of APIs like MachineOperand::readsReg().
> 
> I guess if you’re only asking whether an instruction zeros the upper part of the register, that information *should* be available from MCInstr/MCRegisterInfo, but I’m not very familiar with the API.

I don’t think we have this information in an explicit form today:

- It’s usually not a correctness problem because we cannot really address the upper register parts independently on those targets.
- We work around some ISEL shortcomings via `SUBREG_TO_REG` (see TargetOpcode.def) which I consider a nasty hack as stating assumptions about the predecessor node violates the referential transparency that you would expect from SSA.
- Coalescing/regalloc is using `%vregX:sub32<undef> =` to represent this.

So today you are probably out of luck when coming from the MC side of things. I think adding a OperandFlag in MCInstrDesc would be a great idea and could be a first step towards retiring SUBREG_TO_REG.

- Matthias

> 
> Matthias?
> 
> -Andy
> 
>> 1) Partial register updates versus full register updates.
>> 
>> On x86-64, a 32-bit GPR write fully updates the super-register. Example:
>>       add %edi %eax    ## eax += edi
>> 
>> Here, register %eax aliases the lower half of 64-bit register %rax. On x86-64,
>> register %rax is fully updated by the 'add' (the upper half of %rax is zeroed).
>> Essentially, it "kills" any previous definition of (the upper half of) register
>> %rax.
>> 
>> On the other hand, 8/16 bit register writes only perform a so-called "partial
>> register update". Example:
>>       add %di, %ax     ## ax += di
>> 
>> Here, register %eax is only partially updated. To be more specific, the lower
>> half of %eax is set, and the upper half is left unchanged. There is also no
>> change in the upper 48 bits of register %rax.
>> 
>> To get accurate performance analysis, the tool has to know which instructions
>> perform a partial register update, and which instructions fully update the
>> destination's super-register.
>> 
>> One way to expose this information is (again) via tablegen.  For example, we
>> could add a flag in the tablegen instruction class to tag instructions that
>> perform partial register updates. Something like this: 'bit
>> hasPartialRegisterUpdate = 1'. However, this would force a `let
>> hasPartialRegisterUpdate = 0` on several instruction definitions.
>> 
>> Another approach is to have a MCSubtargetInfo hook similar to this:
>>     virtual bool updatesSuperRegisters(unsigned short opcode) { return false; }
>> 
>> Targets will be able to override this method if needed.  Again, this is just an
>> idea. But the plan is to have this fixed as a future development.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20180304/e677b73f/attachment.html>


More information about the llvm-dev mailing list