//===- InitUndef.cpp - Initialize undef value to pseudo ----===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file implements a function pass that initializes undef value to // temporary pseudo instruction to prevent register allocation resulting in a // constraint violated result for the particular instruction. It also rewrites // the NoReg tied operand back to an IMPLICIT_DEF. // // Certain instructions have register overlapping constraints, and // will cause illegal instruction trap if violated, we use early clobber to // model this constraint, but it can't prevent register allocator allocating // same or overlapped if the input register is undef value, so convert // IMPLICIT_DEF to temporary pseudo instruction and remove it later could // prevent that happen, it's not best way to resolve this, and it might // change the order of program or increase the register pressure, so ideally we // should model the constraint right, but before we model the constraint right, // it's the only way to prevent that happen. // // When we enable the subregister liveness option, it will also trigger the same // issue due to the partial of register is undef. If we pseudoinit the whole // register, then it will generate redundant COPY instruction. Currently, it // will generate INSERT_SUBREG to make sure the whole register is occupied // when program encounter operation that has early-clobber constraint. // // // See also: https://github.com/llvm/llvm-project/issues/50157 // // Additionally, this pass rewrites tied operands of instructions // from NoReg to IMPLICIT_DEF. (Not that this is a non-overlapping set of // operands to the above.) We use NoReg to side step a MachineCSE // optimization quality problem but need to convert back before // TwoAddressInstruction. See pr64282 for context. // //===----------------------------------------------------------------------===// #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/DetectDeadLanes.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/TargetInstrInfo.h" #include "llvm/CodeGen/TargetRegisterInfo.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/InitializePasses.h" #include "llvm/MC/MCRegister.h" #include "llvm/Pass.h" #include "llvm/Support/Debug.h" usingnamespacellvm; #define DEBUG_TYPE … #define INIT_UNDEF_NAME … namespace { class InitUndef : public MachineFunctionPass { … }; } // end anonymous namespace char InitUndef::ID = …; INITIALIZE_PASS(…) char &llvm::InitUndefID = …; static bool isEarlyClobberMI(MachineInstr &MI) { … } static bool findImplictDefMIFromReg(Register Reg, MachineRegisterInfo *MRI) { … } bool InitUndef::handleReg(MachineInstr *MI) { … } bool InitUndef::handleSubReg(MachineFunction &MF, MachineInstr &MI, const DeadLaneDetector &DLD) { … } bool InitUndef::fixupIllOperand(MachineInstr *MI, MachineOperand &MO) { … } bool InitUndef::processBasicBlock(MachineFunction &MF, MachineBasicBlock &MBB, const DeadLaneDetector *DLD) { … } bool InitUndef::runOnMachineFunction(MachineFunction &MF) { … }