
Previously we converted ISD condition codes to integers and stored them directly in our MIR instructions. The ISD enum kind of belongs to SelectionDAG so that seems like incorrect layering. This patch instead uses a CondCode node on RISCV::SELECT_CC until isel and then converts it from ISD encoding to a RISCV specific value. This value can be converted to/from the RISCV branch opcodes in the RISCV namespace. My larger motivation is to possibly support a microarchitectural feature of some CPUs where a short forward branch over a single instruction can be predicated internally. This will require a new pseudo instruction for select that needs to carry a branch condition and live probably until RISCVExpandPseudos. At that point it can be expanded to control flow without other instructions ending up in the predicated basic block. Using an ISD encoding in RISCVExpandPseudos doesn't seem like correct layering. Reviewed By: luismarques Differential Revision: https://reviews.llvm.org/D107400
198 lines
7.3 KiB
C++
198 lines
7.3 KiB
C++
//===-- RISCVInstrInfo.h - RISCV Instruction Information --------*- 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 file contains the RISCV implementation of the TargetInstrInfo class.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_LIB_TARGET_RISCV_RISCVINSTRINFO_H
|
|
#define LLVM_LIB_TARGET_RISCV_RISCVINSTRINFO_H
|
|
|
|
#include "RISCVRegisterInfo.h"
|
|
#include "llvm/CodeGen/TargetInstrInfo.h"
|
|
#include "llvm/IR/DiagnosticInfo.h"
|
|
|
|
#define GET_INSTRINFO_HEADER
|
|
#include "RISCVGenInstrInfo.inc"
|
|
|
|
namespace llvm {
|
|
|
|
class RISCVSubtarget;
|
|
|
|
namespace RISCVCC {
|
|
|
|
enum CondCode {
|
|
COND_EQ,
|
|
COND_NE,
|
|
COND_LT,
|
|
COND_GE,
|
|
COND_LTU,
|
|
COND_GEU,
|
|
COND_INVALID
|
|
};
|
|
|
|
CondCode getOppositeBranchCondition(CondCode);
|
|
|
|
} // end of namespace RISCVCC
|
|
|
|
class RISCVInstrInfo : public RISCVGenInstrInfo {
|
|
|
|
public:
|
|
explicit RISCVInstrInfo(RISCVSubtarget &STI);
|
|
|
|
MCInst getNop() const override;
|
|
const MCInstrDesc &getBrCond(RISCVCC::CondCode CC) const;
|
|
|
|
unsigned isLoadFromStackSlot(const MachineInstr &MI,
|
|
int &FrameIndex) const override;
|
|
unsigned isStoreToStackSlot(const MachineInstr &MI,
|
|
int &FrameIndex) const override;
|
|
|
|
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
|
|
const DebugLoc &DL, MCRegister DstReg, MCRegister SrcReg,
|
|
bool KillSrc) const override;
|
|
|
|
void storeRegToStackSlot(MachineBasicBlock &MBB,
|
|
MachineBasicBlock::iterator MBBI, Register SrcReg,
|
|
bool IsKill, int FrameIndex,
|
|
const TargetRegisterClass *RC,
|
|
const TargetRegisterInfo *TRI) const override;
|
|
|
|
void loadRegFromStackSlot(MachineBasicBlock &MBB,
|
|
MachineBasicBlock::iterator MBBI, Register DstReg,
|
|
int FrameIndex, const TargetRegisterClass *RC,
|
|
const TargetRegisterInfo *TRI) const override;
|
|
|
|
// Materializes the given integer Val into DstReg.
|
|
void movImm(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
|
|
const DebugLoc &DL, Register DstReg, uint64_t Val,
|
|
MachineInstr::MIFlag Flag = MachineInstr::NoFlags) const;
|
|
|
|
unsigned getInstSizeInBytes(const MachineInstr &MI) const override;
|
|
|
|
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
|
|
MachineBasicBlock *&FBB,
|
|
SmallVectorImpl<MachineOperand> &Cond,
|
|
bool AllowModify) const override;
|
|
|
|
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
|
|
MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond,
|
|
const DebugLoc &dl,
|
|
int *BytesAdded = nullptr) const override;
|
|
|
|
unsigned insertIndirectBranch(MachineBasicBlock &MBB,
|
|
MachineBasicBlock &NewDestBB,
|
|
const DebugLoc &DL, int64_t BrOffset,
|
|
RegScavenger *RS = nullptr) const override;
|
|
|
|
unsigned removeBranch(MachineBasicBlock &MBB,
|
|
int *BytesRemoved = nullptr) const override;
|
|
|
|
bool
|
|
reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const override;
|
|
|
|
MachineBasicBlock *getBranchDestBlock(const MachineInstr &MI) const override;
|
|
|
|
bool isBranchOffsetInRange(unsigned BranchOpc,
|
|
int64_t BrOffset) const override;
|
|
|
|
bool isAsCheapAsAMove(const MachineInstr &MI) const override;
|
|
|
|
Optional<DestSourcePair>
|
|
isCopyInstrImpl(const MachineInstr &MI) const override;
|
|
|
|
bool verifyInstruction(const MachineInstr &MI,
|
|
StringRef &ErrInfo) const override;
|
|
|
|
bool getMemOperandWithOffsetWidth(const MachineInstr &LdSt,
|
|
const MachineOperand *&BaseOp,
|
|
int64_t &Offset, unsigned &Width,
|
|
const TargetRegisterInfo *TRI) const;
|
|
|
|
bool areMemAccessesTriviallyDisjoint(const MachineInstr &MIa,
|
|
const MachineInstr &MIb) const override;
|
|
|
|
|
|
std::pair<unsigned, unsigned>
|
|
decomposeMachineOperandsTargetFlags(unsigned TF) const override;
|
|
|
|
ArrayRef<std::pair<unsigned, const char *>>
|
|
getSerializableDirectMachineOperandTargetFlags() const override;
|
|
|
|
// Return true if the function can safely be outlined from.
|
|
virtual bool
|
|
isFunctionSafeToOutlineFrom(MachineFunction &MF,
|
|
bool OutlineFromLinkOnceODRs) const override;
|
|
|
|
// Return true if MBB is safe to outline from, and return any target-specific
|
|
// information in Flags.
|
|
virtual bool isMBBSafeToOutlineFrom(MachineBasicBlock &MBB,
|
|
unsigned &Flags) const override;
|
|
|
|
// Calculate target-specific information for a set of outlining candidates.
|
|
outliner::OutlinedFunction getOutliningCandidateInfo(
|
|
std::vector<outliner::Candidate> &RepeatedSequenceLocs) const override;
|
|
|
|
// Return if/how a given MachineInstr should be outlined.
|
|
virtual outliner::InstrType
|
|
getOutliningType(MachineBasicBlock::iterator &MBBI,
|
|
unsigned Flags) const override;
|
|
|
|
// Insert a custom frame for outlined functions.
|
|
virtual void
|
|
buildOutlinedFrame(MachineBasicBlock &MBB, MachineFunction &MF,
|
|
const outliner::OutlinedFunction &OF) const override;
|
|
|
|
// Insert a call to an outlined function into a given basic block.
|
|
virtual MachineBasicBlock::iterator
|
|
insertOutlinedCall(Module &M, MachineBasicBlock &MBB,
|
|
MachineBasicBlock::iterator &It, MachineFunction &MF,
|
|
const outliner::Candidate &C) const override;
|
|
|
|
bool findCommutedOpIndices(const MachineInstr &MI, unsigned &SrcOpIdx1,
|
|
unsigned &SrcOpIdx2) const override;
|
|
MachineInstr *commuteInstructionImpl(MachineInstr &MI, bool NewMI,
|
|
unsigned OpIdx1,
|
|
unsigned OpIdx2) const override;
|
|
|
|
MachineInstr *convertToThreeAddress(MachineFunction::iterator &MBB,
|
|
MachineInstr &MI,
|
|
LiveVariables *LV) const override;
|
|
|
|
Register getVLENFactoredAmount(
|
|
MachineFunction &MF, MachineBasicBlock &MBB,
|
|
MachineBasicBlock::iterator II, const DebugLoc &DL, int64_t Amount,
|
|
MachineInstr::MIFlag Flag = MachineInstr::NoFlags) const;
|
|
|
|
// Returns true if the given MI is an RVV instruction opcode for which we may
|
|
// expect to see a FrameIndex operand. When CheckFIs is true, the instruction
|
|
// must contain at least one FrameIndex operand.
|
|
bool isRVVSpill(const MachineInstr &MI, bool CheckFIs) const;
|
|
|
|
Optional<std::pair<unsigned, unsigned>>
|
|
isRVVSpillForZvlsseg(unsigned Opcode) const;
|
|
|
|
protected:
|
|
const RISCVSubtarget &STI;
|
|
};
|
|
|
|
namespace RISCVVPseudosTable {
|
|
|
|
struct PseudoInfo {
|
|
uint16_t Pseudo;
|
|
uint16_t BaseInstr;
|
|
};
|
|
|
|
#define GET_RISCVVPseudosTable_DECL
|
|
#include "RISCVGenSearchableTables.inc"
|
|
|
|
} // end namespace RISCVVPseudosTable
|
|
|
|
} // end namespace llvm
|
|
#endif
|