From: Evan Cheng Date: Fri, 19 Jan 2007 22:40:14 +0000 (+0000) Subject: GetRegForReload() now keeps track which registers have been considered and rejected... X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=3c82cab9aad8bd1ae7a9dd03548f721522db79f3;p=oota-llvm.git GetRegForReload() now keeps track which registers have been considered and rejected during its quest to find a suitable reload register. This avoids an infinite loop in case like this: t1 := op t2, t3 t2 <- assigned r0 for use by the reload but ended up reuse r1 t3 <- assigned r1 for use by the reload but ended up reuse r0 t1 <- desires r1 sees r1 is taken by t2, tries t2's reload register r0 sees r0 is taken by t3, tries t3's reload register r1 sees r1 is taken by t2, tries t2's reload register r0 ... git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@33382 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/VirtRegMap.cpp b/lib/CodeGen/VirtRegMap.cpp index 2c93e09e3f2..1d1f6f75cba 100644 --- a/lib/CodeGen/VirtRegMap.cpp +++ b/lib/CodeGen/VirtRegMap.cpp @@ -30,6 +30,7 @@ #include "llvm/ADT/Statistic.h" #include "llvm/ADT/STLExtras.h" #include +#include using namespace llvm; STATISTIC(NumSpills, "Number of register spills"); @@ -469,18 +470,23 @@ namespace { /// a new register to use, or evict the previous reload and use this reg. unsigned GetRegForReload(unsigned PhysReg, MachineInstr *MI, AvailableSpills &Spills, - std::map &MaybeDeadStores) { + std::map &MaybeDeadStores, + std::set &Rejected) { if (Reuses.empty()) return PhysReg; // This is most often empty. for (unsigned ro = 0, e = Reuses.size(); ro != e; ++ro) { ReusedOp &Op = Reuses[ro]; // If we find some other reuse that was supposed to use this register // exactly for its reload, we can change this reload to use ITS reload - // register. - if (Op.PhysRegReused == PhysReg) { + // register. That is, unless its reload register has already been + // considered and subsequently rejected because it has also been reused + // by another operand. + if (Op.PhysRegReused == PhysReg && + Rejected.count(Op.AssignedPhysReg) == 0) { // Yup, use the reload register that we didn't use before. - unsigned NewReg = Op.AssignedPhysReg; - return GetRegForReload(NewReg, MI, Spills, MaybeDeadStores); + unsigned NewReg = Op.AssignedPhysReg; + Rejected.insert(PhysReg); + return GetRegForReload(NewReg, MI, Spills, MaybeDeadStores, Rejected); } else { // Otherwise, we might also have a problem if a previously reused // value aliases the new register. If so, codegen the previous reload @@ -505,7 +511,7 @@ namespace { // register could hold a reuse. Check to see if it conflicts or // would prefer us to use a different register. unsigned NewPhysReg = GetRegForReload(NewOp.AssignedPhysReg, - MI, Spills, MaybeDeadStores); + MI, Spills, MaybeDeadStores, Rejected); MRI->loadRegFromStackSlot(*MBB, MI, NewPhysReg, NewOp.StackSlot, AliasRC); @@ -532,6 +538,24 @@ namespace { } return PhysReg; } + + /// GetRegForReload - Helper for the above GetRegForReload(). Add a + /// 'Rejected' set to remember which registers have been considered and + /// rejected for the reload. This avoids infinite looping in case like + /// this: + /// t1 := op t2, t3 + /// t2 <- assigned r0 for use by the reload but ended up reuse r1 + /// t3 <- assigned r1 for use by the reload but ended up reuse r0 + /// t1 <- desires r1 + /// sees r1 is taken by t2, tries t2's reload register r0 + /// sees r0 is taken by t3, tries t3's reload register r1 + /// sees r1 is taken by t2, tries t2's reload register r0 ... + unsigned GetRegForReload(unsigned PhysReg, MachineInstr *MI, + AvailableSpills &Spills, + std::map &MaybeDeadStores) { + std::set Rejected; + return GetRegForReload(PhysReg, MI, Spills, MaybeDeadStores, Rejected); + } }; } @@ -626,8 +650,8 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) { MI.getOperand(ti).isReg() && MI.getOperand(ti).getReg() == VirtReg) { // Okay, we have a two address operand. We can reuse this physreg as - // long as we are allowed to clobber the value and there is an earlier - // def that has already clobbered the physreg. + // long as we are allowed to clobber the value and there isn't an + // earlier def that has already clobbered the physreg. CanReuse = Spills.canClobberPhysReg(StackSlot) && !ReusedOperands.isClobbered(PhysReg); }