llvm-project/llvm/lib/Target/RISCV/RISCVInstrInfo.h
Craig Topper 88bc29f5f2 [RISCV] Introduce a RISCV CondCode enum instead of using ISD:SET* in MIR. NFC
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
2021-08-08 17:25:37 -07:00

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