mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-11-23 00:20:25 +00:00
Do not consider a machine instruction that uses and defines the same
physical register as candidate for common subexpression elimination in MachineCSE. This fixes a bug on PowerPC in MultiSource/Applications/oggenc/oggenc caused by MachineCSE invalidly merging two separate DYNALLOC insns. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@167855 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -84,7 +84,8 @@ namespace {
|
|||||||
bool hasLivePhysRegDefUses(const MachineInstr *MI,
|
bool hasLivePhysRegDefUses(const MachineInstr *MI,
|
||||||
const MachineBasicBlock *MBB,
|
const MachineBasicBlock *MBB,
|
||||||
SmallSet<unsigned,8> &PhysRefs,
|
SmallSet<unsigned,8> &PhysRefs,
|
||||||
SmallVector<unsigned,2> &PhysDefs) const;
|
SmallVector<unsigned,2> &PhysDefs,
|
||||||
|
bool &PhysUseDef) const;
|
||||||
bool PhysRegDefsReach(MachineInstr *CSMI, MachineInstr *MI,
|
bool PhysRegDefsReach(MachineInstr *CSMI, MachineInstr *MI,
|
||||||
SmallSet<unsigned,8> &PhysRefs,
|
SmallSet<unsigned,8> &PhysRefs,
|
||||||
SmallVector<unsigned,2> &PhysDefs,
|
SmallVector<unsigned,2> &PhysDefs,
|
||||||
@@ -194,31 +195,52 @@ MachineCSE::isPhysDefTriviallyDead(unsigned Reg,
|
|||||||
bool MachineCSE::hasLivePhysRegDefUses(const MachineInstr *MI,
|
bool MachineCSE::hasLivePhysRegDefUses(const MachineInstr *MI,
|
||||||
const MachineBasicBlock *MBB,
|
const MachineBasicBlock *MBB,
|
||||||
SmallSet<unsigned,8> &PhysRefs,
|
SmallSet<unsigned,8> &PhysRefs,
|
||||||
SmallVector<unsigned,2> &PhysDefs) const{
|
SmallVector<unsigned,2> &PhysDefs,
|
||||||
MachineBasicBlock::const_iterator I = MI; I = llvm::next(I);
|
bool &PhysUseDef) const{
|
||||||
|
// First, add all uses to PhysRefs.
|
||||||
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
|
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
|
||||||
const MachineOperand &MO = MI->getOperand(i);
|
const MachineOperand &MO = MI->getOperand(i);
|
||||||
if (!MO.isReg())
|
if (!MO.isReg() || MO.isDef())
|
||||||
continue;
|
continue;
|
||||||
unsigned Reg = MO.getReg();
|
unsigned Reg = MO.getReg();
|
||||||
if (!Reg)
|
if (!Reg)
|
||||||
continue;
|
continue;
|
||||||
if (TargetRegisterInfo::isVirtualRegister(Reg))
|
if (TargetRegisterInfo::isVirtualRegister(Reg))
|
||||||
continue;
|
continue;
|
||||||
// If the def is dead, it's ok. But the def may not marked "dead". That's
|
|
||||||
// common since this pass is run before livevariables. We can scan
|
|
||||||
// forward a few instructions and check if it is obviously dead.
|
|
||||||
if (MO.isDef() &&
|
|
||||||
(MO.isDead() || isPhysDefTriviallyDead(Reg, I, MBB->end())))
|
|
||||||
continue;
|
|
||||||
// Reading constant physregs is ok.
|
// Reading constant physregs is ok.
|
||||||
if (!MRI->isConstantPhysReg(Reg, *MBB->getParent()))
|
if (!MRI->isConstantPhysReg(Reg, *MBB->getParent()))
|
||||||
for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI)
|
for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI)
|
||||||
PhysRefs.insert(*AI);
|
PhysRefs.insert(*AI);
|
||||||
if (MO.isDef())
|
}
|
||||||
|
|
||||||
|
// Next, collect all defs into PhysDefs. If any is already in PhysRefs
|
||||||
|
// (which currently contains only uses), set the PhysUseDef flag.
|
||||||
|
PhysUseDef = false;
|
||||||
|
MachineBasicBlock::const_iterator I = MI; I = llvm::next(I);
|
||||||
|
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
|
||||||
|
const MachineOperand &MO = MI->getOperand(i);
|
||||||
|
if (!MO.isReg() || !MO.isDef())
|
||||||
|
continue;
|
||||||
|
unsigned Reg = MO.getReg();
|
||||||
|
if (!Reg)
|
||||||
|
continue;
|
||||||
|
if (TargetRegisterInfo::isVirtualRegister(Reg))
|
||||||
|
continue;
|
||||||
|
// Check against PhysRefs even if the def is "dead".
|
||||||
|
if (PhysRefs.count(Reg))
|
||||||
|
PhysUseDef = true;
|
||||||
|
// If the def is dead, it's ok. But the def may not marked "dead". That's
|
||||||
|
// common since this pass is run before livevariables. We can scan
|
||||||
|
// forward a few instructions and check if it is obviously dead.
|
||||||
|
if (!MO.isDead() && !isPhysDefTriviallyDead(Reg, I, MBB->end()))
|
||||||
PhysDefs.push_back(Reg);
|
PhysDefs.push_back(Reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Finally, add all defs to PhysRefs as well.
|
||||||
|
for (unsigned i = 0, e = PhysDefs.size(); i != e; ++i)
|
||||||
|
for (MCRegAliasIterator AI(PhysDefs[i], TRI, true); AI.isValid(); ++AI)
|
||||||
|
PhysRefs.insert(*AI);
|
||||||
|
|
||||||
return !PhysRefs.empty();
|
return !PhysRefs.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -459,16 +481,22 @@ bool MachineCSE::ProcessBlock(MachineBasicBlock *MBB) {
|
|||||||
bool CrossMBBPhysDef = false;
|
bool CrossMBBPhysDef = false;
|
||||||
SmallSet<unsigned, 8> PhysRefs;
|
SmallSet<unsigned, 8> PhysRefs;
|
||||||
SmallVector<unsigned, 2> PhysDefs;
|
SmallVector<unsigned, 2> PhysDefs;
|
||||||
if (FoundCSE && hasLivePhysRegDefUses(MI, MBB, PhysRefs, PhysDefs)) {
|
bool PhysUseDef = false;
|
||||||
|
if (FoundCSE && hasLivePhysRegDefUses(MI, MBB, PhysRefs,
|
||||||
|
PhysDefs, PhysUseDef)) {
|
||||||
FoundCSE = false;
|
FoundCSE = false;
|
||||||
|
|
||||||
// ... Unless the CS is local or is in the sole predecessor block
|
// ... Unless the CS is local or is in the sole predecessor block
|
||||||
// and it also defines the physical register which is not clobbered
|
// and it also defines the physical register which is not clobbered
|
||||||
// in between and the physical register uses were not clobbered.
|
// in between and the physical register uses were not clobbered.
|
||||||
unsigned CSVN = VNT.lookup(MI);
|
// This can never be the case if the instruction both uses and
|
||||||
MachineInstr *CSMI = Exps[CSVN];
|
// defines the same physical register, which was detected above.
|
||||||
if (PhysRegDefsReach(CSMI, MI, PhysRefs, PhysDefs, CrossMBBPhysDef))
|
if (!PhysUseDef) {
|
||||||
FoundCSE = true;
|
unsigned CSVN = VNT.lookup(MI);
|
||||||
|
MachineInstr *CSMI = Exps[CSVN];
|
||||||
|
if (PhysRegDefsReach(CSMI, MI, PhysRefs, PhysDefs, CrossMBBPhysDef))
|
||||||
|
FoundCSE = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!FoundCSE) {
|
if (!FoundCSE) {
|
||||||
|
|||||||
18
test/CodeGen/PowerPC/2012-10-11-dynalloc.ll
Normal file
18
test/CodeGen/PowerPC/2012-10-11-dynalloc.ll
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
; RUN: llc < %s | FileCheck %s
|
||||||
|
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-v128:128:128-n32:64"
|
||||||
|
target triple = "powerpc64-unknown-linux-gnu"
|
||||||
|
|
||||||
|
define void @test(i64 %n) nounwind {
|
||||||
|
entry:
|
||||||
|
%0 = alloca i8, i64 %n, align 1
|
||||||
|
%1 = alloca i8, i64 %n, align 1
|
||||||
|
call void @use(i8* %0, i8* %1) nounwind
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @use(i8*, i8*)
|
||||||
|
|
||||||
|
; Check we actually have two instances of dynamic stack allocation,
|
||||||
|
; identified by the stdux used to update the back-chain link.
|
||||||
|
; CHECK: stdux
|
||||||
|
; CHECK: stdux
|
||||||
Reference in New Issue
Block a user