[PATCH] D6629: x86: Emit LAHF/SAHF instead of PUSHF/POPF

Sanjoy Das via llvm-commits llvm-commits at lists.llvm.org
Sun Oct 4 13:02:54 PDT 2015


sanjoy added inline comments.

================
Comment at: llvm/trunk/lib/CodeGen/MachineInstrBundle.cpp:313
@@ -312,3 +312,3 @@
 
-    bool IsRegOrSuperReg = MOReg == Reg || TRI->isSubRegister(MOReg, Reg);
+    bool IsRegOrSuperReg = MOReg == Reg || TRI->isSuperRegister(MOReg, Reg);
     bool IsRegOrOverlapping = MOReg == Reg || TRI->regsOverlap(MOReg, Reg);
----------------
jfb wrote:
> sanjoy wrote:
> > Was this bit intentional?  I think (without understanding the surrounding code) this is contributing to PR25033.
> Yes, this change was intentional: the code used to get confused about sub/super reg before and my patch would tickle the issues (because it uses AL and AH separately. I believe that the previous code had no clue about subregs, and so other code was simply incorrect but that never manifested because of this bug. I think my fix may tickle other bugs :-)
> 
> Michael Hordijk tracked down the problem in the mailing list:
> 
> The IR:
> ```
>         CALL64pcrel32 <ga:@foo>, <regmask>, %RSP<imp-use>, %RSP<imp-def>,
> %EAX<imp-def>
>         %RAX<def> = MOV64rr %R14<kill>
> ```
> So `CALL` defines `EAX`, and we're asking `computeRegisterLiveness` whether or
> not `RAX` is live.  `computeRegisterLiveness` walks backwards and one thing it
> looks for is whether the register is being defined:
> ```
>     if (IsRegOrSuperReg) {
>         PRI.Defines = true;     // Reg or a super-register is defined.
>         if (!MO.isDead())
>         AllDefsDead = false;
>     }
> ```
> 
> And this is what determines if we (`RAX`) is a register or a super-register
> of the register being defined (`lib/CodeGen/MachineInstrBundle.cpp`):
> ```
> 313:    bool IsRegOrSuperReg = MOReg == Reg || TRI->isSubRegister(MOReg,
> Reg);
> ```
> This will return false, as `RAX` is not a sub register of `EAX`.
> 
I'm not familiar with the LLVM backend, so here is what I've *assumed*
about "clobber" vs. "define":

  - a register is clobbered if it is partially written to

  - a register is defined if it is fully written to either by a move
    to that register, or to some super-register that wholly contains
    the said register

If these assumptions are wrong, then you can ignore everything I've
said below. :)

With these assumptions in place, I read the code in `analyzePhysReg` this way:

`IsRegOrSuperReg == true` ==> if `MOReg` is written to (in the
containing MI), then `Reg` is defined.  Specifically, if `MOReg` is
`EAX` and `Reg` is `RAX` then this is `false`, since even if the
instruction is defines `EAX`, it does not *define* `RAX` (though it
may still clobber it).


`IsRegOrOverlapping == true` ==> if `MOReg` is written to, `Reg` is
clobbered (i.e. partially written to).  This should be true if `MOReg`
is `EAX` and `Reg` is `RAX`.



I think the initial problem (before this change, in the IR you showed) was not that
`IsRegOrSuperReg` was `false` when it should have been true, but that
in `computeRegisterLiveness` we have

      if (Analysis.Kills || Analysis.Clobbers)
        // Register killed, so isn't live.
        return LQR_Dead;

I don't think we can return `LQR_Dead` if `Analysis.Clobbers` is true.


Repository:
  rL LLVM

http://reviews.llvm.org/D6629





More information about the llvm-commits mailing list