128233408SJack Styles //===- InitUndef.cpp - Initialize undef value to pseudo ----===// 228233408SJack Styles // 328233408SJack Styles // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 428233408SJack Styles // See https://llvm.org/LICENSE.txt for license information. 528233408SJack Styles // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 628233408SJack Styles // 728233408SJack Styles //===----------------------------------------------------------------------===// 828233408SJack Styles // 928233408SJack Styles // This file implements a function pass that initializes undef value to 1028233408SJack Styles // temporary pseudo instruction to prevent register allocation resulting in a 1128233408SJack Styles // constraint violated result for the particular instruction. It also rewrites 1228233408SJack Styles // the NoReg tied operand back to an IMPLICIT_DEF. 1328233408SJack Styles // 1428233408SJack Styles // Certain instructions have register overlapping constraints, and 1528233408SJack Styles // will cause illegal instruction trap if violated, we use early clobber to 1628233408SJack Styles // model this constraint, but it can't prevent register allocator allocating 1728233408SJack Styles // same or overlapped if the input register is undef value, so convert 1828233408SJack Styles // IMPLICIT_DEF to temporary pseudo instruction and remove it later could 1928233408SJack Styles // prevent that happen, it's not best way to resolve this, and it might 2028233408SJack Styles // change the order of program or increase the register pressure, so ideally we 2128233408SJack Styles // should model the constraint right, but before we model the constraint right, 2228233408SJack Styles // it's the only way to prevent that happen. 2328233408SJack Styles // 2428233408SJack Styles // When we enable the subregister liveness option, it will also trigger the same 2528233408SJack Styles // issue due to the partial of register is undef. If we pseudoinit the whole 2628233408SJack Styles // register, then it will generate redundant COPY instruction. Currently, it 2728233408SJack Styles // will generate INSERT_SUBREG to make sure the whole register is occupied 2828233408SJack Styles // when program encounter operation that has early-clobber constraint. 2928233408SJack Styles // 3028233408SJack Styles // 3128233408SJack Styles // See also: https://github.com/llvm/llvm-project/issues/50157 3228233408SJack Styles // 3328233408SJack Styles // Additionally, this pass rewrites tied operands of instructions 3428233408SJack Styles // from NoReg to IMPLICIT_DEF. (Not that this is a non-overlapping set of 3528233408SJack Styles // operands to the above.) We use NoReg to side step a MachineCSE 3628233408SJack Styles // optimization quality problem but need to convert back before 3728233408SJack Styles // TwoAddressInstruction. See pr64282 for context. 3828233408SJack Styles // 3928233408SJack Styles //===----------------------------------------------------------------------===// 4028233408SJack Styles 4128233408SJack Styles #include "llvm/ADT/SmallSet.h" 4228233408SJack Styles #include "llvm/ADT/SmallVector.h" 4328233408SJack Styles #include "llvm/CodeGen/DetectDeadLanes.h" 4428233408SJack Styles #include "llvm/CodeGen/MachineFunction.h" 4528233408SJack Styles #include "llvm/CodeGen/MachineFunctionPass.h" 4628233408SJack Styles #include "llvm/CodeGen/MachineRegisterInfo.h" 4728233408SJack Styles #include "llvm/CodeGen/TargetInstrInfo.h" 4828233408SJack Styles #include "llvm/CodeGen/TargetRegisterInfo.h" 4928233408SJack Styles #include "llvm/CodeGen/TargetSubtargetInfo.h" 5028233408SJack Styles #include "llvm/InitializePasses.h" 5128233408SJack Styles #include "llvm/MC/MCRegister.h" 5228233408SJack Styles #include "llvm/Pass.h" 5328233408SJack Styles #include "llvm/Support/Debug.h" 5428233408SJack Styles 5528233408SJack Styles using namespace llvm; 5628233408SJack Styles 5728233408SJack Styles #define DEBUG_TYPE "init-undef" 5828233408SJack Styles #define INIT_UNDEF_NAME "Init Undef Pass" 5928233408SJack Styles 6028233408SJack Styles namespace { 6128233408SJack Styles 6228233408SJack Styles class InitUndef : public MachineFunctionPass { 6328233408SJack Styles const TargetInstrInfo *TII; 6428233408SJack Styles MachineRegisterInfo *MRI; 6528233408SJack Styles const TargetSubtargetInfo *ST; 6628233408SJack Styles const TargetRegisterInfo *TRI; 6728233408SJack Styles 6828233408SJack Styles // Newly added vregs, assumed to be fully rewritten 6928233408SJack Styles SmallSet<Register, 8> NewRegs; 7028233408SJack Styles SmallVector<MachineInstr *, 8> DeadInsts; 7128233408SJack Styles 7228233408SJack Styles public: 7328233408SJack Styles static char ID; 7428233408SJack Styles 7528233408SJack Styles InitUndef() : MachineFunctionPass(ID) {} 7628233408SJack Styles bool runOnMachineFunction(MachineFunction &MF) override; 7728233408SJack Styles 7828233408SJack Styles void getAnalysisUsage(AnalysisUsage &AU) const override { 7928233408SJack Styles AU.setPreservesCFG(); 8028233408SJack Styles MachineFunctionPass::getAnalysisUsage(AU); 8128233408SJack Styles } 8228233408SJack Styles 8328233408SJack Styles StringRef getPassName() const override { return INIT_UNDEF_NAME; } 8428233408SJack Styles 8528233408SJack Styles private: 8628233408SJack Styles bool processBasicBlock(MachineFunction &MF, MachineBasicBlock &MBB, 87e2723c2aSNikita Popov const DeadLaneDetector *DLD); 8828233408SJack Styles bool handleSubReg(MachineFunction &MF, MachineInstr &MI, 8928233408SJack Styles const DeadLaneDetector &DLD); 9028233408SJack Styles bool fixupIllOperand(MachineInstr *MI, MachineOperand &MO); 9128233408SJack Styles bool handleReg(MachineInstr *MI); 9228233408SJack Styles }; 9328233408SJack Styles 9428233408SJack Styles } // end anonymous namespace 9528233408SJack Styles 9628233408SJack Styles char InitUndef::ID = 0; 9728233408SJack Styles INITIALIZE_PASS(InitUndef, DEBUG_TYPE, INIT_UNDEF_NAME, false, false) 9828233408SJack Styles char &llvm::InitUndefID = InitUndef::ID; 9928233408SJack Styles 10028233408SJack Styles static bool isEarlyClobberMI(MachineInstr &MI) { 10171837718SNikita Popov return llvm::any_of(MI.all_defs(), [](const MachineOperand &DefMO) { 10228233408SJack Styles return DefMO.isReg() && DefMO.isEarlyClobber(); 10328233408SJack Styles }); 10428233408SJack Styles } 10528233408SJack Styles 10628233408SJack Styles static bool findImplictDefMIFromReg(Register Reg, MachineRegisterInfo *MRI) { 10728233408SJack Styles for (auto &DefMI : MRI->def_instructions(Reg)) { 10828233408SJack Styles if (DefMI.getOpcode() == TargetOpcode::IMPLICIT_DEF) 10928233408SJack Styles return true; 11028233408SJack Styles } 11128233408SJack Styles return false; 11228233408SJack Styles } 11328233408SJack Styles 11428233408SJack Styles bool InitUndef::handleReg(MachineInstr *MI) { 11528233408SJack Styles bool Changed = false; 11628233408SJack Styles for (auto &UseMO : MI->uses()) { 11728233408SJack Styles if (!UseMO.isReg()) 11828233408SJack Styles continue; 11928233408SJack Styles if (UseMO.isTied()) 12028233408SJack Styles continue; 12128233408SJack Styles if (!UseMO.getReg().isVirtual()) 12228233408SJack Styles continue; 12328233408SJack Styles 12428233408SJack Styles if (UseMO.isUndef() || findImplictDefMIFromReg(UseMO.getReg(), MRI)) 12528233408SJack Styles Changed |= fixupIllOperand(MI, UseMO); 12628233408SJack Styles } 12728233408SJack Styles return Changed; 12828233408SJack Styles } 12928233408SJack Styles 13028233408SJack Styles bool InitUndef::handleSubReg(MachineFunction &MF, MachineInstr &MI, 13128233408SJack Styles const DeadLaneDetector &DLD) { 13228233408SJack Styles bool Changed = false; 13328233408SJack Styles 13428233408SJack Styles for (MachineOperand &UseMO : MI.uses()) { 13528233408SJack Styles if (!UseMO.isReg()) 13628233408SJack Styles continue; 13728233408SJack Styles if (!UseMO.getReg().isVirtual()) 13828233408SJack Styles continue; 13928233408SJack Styles if (UseMO.isTied()) 14028233408SJack Styles continue; 14128233408SJack Styles 14228233408SJack Styles Register Reg = UseMO.getReg(); 14328233408SJack Styles if (NewRegs.count(Reg)) 14428233408SJack Styles continue; 14528233408SJack Styles DeadLaneDetector::VRegInfo Info = 14628233408SJack Styles DLD.getVRegInfo(Register::virtReg2Index(Reg)); 14728233408SJack Styles 14828233408SJack Styles if (Info.UsedLanes == Info.DefinedLanes) 14928233408SJack Styles continue; 15028233408SJack Styles 1511e3a24d2SNikita Popov const TargetRegisterClass *TargetRegClass = MRI->getRegClass(Reg); 15228233408SJack Styles 15328233408SJack Styles LaneBitmask NeedDef = Info.UsedLanes & ~Info.DefinedLanes; 15428233408SJack Styles 15528233408SJack Styles LLVM_DEBUG({ 15628233408SJack Styles dbgs() << "Instruction has undef subregister.\n"; 15728233408SJack Styles dbgs() << printReg(Reg, nullptr) 15828233408SJack Styles << " Used: " << PrintLaneMask(Info.UsedLanes) 15928233408SJack Styles << " Def: " << PrintLaneMask(Info.DefinedLanes) 16028233408SJack Styles << " Need Def: " << PrintLaneMask(NeedDef) << "\n"; 16128233408SJack Styles }); 16228233408SJack Styles 16328233408SJack Styles SmallVector<unsigned> SubRegIndexNeedInsert; 164*0d71b3e4SJay Foad TRI->getCoveringSubRegIndexes(TargetRegClass, NeedDef, 16528233408SJack Styles SubRegIndexNeedInsert); 16628233408SJack Styles 16761653f8eSSander de Smalen // It's not possible to create the INIT_UNDEF when there is no register 16861653f8eSSander de Smalen // class associated for the subreg. This may happen for artificial subregs 16961653f8eSSander de Smalen // that are not directly addressable. 17061653f8eSSander de Smalen if (any_of(SubRegIndexNeedInsert, [&](unsigned Ind) -> bool { 17161653f8eSSander de Smalen return !TRI->getSubRegisterClass(TargetRegClass, Ind); 17261653f8eSSander de Smalen })) 17361653f8eSSander de Smalen continue; 17461653f8eSSander de Smalen 17528233408SJack Styles Register LatestReg = Reg; 17628233408SJack Styles for (auto ind : SubRegIndexNeedInsert) { 17728233408SJack Styles Changed = true; 1781e3a24d2SNikita Popov const TargetRegisterClass *SubRegClass = 1791e3a24d2SNikita Popov TRI->getSubRegisterClass(TargetRegClass, ind); 18028233408SJack Styles Register TmpInitSubReg = MRI->createVirtualRegister(SubRegClass); 18128233408SJack Styles LLVM_DEBUG(dbgs() << "Register Class ID" << SubRegClass->getID() << "\n"); 18228233408SJack Styles BuildMI(*MI.getParent(), &MI, MI.getDebugLoc(), 183f0062462SNikita Popov TII->get(TargetOpcode::INIT_UNDEF), TmpInitSubReg); 18428233408SJack Styles Register NewReg = MRI->createVirtualRegister(TargetRegClass); 18528233408SJack Styles BuildMI(*MI.getParent(), &MI, MI.getDebugLoc(), 18628233408SJack Styles TII->get(TargetOpcode::INSERT_SUBREG), NewReg) 18728233408SJack Styles .addReg(LatestReg) 18828233408SJack Styles .addReg(TmpInitSubReg) 18928233408SJack Styles .addImm(ind); 19028233408SJack Styles LatestReg = NewReg; 19128233408SJack Styles } 19228233408SJack Styles 19328233408SJack Styles UseMO.setReg(LatestReg); 19428233408SJack Styles } 19528233408SJack Styles 19628233408SJack Styles return Changed; 19728233408SJack Styles } 19828233408SJack Styles 19928233408SJack Styles bool InitUndef::fixupIllOperand(MachineInstr *MI, MachineOperand &MO) { 20028233408SJack Styles 20128233408SJack Styles LLVM_DEBUG( 20228233408SJack Styles dbgs() << "Emitting PseudoInitUndef Instruction for implicit register " 203cd3667d1SCraig Topper << printReg(MO.getReg()) << '\n'); 20428233408SJack Styles 2051e3a24d2SNikita Popov const TargetRegisterClass *TargetRegClass = MRI->getRegClass(MO.getReg()); 20628233408SJack Styles LLVM_DEBUG(dbgs() << "Register Class ID" << TargetRegClass->getID() << "\n"); 20728233408SJack Styles Register NewReg = MRI->createVirtualRegister(TargetRegClass); 208f0062462SNikita Popov BuildMI(*MI->getParent(), MI, MI->getDebugLoc(), 209f0062462SNikita Popov TII->get(TargetOpcode::INIT_UNDEF), NewReg); 21028233408SJack Styles MO.setReg(NewReg); 21128233408SJack Styles if (MO.isUndef()) 21228233408SJack Styles MO.setIsUndef(false); 21328233408SJack Styles return true; 21428233408SJack Styles } 21528233408SJack Styles 21628233408SJack Styles bool InitUndef::processBasicBlock(MachineFunction &MF, MachineBasicBlock &MBB, 217e2723c2aSNikita Popov const DeadLaneDetector *DLD) { 21828233408SJack Styles bool Changed = false; 21928233408SJack Styles for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) { 22028233408SJack Styles MachineInstr &MI = *I; 22128233408SJack Styles 22228233408SJack Styles // If we used NoReg to represent the passthru, switch this back to being 22328233408SJack Styles // an IMPLICIT_DEF before TwoAddressInstructions. 22428233408SJack Styles unsigned UseOpIdx; 22528233408SJack Styles if (MI.getNumDefs() != 0 && MI.isRegTiedToUseOperand(0, &UseOpIdx)) { 22628233408SJack Styles MachineOperand &UseMO = MI.getOperand(UseOpIdx); 22728233408SJack Styles if (UseMO.getReg() == MCRegister::NoRegister) { 22828233408SJack Styles const TargetRegisterClass *RC = 22928233408SJack Styles TII->getRegClass(MI.getDesc(), UseOpIdx, TRI, MF); 23028233408SJack Styles Register NewDest = MRI->createVirtualRegister(RC); 23128233408SJack Styles // We don't have a way to update dead lanes, so keep track of the 23228233408SJack Styles // new register so that we avoid querying it later. 23328233408SJack Styles NewRegs.insert(NewDest); 23428233408SJack Styles BuildMI(MBB, I, I->getDebugLoc(), TII->get(TargetOpcode::IMPLICIT_DEF), 23528233408SJack Styles NewDest); 23628233408SJack Styles UseMO.setReg(NewDest); 23728233408SJack Styles Changed = true; 23828233408SJack Styles } 23928233408SJack Styles } 24028233408SJack Styles 24128233408SJack Styles if (isEarlyClobberMI(MI)) { 242706e1975SDavid Green if (MRI->subRegLivenessEnabled()) 243e2723c2aSNikita Popov Changed |= handleSubReg(MF, MI, *DLD); 24428233408SJack Styles Changed |= handleReg(&MI); 24528233408SJack Styles } 24628233408SJack Styles } 24728233408SJack Styles return Changed; 24828233408SJack Styles } 24928233408SJack Styles 25028233408SJack Styles bool InitUndef::runOnMachineFunction(MachineFunction &MF) { 25128233408SJack Styles ST = &MF.getSubtarget(); 25228233408SJack Styles 253dfa54298SNikita Popov // The pass is only needed if early-clobber defs and undef ops cannot be 254dfa54298SNikita Popov // allocated to the same register. 255dfa54298SNikita Popov if (!ST->requiresDisjointEarlyClobberAndUndef()) 25628233408SJack Styles return false; 25728233408SJack Styles 25828233408SJack Styles MRI = &MF.getRegInfo(); 25928233408SJack Styles TII = ST->getInstrInfo(); 26028233408SJack Styles TRI = MRI->getTargetRegisterInfo(); 26128233408SJack Styles 26228233408SJack Styles bool Changed = false; 263e2723c2aSNikita Popov std::unique_ptr<DeadLaneDetector> DLD; 264e2723c2aSNikita Popov if (MRI->subRegLivenessEnabled()) { 265e2723c2aSNikita Popov DLD = std::make_unique<DeadLaneDetector>(MRI, TRI); 266e2723c2aSNikita Popov DLD->computeSubRegisterLaneBitInfo(); 267e2723c2aSNikita Popov } 26828233408SJack Styles 26928233408SJack Styles for (MachineBasicBlock &BB : MF) 270e2723c2aSNikita Popov Changed |= processBasicBlock(MF, BB, DLD.get()); 27128233408SJack Styles 27228233408SJack Styles for (auto *DeadMI : DeadInsts) 27328233408SJack Styles DeadMI->eraseFromParent(); 27428233408SJack Styles DeadInsts.clear(); 275bf8101e4SJoe Faulls NewRegs.clear(); 27628233408SJack Styles 27728233408SJack Styles return Changed; 27828233408SJack Styles } 279