1*0fca6ea1SDimitry Andric //===- InitUndef.cpp - Initialize undef value to pseudo ----===// 2*0fca6ea1SDimitry Andric // 3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0fca6ea1SDimitry Andric // 7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 8*0fca6ea1SDimitry Andric // 9*0fca6ea1SDimitry Andric // This file implements a function pass that initializes undef value to 10*0fca6ea1SDimitry Andric // temporary pseudo instruction to prevent register allocation resulting in a 11*0fca6ea1SDimitry Andric // constraint violated result for the particular instruction. It also rewrites 12*0fca6ea1SDimitry Andric // the NoReg tied operand back to an IMPLICIT_DEF. 13*0fca6ea1SDimitry Andric // 14*0fca6ea1SDimitry Andric // Certain instructions have register overlapping constraints, and 15*0fca6ea1SDimitry Andric // will cause illegal instruction trap if violated, we use early clobber to 16*0fca6ea1SDimitry Andric // model this constraint, but it can't prevent register allocator allocating 17*0fca6ea1SDimitry Andric // same or overlapped if the input register is undef value, so convert 18*0fca6ea1SDimitry Andric // IMPLICIT_DEF to temporary pseudo instruction and remove it later could 19*0fca6ea1SDimitry Andric // prevent that happen, it's not best way to resolve this, and it might 20*0fca6ea1SDimitry Andric // change the order of program or increase the register pressure, so ideally we 21*0fca6ea1SDimitry Andric // should model the constraint right, but before we model the constraint right, 22*0fca6ea1SDimitry Andric // it's the only way to prevent that happen. 23*0fca6ea1SDimitry Andric // 24*0fca6ea1SDimitry Andric // When we enable the subregister liveness option, it will also trigger the same 25*0fca6ea1SDimitry Andric // issue due to the partial of register is undef. If we pseudoinit the whole 26*0fca6ea1SDimitry Andric // register, then it will generate redundant COPY instruction. Currently, it 27*0fca6ea1SDimitry Andric // will generate INSERT_SUBREG to make sure the whole register is occupied 28*0fca6ea1SDimitry Andric // when program encounter operation that has early-clobber constraint. 29*0fca6ea1SDimitry Andric // 30*0fca6ea1SDimitry Andric // 31*0fca6ea1SDimitry Andric // See also: https://github.com/llvm/llvm-project/issues/50157 32*0fca6ea1SDimitry Andric // 33*0fca6ea1SDimitry Andric // Additionally, this pass rewrites tied operands of instructions 34*0fca6ea1SDimitry Andric // from NoReg to IMPLICIT_DEF. (Not that this is a non-overlapping set of 35*0fca6ea1SDimitry Andric // operands to the above.) We use NoReg to side step a MachineCSE 36*0fca6ea1SDimitry Andric // optimization quality problem but need to convert back before 37*0fca6ea1SDimitry Andric // TwoAddressInstruction. See pr64282 for context. 38*0fca6ea1SDimitry Andric // 39*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 40*0fca6ea1SDimitry Andric 41*0fca6ea1SDimitry Andric #include "llvm/ADT/SmallSet.h" 42*0fca6ea1SDimitry Andric #include "llvm/ADT/SmallVector.h" 43*0fca6ea1SDimitry Andric #include "llvm/CodeGen/DetectDeadLanes.h" 44*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 45*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 46*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 47*0fca6ea1SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h" 48*0fca6ea1SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h" 49*0fca6ea1SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h" 50*0fca6ea1SDimitry Andric #include "llvm/InitializePasses.h" 51*0fca6ea1SDimitry Andric #include "llvm/MC/MCRegister.h" 52*0fca6ea1SDimitry Andric #include "llvm/Pass.h" 53*0fca6ea1SDimitry Andric #include "llvm/Support/Debug.h" 54*0fca6ea1SDimitry Andric 55*0fca6ea1SDimitry Andric using namespace llvm; 56*0fca6ea1SDimitry Andric 57*0fca6ea1SDimitry Andric #define DEBUG_TYPE "init-undef" 58*0fca6ea1SDimitry Andric #define INIT_UNDEF_NAME "Init Undef Pass" 59*0fca6ea1SDimitry Andric 60*0fca6ea1SDimitry Andric namespace { 61*0fca6ea1SDimitry Andric 62*0fca6ea1SDimitry Andric class InitUndef : public MachineFunctionPass { 63*0fca6ea1SDimitry Andric const TargetInstrInfo *TII; 64*0fca6ea1SDimitry Andric MachineRegisterInfo *MRI; 65*0fca6ea1SDimitry Andric const TargetSubtargetInfo *ST; 66*0fca6ea1SDimitry Andric const TargetRegisterInfo *TRI; 67*0fca6ea1SDimitry Andric 68*0fca6ea1SDimitry Andric // Newly added vregs, assumed to be fully rewritten 69*0fca6ea1SDimitry Andric SmallSet<Register, 8> NewRegs; 70*0fca6ea1SDimitry Andric SmallVector<MachineInstr *, 8> DeadInsts; 71*0fca6ea1SDimitry Andric 72*0fca6ea1SDimitry Andric public: 73*0fca6ea1SDimitry Andric static char ID; 74*0fca6ea1SDimitry Andric 75*0fca6ea1SDimitry Andric InitUndef() : MachineFunctionPass(ID) {} 76*0fca6ea1SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override; 77*0fca6ea1SDimitry Andric 78*0fca6ea1SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 79*0fca6ea1SDimitry Andric AU.setPreservesCFG(); 80*0fca6ea1SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 81*0fca6ea1SDimitry Andric } 82*0fca6ea1SDimitry Andric 83*0fca6ea1SDimitry Andric StringRef getPassName() const override { return INIT_UNDEF_NAME; } 84*0fca6ea1SDimitry Andric 85*0fca6ea1SDimitry Andric private: 86*0fca6ea1SDimitry Andric bool processBasicBlock(MachineFunction &MF, MachineBasicBlock &MBB, 87*0fca6ea1SDimitry Andric const DeadLaneDetector &DLD); 88*0fca6ea1SDimitry Andric bool handleSubReg(MachineFunction &MF, MachineInstr &MI, 89*0fca6ea1SDimitry Andric const DeadLaneDetector &DLD); 90*0fca6ea1SDimitry Andric bool fixupIllOperand(MachineInstr *MI, MachineOperand &MO); 91*0fca6ea1SDimitry Andric bool handleReg(MachineInstr *MI); 92*0fca6ea1SDimitry Andric }; 93*0fca6ea1SDimitry Andric 94*0fca6ea1SDimitry Andric } // end anonymous namespace 95*0fca6ea1SDimitry Andric 96*0fca6ea1SDimitry Andric char InitUndef::ID = 0; 97*0fca6ea1SDimitry Andric INITIALIZE_PASS(InitUndef, DEBUG_TYPE, INIT_UNDEF_NAME, false, false) 98*0fca6ea1SDimitry Andric char &llvm::InitUndefID = InitUndef::ID; 99*0fca6ea1SDimitry Andric 100*0fca6ea1SDimitry Andric static bool isEarlyClobberMI(MachineInstr &MI) { 101*0fca6ea1SDimitry Andric return llvm::any_of(MI.defs(), [](const MachineOperand &DefMO) { 102*0fca6ea1SDimitry Andric return DefMO.isReg() && DefMO.isEarlyClobber(); 103*0fca6ea1SDimitry Andric }); 104*0fca6ea1SDimitry Andric } 105*0fca6ea1SDimitry Andric 106*0fca6ea1SDimitry Andric static bool findImplictDefMIFromReg(Register Reg, MachineRegisterInfo *MRI) { 107*0fca6ea1SDimitry Andric for (auto &DefMI : MRI->def_instructions(Reg)) { 108*0fca6ea1SDimitry Andric if (DefMI.getOpcode() == TargetOpcode::IMPLICIT_DEF) 109*0fca6ea1SDimitry Andric return true; 110*0fca6ea1SDimitry Andric } 111*0fca6ea1SDimitry Andric return false; 112*0fca6ea1SDimitry Andric } 113*0fca6ea1SDimitry Andric 114*0fca6ea1SDimitry Andric bool InitUndef::handleReg(MachineInstr *MI) { 115*0fca6ea1SDimitry Andric bool Changed = false; 116*0fca6ea1SDimitry Andric for (auto &UseMO : MI->uses()) { 117*0fca6ea1SDimitry Andric if (!UseMO.isReg()) 118*0fca6ea1SDimitry Andric continue; 119*0fca6ea1SDimitry Andric if (UseMO.isTied()) 120*0fca6ea1SDimitry Andric continue; 121*0fca6ea1SDimitry Andric if (!UseMO.getReg().isVirtual()) 122*0fca6ea1SDimitry Andric continue; 123*0fca6ea1SDimitry Andric if (!TRI->doesRegClassHavePseudoInitUndef(MRI->getRegClass(UseMO.getReg()))) 124*0fca6ea1SDimitry Andric continue; 125*0fca6ea1SDimitry Andric 126*0fca6ea1SDimitry Andric if (UseMO.isUndef() || findImplictDefMIFromReg(UseMO.getReg(), MRI)) 127*0fca6ea1SDimitry Andric Changed |= fixupIllOperand(MI, UseMO); 128*0fca6ea1SDimitry Andric } 129*0fca6ea1SDimitry Andric return Changed; 130*0fca6ea1SDimitry Andric } 131*0fca6ea1SDimitry Andric 132*0fca6ea1SDimitry Andric bool InitUndef::handleSubReg(MachineFunction &MF, MachineInstr &MI, 133*0fca6ea1SDimitry Andric const DeadLaneDetector &DLD) { 134*0fca6ea1SDimitry Andric bool Changed = false; 135*0fca6ea1SDimitry Andric 136*0fca6ea1SDimitry Andric for (MachineOperand &UseMO : MI.uses()) { 137*0fca6ea1SDimitry Andric if (!UseMO.isReg()) 138*0fca6ea1SDimitry Andric continue; 139*0fca6ea1SDimitry Andric if (!UseMO.getReg().isVirtual()) 140*0fca6ea1SDimitry Andric continue; 141*0fca6ea1SDimitry Andric if (UseMO.isTied()) 142*0fca6ea1SDimitry Andric continue; 143*0fca6ea1SDimitry Andric if (!TRI->doesRegClassHavePseudoInitUndef(MRI->getRegClass(UseMO.getReg()))) 144*0fca6ea1SDimitry Andric continue; 145*0fca6ea1SDimitry Andric 146*0fca6ea1SDimitry Andric Register Reg = UseMO.getReg(); 147*0fca6ea1SDimitry Andric if (NewRegs.count(Reg)) 148*0fca6ea1SDimitry Andric continue; 149*0fca6ea1SDimitry Andric DeadLaneDetector::VRegInfo Info = 150*0fca6ea1SDimitry Andric DLD.getVRegInfo(Register::virtReg2Index(Reg)); 151*0fca6ea1SDimitry Andric 152*0fca6ea1SDimitry Andric if (Info.UsedLanes == Info.DefinedLanes) 153*0fca6ea1SDimitry Andric continue; 154*0fca6ea1SDimitry Andric 155*0fca6ea1SDimitry Andric const TargetRegisterClass *TargetRegClass = 156*0fca6ea1SDimitry Andric TRI->getLargestSuperClass(MRI->getRegClass(Reg)); 157*0fca6ea1SDimitry Andric 158*0fca6ea1SDimitry Andric LaneBitmask NeedDef = Info.UsedLanes & ~Info.DefinedLanes; 159*0fca6ea1SDimitry Andric 160*0fca6ea1SDimitry Andric LLVM_DEBUG({ 161*0fca6ea1SDimitry Andric dbgs() << "Instruction has undef subregister.\n"; 162*0fca6ea1SDimitry Andric dbgs() << printReg(Reg, nullptr) 163*0fca6ea1SDimitry Andric << " Used: " << PrintLaneMask(Info.UsedLanes) 164*0fca6ea1SDimitry Andric << " Def: " << PrintLaneMask(Info.DefinedLanes) 165*0fca6ea1SDimitry Andric << " Need Def: " << PrintLaneMask(NeedDef) << "\n"; 166*0fca6ea1SDimitry Andric }); 167*0fca6ea1SDimitry Andric 168*0fca6ea1SDimitry Andric SmallVector<unsigned> SubRegIndexNeedInsert; 169*0fca6ea1SDimitry Andric TRI->getCoveringSubRegIndexes(*MRI, TargetRegClass, NeedDef, 170*0fca6ea1SDimitry Andric SubRegIndexNeedInsert); 171*0fca6ea1SDimitry Andric 172*0fca6ea1SDimitry Andric Register LatestReg = Reg; 173*0fca6ea1SDimitry Andric for (auto ind : SubRegIndexNeedInsert) { 174*0fca6ea1SDimitry Andric Changed = true; 175*0fca6ea1SDimitry Andric const TargetRegisterClass *SubRegClass = TRI->getLargestSuperClass( 176*0fca6ea1SDimitry Andric TRI->getSubRegisterClass(TargetRegClass, ind)); 177*0fca6ea1SDimitry Andric Register TmpInitSubReg = MRI->createVirtualRegister(SubRegClass); 178*0fca6ea1SDimitry Andric LLVM_DEBUG(dbgs() << "Register Class ID" << SubRegClass->getID() << "\n"); 179*0fca6ea1SDimitry Andric BuildMI(*MI.getParent(), &MI, MI.getDebugLoc(), 180*0fca6ea1SDimitry Andric TII->get(TII->getUndefInitOpcode(SubRegClass->getID())), 181*0fca6ea1SDimitry Andric TmpInitSubReg); 182*0fca6ea1SDimitry Andric Register NewReg = MRI->createVirtualRegister(TargetRegClass); 183*0fca6ea1SDimitry Andric BuildMI(*MI.getParent(), &MI, MI.getDebugLoc(), 184*0fca6ea1SDimitry Andric TII->get(TargetOpcode::INSERT_SUBREG), NewReg) 185*0fca6ea1SDimitry Andric .addReg(LatestReg) 186*0fca6ea1SDimitry Andric .addReg(TmpInitSubReg) 187*0fca6ea1SDimitry Andric .addImm(ind); 188*0fca6ea1SDimitry Andric LatestReg = NewReg; 189*0fca6ea1SDimitry Andric } 190*0fca6ea1SDimitry Andric 191*0fca6ea1SDimitry Andric UseMO.setReg(LatestReg); 192*0fca6ea1SDimitry Andric } 193*0fca6ea1SDimitry Andric 194*0fca6ea1SDimitry Andric return Changed; 195*0fca6ea1SDimitry Andric } 196*0fca6ea1SDimitry Andric 197*0fca6ea1SDimitry Andric bool InitUndef::fixupIllOperand(MachineInstr *MI, MachineOperand &MO) { 198*0fca6ea1SDimitry Andric 199*0fca6ea1SDimitry Andric LLVM_DEBUG( 200*0fca6ea1SDimitry Andric dbgs() << "Emitting PseudoInitUndef Instruction for implicit register " 201*0fca6ea1SDimitry Andric << MO.getReg() << '\n'); 202*0fca6ea1SDimitry Andric 203*0fca6ea1SDimitry Andric const TargetRegisterClass *TargetRegClass = 204*0fca6ea1SDimitry Andric TRI->getLargestSuperClass(MRI->getRegClass(MO.getReg())); 205*0fca6ea1SDimitry Andric LLVM_DEBUG(dbgs() << "Register Class ID" << TargetRegClass->getID() << "\n"); 206*0fca6ea1SDimitry Andric unsigned Opcode = TII->getUndefInitOpcode(TargetRegClass->getID()); 207*0fca6ea1SDimitry Andric Register NewReg = MRI->createVirtualRegister(TargetRegClass); 208*0fca6ea1SDimitry Andric BuildMI(*MI->getParent(), MI, MI->getDebugLoc(), TII->get(Opcode), NewReg); 209*0fca6ea1SDimitry Andric MO.setReg(NewReg); 210*0fca6ea1SDimitry Andric if (MO.isUndef()) 211*0fca6ea1SDimitry Andric MO.setIsUndef(false); 212*0fca6ea1SDimitry Andric return true; 213*0fca6ea1SDimitry Andric } 214*0fca6ea1SDimitry Andric 215*0fca6ea1SDimitry Andric bool InitUndef::processBasicBlock(MachineFunction &MF, MachineBasicBlock &MBB, 216*0fca6ea1SDimitry Andric const DeadLaneDetector &DLD) { 217*0fca6ea1SDimitry Andric bool Changed = false; 218*0fca6ea1SDimitry Andric for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) { 219*0fca6ea1SDimitry Andric MachineInstr &MI = *I; 220*0fca6ea1SDimitry Andric 221*0fca6ea1SDimitry Andric // If we used NoReg to represent the passthru, switch this back to being 222*0fca6ea1SDimitry Andric // an IMPLICIT_DEF before TwoAddressInstructions. 223*0fca6ea1SDimitry Andric unsigned UseOpIdx; 224*0fca6ea1SDimitry Andric if (MI.getNumDefs() != 0 && MI.isRegTiedToUseOperand(0, &UseOpIdx)) { 225*0fca6ea1SDimitry Andric MachineOperand &UseMO = MI.getOperand(UseOpIdx); 226*0fca6ea1SDimitry Andric if (UseMO.getReg() == MCRegister::NoRegister) { 227*0fca6ea1SDimitry Andric const TargetRegisterClass *RC = 228*0fca6ea1SDimitry Andric TII->getRegClass(MI.getDesc(), UseOpIdx, TRI, MF); 229*0fca6ea1SDimitry Andric Register NewDest = MRI->createVirtualRegister(RC); 230*0fca6ea1SDimitry Andric // We don't have a way to update dead lanes, so keep track of the 231*0fca6ea1SDimitry Andric // new register so that we avoid querying it later. 232*0fca6ea1SDimitry Andric NewRegs.insert(NewDest); 233*0fca6ea1SDimitry Andric BuildMI(MBB, I, I->getDebugLoc(), TII->get(TargetOpcode::IMPLICIT_DEF), 234*0fca6ea1SDimitry Andric NewDest); 235*0fca6ea1SDimitry Andric UseMO.setReg(NewDest); 236*0fca6ea1SDimitry Andric Changed = true; 237*0fca6ea1SDimitry Andric } 238*0fca6ea1SDimitry Andric } 239*0fca6ea1SDimitry Andric 240*0fca6ea1SDimitry Andric if (isEarlyClobberMI(MI)) { 241*0fca6ea1SDimitry Andric if (MRI->subRegLivenessEnabled()) 242*0fca6ea1SDimitry Andric Changed |= handleSubReg(MF, MI, DLD); 243*0fca6ea1SDimitry Andric Changed |= handleReg(&MI); 244*0fca6ea1SDimitry Andric } 245*0fca6ea1SDimitry Andric } 246*0fca6ea1SDimitry Andric return Changed; 247*0fca6ea1SDimitry Andric } 248*0fca6ea1SDimitry Andric 249*0fca6ea1SDimitry Andric bool InitUndef::runOnMachineFunction(MachineFunction &MF) { 250*0fca6ea1SDimitry Andric ST = &MF.getSubtarget(); 251*0fca6ea1SDimitry Andric 252*0fca6ea1SDimitry Andric // supportsInitUndef is implemented to reflect if an architecture has support 253*0fca6ea1SDimitry Andric // for the InitUndef pass. Support comes from having the relevant Pseudo 254*0fca6ea1SDimitry Andric // instructions that can be used to initialize the register. The function 255*0fca6ea1SDimitry Andric // returns false by default so requires an implementation per architecture. 256*0fca6ea1SDimitry Andric // Support can be added by overriding the function in a way that best fits 257*0fca6ea1SDimitry Andric // the architecture. 258*0fca6ea1SDimitry Andric if (!ST->supportsInitUndef()) 259*0fca6ea1SDimitry Andric return false; 260*0fca6ea1SDimitry Andric 261*0fca6ea1SDimitry Andric MRI = &MF.getRegInfo(); 262*0fca6ea1SDimitry Andric TII = ST->getInstrInfo(); 263*0fca6ea1SDimitry Andric TRI = MRI->getTargetRegisterInfo(); 264*0fca6ea1SDimitry Andric 265*0fca6ea1SDimitry Andric bool Changed = false; 266*0fca6ea1SDimitry Andric DeadLaneDetector DLD(MRI, TRI); 267*0fca6ea1SDimitry Andric DLD.computeSubRegisterLaneBitInfo(); 268*0fca6ea1SDimitry Andric 269*0fca6ea1SDimitry Andric for (MachineBasicBlock &BB : MF) 270*0fca6ea1SDimitry Andric Changed |= processBasicBlock(MF, BB, DLD); 271*0fca6ea1SDimitry Andric 272*0fca6ea1SDimitry Andric for (auto *DeadMI : DeadInsts) 273*0fca6ea1SDimitry Andric DeadMI->eraseFromParent(); 274*0fca6ea1SDimitry Andric DeadInsts.clear(); 275*0fca6ea1SDimitry Andric 276*0fca6ea1SDimitry Andric return Changed; 277*0fca6ea1SDimitry Andric } 278