mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 11:13:28 +01:00
409363cd51
This patch emits DBG_INSTR_REFs for two remaining flavours of variable locations that weren't supported: copies, and inter-block VRegs. There are still some locations that must be represented by DBG_VALUE such as constants, but they're mostly independent of optimisations. For variable locations that refer to values defined in different blocks, vregs are allocated before isel begins, but the defining instruction might not exist until late in isel. To get around this, emit DBG_INSTR_REFs in a "half done" state, where the first operand refers to a VReg. Then at the end of isel, patch these back up to refer to instructions, using the finalizeDebugInstrRefs method. Copies are something that I complained about the original RFC, and I really don't want to have to put instruction numbers on copies. They don't define a value: they move them. To address this isel, salvageCopySSA interprets: * COPYs, * SUBREG_TO_REG, * Anything that isCopyInstr thinks is a copy. And follows chains of copies back to the defining instruction that they read from. This relies on any physical registers that COPYs read being defined in the same block, or being entry-block arguments. For the former we can put an instruction number on the defining instruction; for the latter we can drop a DBG_PHI that reads the incoming value. Differential Revision: https://reviews.llvm.org/D88896
168 lines
6.7 KiB
C++
168 lines
6.7 KiB
C++
//===- InstrEmitter.h - Emit MachineInstrs for the SelectionDAG -*- C++ -*--==//
|
|
//
|
|
// 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 declares the Emit routines for the SelectionDAG class, which creates
|
|
// MachineInstrs based on the decisions of the SelectionDAG instruction
|
|
// selection.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_LIB_CODEGEN_SELECTIONDAG_INSTREMITTER_H
|
|
#define LLVM_LIB_CODEGEN_SELECTIONDAG_INSTREMITTER_H
|
|
|
|
#include "llvm/ADT/DenseMap.h"
|
|
#include "llvm/CodeGen/MachineBasicBlock.h"
|
|
#include "llvm/CodeGen/SelectionDAGNodes.h"
|
|
|
|
namespace llvm {
|
|
|
|
class MachineInstrBuilder;
|
|
class MCInstrDesc;
|
|
class SDDbgLabel;
|
|
class SDDbgValue;
|
|
class SDDbgOperand;
|
|
class TargetLowering;
|
|
class TargetMachine;
|
|
|
|
class LLVM_LIBRARY_VISIBILITY InstrEmitter {
|
|
MachineFunction *MF;
|
|
MachineRegisterInfo *MRI;
|
|
const TargetInstrInfo *TII;
|
|
const TargetRegisterInfo *TRI;
|
|
const TargetLowering *TLI;
|
|
|
|
MachineBasicBlock *MBB;
|
|
MachineBasicBlock::iterator InsertPos;
|
|
|
|
/// Should we try to produce DBG_INSTR_REF instructions?
|
|
bool EmitDebugInstrRefs;
|
|
|
|
/// EmitCopyFromReg - Generate machine code for an CopyFromReg node or an
|
|
/// implicit physical register output.
|
|
void EmitCopyFromReg(SDNode *Node, unsigned ResNo,
|
|
bool IsClone, bool IsCloned,
|
|
Register SrcReg,
|
|
DenseMap<SDValue, Register> &VRBaseMap);
|
|
|
|
void CreateVirtualRegisters(SDNode *Node,
|
|
MachineInstrBuilder &MIB,
|
|
const MCInstrDesc &II,
|
|
bool IsClone, bool IsCloned,
|
|
DenseMap<SDValue, Register> &VRBaseMap);
|
|
|
|
/// getVR - Return the virtual register corresponding to the specified result
|
|
/// of the specified node.
|
|
Register getVR(SDValue Op,
|
|
DenseMap<SDValue, Register> &VRBaseMap);
|
|
|
|
/// AddRegisterOperand - Add the specified register as an operand to the
|
|
/// specified machine instr. Insert register copies if the register is
|
|
/// not in the required register class.
|
|
void AddRegisterOperand(MachineInstrBuilder &MIB,
|
|
SDValue Op,
|
|
unsigned IIOpNum,
|
|
const MCInstrDesc *II,
|
|
DenseMap<SDValue, Register> &VRBaseMap,
|
|
bool IsDebug, bool IsClone, bool IsCloned);
|
|
|
|
/// AddOperand - Add the specified operand to the specified machine instr. II
|
|
/// specifies the instruction information for the node, and IIOpNum is the
|
|
/// operand number (in the II) that we are adding. IIOpNum and II are used for
|
|
/// assertions only.
|
|
void AddOperand(MachineInstrBuilder &MIB,
|
|
SDValue Op,
|
|
unsigned IIOpNum,
|
|
const MCInstrDesc *II,
|
|
DenseMap<SDValue, Register> &VRBaseMap,
|
|
bool IsDebug, bool IsClone, bool IsCloned);
|
|
|
|
/// ConstrainForSubReg - Try to constrain VReg to a register class that
|
|
/// supports SubIdx sub-registers. Emit a copy if that isn't possible.
|
|
/// Return the virtual register to use.
|
|
Register ConstrainForSubReg(Register VReg, unsigned SubIdx, MVT VT,
|
|
bool isDivergent, const DebugLoc &DL);
|
|
|
|
/// EmitSubregNode - Generate machine code for subreg nodes.
|
|
///
|
|
void EmitSubregNode(SDNode *Node, DenseMap<SDValue, Register> &VRBaseMap,
|
|
bool IsClone, bool IsCloned);
|
|
|
|
/// EmitCopyToRegClassNode - Generate machine code for COPY_TO_REGCLASS nodes.
|
|
/// COPY_TO_REGCLASS is just a normal copy, except that the destination
|
|
/// register is constrained to be in a particular register class.
|
|
///
|
|
void EmitCopyToRegClassNode(SDNode *Node,
|
|
DenseMap<SDValue, Register> &VRBaseMap);
|
|
|
|
/// EmitRegSequence - Generate machine code for REG_SEQUENCE nodes.
|
|
///
|
|
void EmitRegSequence(SDNode *Node, DenseMap<SDValue, Register> &VRBaseMap,
|
|
bool IsClone, bool IsCloned);
|
|
public:
|
|
/// CountResults - The results of target nodes have register or immediate
|
|
/// operands first, then an optional chain, and optional flag operands
|
|
/// (which do not go into the machine instrs.)
|
|
static unsigned CountResults(SDNode *Node);
|
|
|
|
void AddDbgValueLocationOps(MachineInstrBuilder &MIB,
|
|
const MCInstrDesc &DbgValDesc,
|
|
ArrayRef<SDDbgOperand> Locations,
|
|
DenseMap<SDValue, Register> &VRBaseMap);
|
|
|
|
/// EmitDbgValue - Generate machine instruction for a dbg_value node.
|
|
///
|
|
MachineInstr *EmitDbgValue(SDDbgValue *SD,
|
|
DenseMap<SDValue, Register> &VRBaseMap);
|
|
|
|
/// Emit a dbg_value as a DBG_INSTR_REF. May produce DBG_VALUE $noreg instead
|
|
/// if there is no variable location; alternately a half-formed DBG_INSTR_REF
|
|
/// that refers to a virtual register and is corrected later in isel.
|
|
MachineInstr *EmitDbgInstrRef(SDDbgValue *SD,
|
|
DenseMap<SDValue, Register> &VRBaseMap);
|
|
|
|
/// Emit a DBG_VALUE $noreg, indicating a variable has no location.
|
|
MachineInstr *EmitDbgNoLocation(SDDbgValue *SD);
|
|
|
|
/// Emit a DBG_VALUE from the operands to SDDbgValue.
|
|
MachineInstr *EmitDbgValueFromSingleOp(SDDbgValue *SD,
|
|
DenseMap<SDValue, Register> &VRBaseMap);
|
|
|
|
/// Generate machine instruction for a dbg_label node.
|
|
MachineInstr *EmitDbgLabel(SDDbgLabel *SD);
|
|
|
|
/// EmitNode - Generate machine code for a node and needed dependencies.
|
|
///
|
|
void EmitNode(SDNode *Node, bool IsClone, bool IsCloned,
|
|
DenseMap<SDValue, Register> &VRBaseMap) {
|
|
if (Node->isMachineOpcode())
|
|
EmitMachineNode(Node, IsClone, IsCloned, VRBaseMap);
|
|
else
|
|
EmitSpecialNode(Node, IsClone, IsCloned, VRBaseMap);
|
|
}
|
|
|
|
/// getBlock - Return the current basic block.
|
|
MachineBasicBlock *getBlock() { return MBB; }
|
|
|
|
/// getInsertPos - Return the current insertion position.
|
|
MachineBasicBlock::iterator getInsertPos() { return InsertPos; }
|
|
|
|
/// InstrEmitter - Construct an InstrEmitter and set it to start inserting
|
|
/// at the given position in the given block.
|
|
InstrEmitter(const TargetMachine &TM, MachineBasicBlock *mbb,
|
|
MachineBasicBlock::iterator insertpos);
|
|
|
|
private:
|
|
void EmitMachineNode(SDNode *Node, bool IsClone, bool IsCloned,
|
|
DenseMap<SDValue, Register> &VRBaseMap);
|
|
void EmitSpecialNode(SDNode *Node, bool IsClone, bool IsCloned,
|
|
DenseMap<SDValue, Register> &VRBaseMap);
|
|
};
|
|
} // namespace llvm
|
|
|
|
#endif
|