[llvm-commits] [llvm] r105387 - in /llvm/trunk: lib/CodeGen/MachineSink.cpp test/CodeGen/X86/MachineSink-CritEdge.ll test/CodeGen/X86/sink-hoist.ll
Evan Cheng
evan.cheng at apple.com
Thu Jun 3 10:36:44 PDT 2010
I am concerned about the compile time impact. Perhaps we should limit the scanning to a small number of instructions and return true conservatively when it reaches the limit?
Evan
On Jun 3, 2010, at 12:54 AM, Bill Wendling wrote:
> Author: void
> Date: Thu Jun 3 02:54:20 2010
> New Revision: 105387
>
> URL: http://llvm.org/viewvc/llvm-project?rev=105387&view=rev
> Log:
> Machine sink could potentially sink instructions into a block where the physical
> registers it defines then interfere with an existing preg live range.
>
> For instance, if we had something like these machine instructions:
>
> BB#0
> ... = imul ... EFLAGS<imp-def,dead>
> test ..., EFLAGS<imp-def>
> jcc BB#2 EFLAGS<imp-use>
>
> BB#1
> ... ; fallthrough to BB#2
>
> BB#2
> ... ; No code that defines EFLAGS
> jcc ... EFLAGS<imp-use>
>
> Machine sink will come along, see that imul implicitly defines EFLAGS, but
> because it's "dead", it assumes that it can move imul into BB#2. But when it
> does, imul's "dead" imp-def of EFLAGS is raised from the dead (a zombie) and
> messes up the condition code for the jump (and pretty much anything else which
> relies upon it being correct).
>
> The solution is to know which pregs are live going into a basic block. However,
> that information isn't calculated at this point. Nor does the LiveVariables pass
> take into account non-allocatable physical registers. In lieu of this, we do a
> *very* conservative pass through the basic block to determine if a preg is live
> coming out of it.
>
> Modified:
> llvm/trunk/lib/CodeGen/MachineSink.cpp
> llvm/trunk/test/CodeGen/X86/MachineSink-CritEdge.ll
> llvm/trunk/test/CodeGen/X86/sink-hoist.ll
>
> Modified: llvm/trunk/lib/CodeGen/MachineSink.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MachineSink.cpp?rev=105387&r1=105386&r2=105387&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/MachineSink.cpp (original)
> +++ llvm/trunk/lib/CodeGen/MachineSink.cpp Thu Jun 3 02:54:20 2010
> @@ -25,6 +25,7 @@
> #include "llvm/Target/TargetRegisterInfo.h"
> #include "llvm/Target/TargetInstrInfo.h"
> #include "llvm/Target/TargetMachine.h"
> +#include "llvm/ADT/SmallSet.h"
> #include "llvm/ADT/Statistic.h"
> #include "llvm/Support/Debug.h"
> #include "llvm/Support/raw_ostream.h"
> @@ -61,6 +62,7 @@
> bool ProcessBlock(MachineBasicBlock &MBB);
> bool SinkInstruction(MachineInstr *MI, bool &SawStore);
> bool AllUsesDominatedByBlock(unsigned Reg, MachineBasicBlock *MBB) const;
> + bool LiveOutOfBasicBlock(const MachineInstr *MI, unsigned Reg) const;
> };
> } // end anonymous namespace
>
> @@ -166,6 +168,44 @@
> return MadeChange;
> }
>
> +/// LiveOutOfBasicBlock - Determine if the physical register, defined and dead
> +/// in MI, is live on exit from the basic block.
> +bool MachineSinking::LiveOutOfBasicBlock(const MachineInstr *MI,
> + unsigned Reg) const {
> + assert(TargetRegisterInfo::isPhysicalRegister(Reg) &&
> + "Only want to determine if a physical register is live out of a BB!");
> +
> + const MachineBasicBlock *MBB = MI->getParent();
> + SmallSet<unsigned, 8> KilledRegs;
> + MachineBasicBlock::const_iterator I = MBB->end();
> + MachineBasicBlock::const_iterator E = MBB->begin();
> + assert(I != E && "How can there be an empty block at this point?!");
> +
> + // Loop through the instructions bottom-up. If we see a kill of the preg
> + // first, then it's not live out of the BB. If we see a use or def first, then
> + // we assume that it is live out of the BB.
> + do {
> + const MachineInstr &CurMI = *--I;
> +
> + for (unsigned i = 0, e = CurMI.getNumOperands(); i != e; ++i) {
> + const MachineOperand &MO = CurMI.getOperand(i);
> + if (!MO.isReg()) continue; // Ignore non-register operands.
> +
> + unsigned MOReg = MO.getReg();
> + if (MOReg == 0) continue;
> +
> + if (MOReg == Reg) {
> + if (MO.isKill())
> + return false;
> + if (MO.isUse() || MO.isDef())
> + return true;
> + }
> + }
> + } while (I != E);
> +
> + return false;
> +}
> +
> /// SinkInstruction - Determine whether it is safe to sink the specified machine
> /// instruction out of its current block into a successor.
> bool MachineSinking::SinkInstruction(MachineInstr *MI, bool &SawStore) {
> @@ -188,6 +228,7 @@
> // SuccToSinkTo - This is the successor to sink this instruction to, once we
> // decide.
> MachineBasicBlock *SuccToSinkTo = 0;
> + SmallVector<unsigned, 4> PhysRegs;
>
> for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
> const MachineOperand &MO = MI->getOperand(i);
> @@ -216,9 +257,12 @@
> if (AllocatableSet.test(AliasReg))
> return false;
> }
> - } else if (!MO.isDead()) {
> - // A def that isn't dead. We can't move it.
> - return false;
> + } else {
> + if (!MO.isDead())
> + // A def that isn't dead. We can't move it.
> + return false;
> + else
> + PhysRegs.push_back(Reg);
> }
> } else {
> // Virtual register uses are always safe to sink.
> @@ -281,7 +325,15 @@
> // happen with loops.
> if (MI->getParent() == SuccToSinkTo)
> return false;
> -
> +
> + // If the instruction to move defines a dead physical register which is live
> + // when leaving the basic block, don't move it because it could turn into a
> + // "zombie" define of that preg. E.g., EFLAGS. (<rdar://problem/8030636>)
> + for (SmallVectorImpl<unsigned>::const_iterator
> + I = PhysRegs.begin(), E = PhysRegs.end(); I != E; ++I)
> + if (LiveOutOfBasicBlock(MI, *I))
> + return false;
> +
> DEBUG(dbgs() << "Sink instr " << *MI << "\tinto block " << *SuccToSinkTo);
>
> // If the block has multiple predecessors, this would introduce computation on
>
> Modified: llvm/trunk/test/CodeGen/X86/MachineSink-CritEdge.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/MachineSink-CritEdge.ll?rev=105387&r1=105386&r2=105387&view=diff
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/MachineSink-CritEdge.ll (original)
> +++ llvm/trunk/test/CodeGen/X86/MachineSink-CritEdge.ll Thu Jun 3 02:54:20 2010
> @@ -1,4 +1,10 @@
> ; RUN: llc < %s | FileCheck %s
> +; XFAIL: *
> +;
> +; See <rdar://problem/8030636>. This test isn't valid after we made machine
> +; sinking more conservative about sinking instructions that define a preg into a
> +; block when we don't know if the preg is killed within the current block.
> +
> target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
> target triple = "x86_64-apple-darwin10.0.0"
>
>
> Modified: llvm/trunk/test/CodeGen/X86/sink-hoist.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/sink-hoist.ll?rev=105387&r1=105386&r2=105387&view=diff
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/sink-hoist.ll (original)
> +++ llvm/trunk/test/CodeGen/X86/sink-hoist.ll Thu Jun 3 02:54:20 2010
> @@ -44,26 +44,33 @@
>
> ; Sink instructions with dead EFLAGS defs.
>
> -; CHECK: zzz:
> -; CHECK: je
> -; CHECK-NEXT: orb
> -
> -define zeroext i8 @zzz(i8 zeroext %a, i8 zeroext %b) nounwind readnone {
> -entry:
> - %tmp = zext i8 %a to i32 ; <i32> [#uses=1]
> - %tmp2 = icmp eq i8 %a, 0 ; <i1> [#uses=1]
> - %tmp3 = or i8 %b, -128 ; <i8> [#uses=1]
> - %tmp4 = and i8 %b, 127 ; <i8> [#uses=1]
> - %b_addr.0 = select i1 %tmp2, i8 %tmp4, i8 %tmp3 ; <i8> [#uses=1]
> - ret i8 %b_addr.0
> -}
> +; FIXME: Unfail the zzz test if we can correctly mark pregs with the kill flag.
> +;
> +; See <rdar://problem/8030636>. This test isn't valid after we made machine
> +; sinking more conservative about sinking instructions that define a preg into a
> +; block when we don't know if the preg is killed within the current block.
> +
> +
> +; FIXMEHECK: zzz:
> +; FIXMEHECK: je
> +; FIXMEHECK-NEXT: orb
> +
> +; define zeroext i8 @zzz(i8 zeroext %a, i8 zeroext %b) nounwind readnone {
> +; entry:
> +; %tmp = zext i8 %a to i32 ; <i32> [#uses=1]
> +; %tmp2 = icmp eq i8 %a, 0 ; <i1> [#uses=1]
> +; %tmp3 = or i8 %b, -128 ; <i8> [#uses=1]
> +; %tmp4 = and i8 %b, 127 ; <i8> [#uses=1]
> +; %b_addr.0 = select i1 %tmp2, i8 %tmp4, i8 %tmp3 ; <i8> [#uses=1]
> +; ret i8 %b_addr.0
> +; }
>
> ; Codegen should hoist and CSE these constants.
>
> ; CHECK: vv:
> -; CHECK: LCPI3_0(%rip), %xmm0
> -; CHECK: LCPI3_1(%rip), %xmm1
> -; CHECK: LCPI3_2(%rip), %xmm2
> +; CHECK: LCPI2_0(%rip), %xmm0
> +; CHECK: LCPI2_1(%rip), %xmm1
> +; CHECK: LCPI2_2(%rip), %xmm2
> ; CHECK: align
> ; CHECK-NOT: LCPI
> ; CHECK: ret
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list