xref: /llvm-project/llvm/lib/CodeGen/InitUndef.cpp (revision 0d71b3e4031e7b18a5947bdea076839e5a56d202)
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