diff options
author | Evan Cheng <evan.cheng@apple.com> | 2009-09-23 06:28:31 +0000 |
---|---|---|
committer | Evan Cheng <evan.cheng@apple.com> | 2009-09-23 06:28:31 +0000 |
commit | d062bf740651c35ed3ee80b66b02d8363fd14a3a (patch) | |
tree | 8350041adcde3c7f4c62bc987c7291ed028577c7 | |
parent | 29a1c10040effaa8c0968a3899b053b6b591a73a (diff) | |
download | external_llvm-d062bf740651c35ed3ee80b66b02d8363fd14a3a.zip external_llvm-d062bf740651c35ed3ee80b66b02d8363fd14a3a.tar.gz external_llvm-d062bf740651c35ed3ee80b66b02d8363fd14a3a.tar.bz2 |
Fix PR5024. LiveVariables physical register defs should *commit* only after all
of the defs are processed.
Also fix a implicit_def propagation bug: a implicit_def of a physical register
should be applied to uses of the sub-registers.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@82616 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/llvm/CodeGen/LiveVariables.h | 6 | ||||
-rw-r--r-- | lib/CodeGen/LiveIntervalAnalysis.cpp | 4 | ||||
-rw-r--r-- | lib/CodeGen/LiveVariables.cpp | 125 | ||||
-rw-r--r-- | test/CodeGen/ARM/2009-09-22-LiveVariablesBug.ll | 23 |
4 files changed, 125 insertions, 33 deletions
diff --git a/include/llvm/CodeGen/LiveVariables.h b/include/llvm/CodeGen/LiveVariables.h index 52d5595..45c72f5 100644 --- a/include/llvm/CodeGen/LiveVariables.h +++ b/include/llvm/CodeGen/LiveVariables.h @@ -149,7 +149,11 @@ private: // Intermediate data structures bool HandlePhysRegKill(unsigned Reg, MachineInstr *MI); void HandlePhysRegUse(unsigned Reg, MachineInstr *MI); - void HandlePhysRegDef(unsigned Reg, MachineInstr *MI); + void HandlePhysRegDef(unsigned Reg, MachineInstr *MI, + SmallVector<unsigned, 4> &Defs, + SmallVector<unsigned, 4> &SuperDefs); + void UpdatePhysRegDefs(MachineInstr *MI, SmallVector<unsigned, 4> &Defs); + void UpdateSuperRegDefs(MachineInstr *MI, SmallVector<unsigned, 4> &Defs); /// FindLastPartialDef - Return the last partial def of the specified register. /// Also returns the sub-registers that're defined by the instruction. diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp index abab1ee..825cf39 100644 --- a/lib/CodeGen/LiveIntervalAnalysis.cpp +++ b/lib/CodeGen/LiveIntervalAnalysis.cpp @@ -141,6 +141,10 @@ void LiveIntervals::processImplicitDefs() { if (MI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF) { unsigned Reg = MI->getOperand(0).getReg(); ImpDefRegs.insert(Reg); + if (TargetRegisterInfo::isPhysicalRegister(Reg)) { + for (const unsigned *SS = tri_->getSubRegisters(Reg); *SS; ++SS) + ImpDefRegs.insert(*SS); + } ImpDefMIs.push_back(MI); continue; } diff --git a/lib/CodeGen/LiveVariables.cpp b/lib/CodeGen/LiveVariables.cpp index e8a94bd..86a8ea9 100644 --- a/lib/CodeGen/LiveVariables.cpp +++ b/lib/CodeGen/LiveVariables.cpp @@ -407,7 +407,9 @@ bool LiveVariables::HandlePhysRegKill(unsigned Reg, MachineInstr *MI) { return true; } -void LiveVariables::HandlePhysRegDef(unsigned Reg, MachineInstr *MI) { +void LiveVariables::HandlePhysRegDef(unsigned Reg, MachineInstr *MI, + SmallVector<unsigned, 4> &Defs, + SmallVector<unsigned, 4> &SuperDefs) { // What parts of the register are previously defined? SmallSet<unsigned, 32> Live; if (PhysRegDef[Reg] || PhysRegUse[Reg]) { @@ -465,36 +467,24 @@ void LiveVariables::HandlePhysRegDef(unsigned Reg, MachineInstr *MI) { // EAX = // AX = EAX<imp-use,kill>, EAX<imp-def> // ... - /// = EAX - if (hasRegisterUseBelow(SuperReg, MI, MI->getParent())) { - MI->addOperand(MachineOperand::CreateReg(SuperReg, false/*IsDef*/, - true/*IsImp*/,true/*IsKill*/)); - MI->addOperand(MachineOperand::CreateReg(SuperReg, true/*IsDef*/, - true/*IsImp*/)); - PhysRegDef[SuperReg] = MI; - PhysRegUse[SuperReg] = NULL; - Processed.insert(SuperReg); - for (const unsigned *SS = TRI->getSubRegisters(SuperReg); *SS; ++SS) { - PhysRegDef[*SS] = MI; - PhysRegUse[*SS] = NULL; - Processed.insert(*SS); - } - } else { - // Otherwise, the super register is killed. - if (HandlePhysRegKill(SuperReg, MI)) { - PhysRegDef[SuperReg] = NULL; - PhysRegUse[SuperReg] = NULL; - for (const unsigned *SS = TRI->getSubRegisters(SuperReg); *SS; ++SS) { - PhysRegDef[*SS] = NULL; - PhysRegUse[*SS] = NULL; - Processed.insert(*SS); - } - } - } + // = EAX + SuperDefs.push_back(SuperReg); + Processed.insert(SuperReg); + for (const unsigned *SS = TRI->getSubRegisters(SuperReg); *SS; ++SS) + Processed.insert(*SS); } } // Remember this def. + Defs.push_back(Reg); + } +} + +void LiveVariables::UpdatePhysRegDefs(MachineInstr *MI, + SmallVector<unsigned, 4> &Defs) { + while (!Defs.empty()) { + unsigned Reg = Defs.back(); + Defs.pop_back(); PhysRegDef[Reg] = MI; PhysRegUse[Reg] = NULL; for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); @@ -505,6 +495,66 @@ void LiveVariables::HandlePhysRegDef(unsigned Reg, MachineInstr *MI) { } } +namespace { + struct RegSorter { + const TargetRegisterInfo *TRI; + + RegSorter(const TargetRegisterInfo *tri) : TRI(tri) { } + bool operator()(unsigned A, unsigned B) { + if (TRI->isSubRegister(A, B)) + return true; + else if (TRI->isSubRegister(B, A)) + return false; + return A < B; + } + }; +} + +void LiveVariables::UpdateSuperRegDefs(MachineInstr *MI, + SmallVector<unsigned, 4> &SuperDefs) { + // This instruction has defined part of some registers. If there are no + // more uses below MI, then the last use / def becomes kill / dead. + if (SuperDefs.empty()) + return; + + RegSorter RS(TRI); + std::sort(SuperDefs.begin(), SuperDefs.end(), RS); + SmallSet<unsigned, 4> Processed; + for (unsigned j = 0, ee = SuperDefs.size(); j != ee; ++j) { + unsigned SuperReg = SuperDefs[j]; + if (!Processed.insert(SuperReg)) + continue; + if (hasRegisterUseBelow(SuperReg, MI, MI->getParent())) { + // Previous use / def is not the last use / dead def. It's now + // partially re-defined. + MI->addOperand(MachineOperand::CreateReg(SuperReg, false/*IsDef*/, + true/*IsImp*/,true/*IsKill*/)); + MI->addOperand(MachineOperand::CreateReg(SuperReg, true/*IsDef*/, + true/*IsImp*/)); + PhysRegDef[SuperReg] = MI; + PhysRegUse[SuperReg] = NULL; + for (const unsigned *SS = TRI->getSubRegisters(SuperReg); *SS; ++SS) { + Processed.insert(*SS); + PhysRegDef[*SS] = MI; + PhysRegUse[*SS] = NULL; + } + } else { + // Previous use / def is kill / dead. It's not being re-defined. + HandlePhysRegKill(SuperReg, MI); + PhysRegDef[SuperReg] = 0; + PhysRegUse[SuperReg] = NULL; + for (const unsigned *SS = TRI->getSubRegisters(SuperReg); *SS; ++SS) { + Processed.insert(*SS); + if (PhysRegDef[*SS] == MI) + continue; // This instruction may have defined it. + PhysRegDef[*SS] = MI; + PhysRegUse[*SS] = NULL; + } + } + } + SuperDefs.clear(); +} + bool LiveVariables::runOnMachineFunction(MachineFunction &mf) { MF = &mf; MRI = &mf.getRegInfo(); @@ -537,11 +587,15 @@ bool LiveVariables::runOnMachineFunction(MachineFunction &mf) { MachineBasicBlock *MBB = *DFI; // Mark live-in registers as live-in. + SmallVector<unsigned, 4> Defs; + SmallVector<unsigned, 4> SuperDefs; for (MachineBasicBlock::const_livein_iterator II = MBB->livein_begin(), EE = MBB->livein_end(); II != EE; ++II) { assert(TargetRegisterInfo::isPhysicalRegister(*II) && "Cannot have a live-in virtual register!"); - HandlePhysRegDef(*II, 0); + HandlePhysRegDef(*II, 0, Defs, SuperDefs); + UpdatePhysRegDefs(0, Defs); + SuperDefs.clear(); } // Loop over all of the instructions, processing them. @@ -587,9 +641,13 @@ bool LiveVariables::runOnMachineFunction(MachineFunction &mf) { unsigned MOReg = DefRegs[i]; if (TargetRegisterInfo::isVirtualRegister(MOReg)) HandleVirtRegDef(MOReg, MI); - else if (!ReservedRegisters[MOReg]) - HandlePhysRegDef(MOReg, MI); + else if (!ReservedRegisters[MOReg]) { + HandlePhysRegDef(MOReg, MI, Defs, SuperDefs); + } } + + UpdateSuperRegDefs(MI, SuperDefs); + UpdatePhysRegDefs(MI, Defs); } // Handle any virtual assignments from PHI nodes which might be at the @@ -627,8 +685,11 @@ bool LiveVariables::runOnMachineFunction(MachineFunction &mf) { // Loop over PhysRegDef / PhysRegUse, killing any registers that are // available at the end of the basic block. for (unsigned i = 0; i != NumRegs; ++i) - if (PhysRegDef[i] || PhysRegUse[i]) - HandlePhysRegDef(i, 0); + if (PhysRegDef[i] || PhysRegUse[i]) { + HandlePhysRegDef(i, 0, Defs, SuperDefs); + UpdatePhysRegDefs(0, Defs); + SuperDefs.clear(); + } std::fill(PhysRegDef, PhysRegDef + NumRegs, (MachineInstr*)0); std::fill(PhysRegUse, PhysRegUse + NumRegs, (MachineInstr*)0); diff --git a/test/CodeGen/ARM/2009-09-22-LiveVariablesBug.ll b/test/CodeGen/ARM/2009-09-22-LiveVariablesBug.ll new file mode 100644 index 0000000..30931a2 --- /dev/null +++ b/test/CodeGen/ARM/2009-09-22-LiveVariablesBug.ll @@ -0,0 +1,23 @@ +; RUN: llc < %s -mtriple=armv7-none-linux-gnueabi -mattr=+neon + +; PR5024 + +%bar = type { %foo, %foo } +%foo = type { <4 x float> } + +declare arm_aapcs_vfpcc float @aaa(%foo* nocapture) nounwind readonly + +declare arm_aapcs_vfpcc %bar* @bbb(%bar*, <4 x float>, <4 x float>) nounwind + +define arm_aapcs_vfpcc void @ccc(i8* nocapture %pBuffer, i32 %numItems) nounwind { +entry: + br i1 undef, label %return, label %bb.nph + +bb.nph: ; preds = %entry + %0 = call arm_aapcs_vfpcc %bar* @bbb(%bar* undef, <4 x float> undef, <4 x float> undef) nounwind ; <%bar*> [#uses=0] + %1 = call arm_aapcs_vfpcc float @aaa(%foo* undef) nounwind ; <float> [#uses=0] + unreachable + +return: ; preds = %entry + ret void +} |