Index: lib/CodeGen/BranchFolding.h =================================================================== --- lib/CodeGen/BranchFolding.h +++ lib/CodeGen/BranchFolding.h @@ -14,6 +14,7 @@ #include "llvm/CodeGen/LivePhysRegs.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/Support/BlockFrequency.h" +#include #include namespace llvm { @@ -156,7 +157,10 @@ bool OptimizeBranches(MachineFunction &MF); bool OptimizeBlock(MachineBasicBlock *MBB); void RemoveDeadBlock(MachineBasicBlock *MBB); - bool OptimizeImpDefsBlock(MachineBasicBlock *MBB); + bool PurgeImpDefsInBlock(MachineBasicBlock *MBB, + std::set &ImpDefRegs); + bool RegenerateImpDefsInBlock(MachineBasicBlock *MBB, + std::set &ImpDefRegs); bool HoistCommonCode(MachineFunction &MF); bool HoistCommonCodeInSuccs(MachineBasicBlock *MBB); Index: lib/CodeGen/BranchFolding.cpp =================================================================== --- lib/CodeGen/BranchFolding.cpp +++ lib/CodeGen/BranchFolding.cpp @@ -25,6 +25,7 @@ #include "llvm/CodeGen/MachineBlockFrequencyInfo.h" #include "llvm/CodeGen/MachineBranchProbabilityInfo.h" #include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineJumpTableInfo.h" #include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/MachineLoopInfo.h" @@ -154,8 +155,9 @@ /// br /// This block can be optimized away later if the implicit instructions are /// removed. -bool BranchFolder::OptimizeImpDefsBlock(MachineBasicBlock *MBB) { - SmallSet ImpDefRegs; +bool BranchFolder::PurgeImpDefsInBlock(MachineBasicBlock *MBB, + std::set &ImpDefRegs) { + std::set LocalImpDefRegs; MachineBasicBlock::iterator I = MBB->begin(); while (I != MBB->end()) { if (!I->isImplicitDef()) @@ -164,13 +166,13 @@ if (TargetRegisterInfo::isPhysicalRegister(Reg)) { for (MCSubRegIterator SubRegs(Reg, TRI, /*IncludeSelf=*/true); SubRegs.isValid(); ++SubRegs) - ImpDefRegs.insert(*SubRegs); + LocalImpDefRegs.insert(*SubRegs); } else { - ImpDefRegs.insert(Reg); + LocalImpDefRegs.insert(Reg); } ++I; } - if (ImpDefRegs.empty()) + if (LocalImpDefRegs.empty()) return false; MachineBasicBlock::iterator FirstTerm = I; @@ -182,7 +184,7 @@ if (!MO.isReg() || !MO.isUse()) continue; unsigned Reg = MO.getReg(); - if (ImpDefRegs.count(Reg)) + if (LocalImpDefRegs.count(Reg)) return false; } ++I; @@ -195,9 +197,58 @@ MBB->erase(ImpDefMI); } + for (unsigned Reg : LocalImpDefRegs) + if (TargetRegisterInfo::isPhysicalRegister(Reg)) + ImpDefRegs.insert(Reg); + return true; } +bool BranchFolder::RegenerateImpDefsInBlock(MachineBasicBlock *MBB, + std::set &ImpDefRegs) { + SmallVector,8> Tmp; + MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo(); + + LiveRegs.init(TRI); + LiveRegs.addLiveIns(*MBB); + for (MachineInstr &MI : *MBB) + LiveRegs.stepForward(MI, Tmp); + + LivePhysRegs LiveOut(TRI); + LiveOut.addLiveOutsNoPristines(*MBB); + + auto HasSuperInSet = [this] (unsigned Reg, bool Self, LivePhysRegs &LPR) { + for (MCSuperRegIterator S(Reg, TRI, Self); S.isValid(); ++S) + if (LPR.contains(*S)) + return true; + return false; + }; + + // LivePhysRegs always adds/removes all subregisters of a given register. + // Create a set of "largest" registers, i.e. registers that have no super + // register also in the set. + std::set NeedLiveOut; + for (MCPhysReg Reg : LiveOut) { + if (HasSuperInSet(Reg, false, LiveOut)) + continue; + if (MRI.isReserved(Reg) || !ImpDefRegs.count(Reg)) + continue; + NeedLiveOut.insert(Reg); + } + + bool Changed = false; + MachineBasicBlock::iterator Term = MBB->getFirstTerminator(); + DebugLoc DL = MBB->findDebugLoc(Term); + for (MCPhysReg Reg : NeedLiveOut) { + if (HasSuperInSet(Reg, true, LiveRegs)) + continue; + BuildMI(*MBB, Term, DL, TII->get(TargetOpcode::IMPLICIT_DEF), Reg); + Changed = true; + } + + return Changed; +} + /// OptimizeFunction - Perhaps branch folding, tail merging and other /// CFG optimizations on the given function. Block placement changes the layout /// and may create new tail merging opportunities. @@ -221,6 +272,8 @@ if (!UpdateLiveIns) MRI.invalidateLiveness(); + std::set ImpDefRegs; + // Fix CFG. The later algorithms expect it to be right. bool MadeChange = false; for (MachineBasicBlock &MBB : MF) { @@ -228,7 +281,7 @@ SmallVector Cond; if (!TII->analyzeBranch(MBB, TBB, FBB, Cond, true)) MadeChange |= MBB.CorrectExtraCFGEdges(TBB, FBB, !Cond.empty()); - MadeChange |= OptimizeImpDefsBlock(&MBB); + MadeChange |= PurgeImpDefsInBlock(&MBB, ImpDefRegs); } // Recalculate funclet membership. @@ -246,6 +299,9 @@ MadeChange |= MadeChangeThisIteration; } + for (MachineBasicBlock &MBB : MF) + MadeChange |= RegenerateImpDefsInBlock(&MBB, ImpDefRegs); + // See if any jump tables have become dead as the code generator // did its thing. MachineJumpTableInfo *JTI = MF.getJumpTableInfo(); Index: test/CodeGen/Hexagon/branchfolder-keep-impdef.ll =================================================================== --- /dev/null +++ test/CodeGen/Hexagon/branchfolder-keep-impdef.ll @@ -0,0 +1,29 @@ +; RUN: llc -march=hexagon -verify-machineinstrs < %s | FileCheck %s +; +; Check that the testcase compiles successfully. Expect that if-conversion +; took place. +; CHECK-LABEL: fred: +; CHECK: if (!p0) r1 = memw(r0 + #0) + +target triple = "hexagon" + +define void @fred(i32 %p0) local_unnamed_addr align 2 { +b0: + br i1 undef, label %b1, label %b2 + +b1: ; preds = %b0 + %t0 = load i8*, i8** undef, align 4 + br label %b2 + +b2: ; preds = %b1, %b0 + %t1 = phi i8* [ %t0, %b1 ], [ undef, %b0 ] + %t2 = getelementptr inbounds i8, i8* %t1, i32 %p0 + tail call void @llvm.memmove.p0i8.p0i8.i32(i8* undef, i8* %t2, i32 undef, i32 1, i1 false) #1 + unreachable +} + +declare void @llvm.memmove.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i32, i1) #0 + +attributes #0 = { argmemonly nounwind } +attributes #1 = { nounwind } +