blob: c7741dd7437f88e9e442c05c3bb25d9b27d748c0 [file] [log] [blame]
//===- LanaiInstrInfo.h - Lanai 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 Lanai implementation of the TargetInstrInfo class.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_TARGET_LANAI_LANAIINSTRINFO_H
#define LLVM_LIB_TARGET_LANAI_LANAIINSTRINFO_H
#include "LanaiRegisterInfo.h"
#include "MCTargetDesc/LanaiMCTargetDesc.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#define GET_INSTRINFO_HEADER
#include "LanaiGenInstrInfo.inc"
namespace llvm {
class LanaiInstrInfo : public LanaiGenInstrInfo {
const LanaiRegisterInfo RegisterInfo;
public:
LanaiInstrInfo();
// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As
// such, whenever a client has an instance of instruction info, it should
// always be able to get register info as well (through this method).
virtual const LanaiRegisterInfo &getRegisterInfo() const {
return RegisterInfo;
}
bool areMemAccessesTriviallyDisjoint(const MachineInstr &MIa,
const MachineInstr &MIb) const override;
unsigned isLoadFromStackSlot(const MachineInstr &MI,
int &FrameIndex) const override;
unsigned isLoadFromStackSlotPostFE(const MachineInstr &MI,
int &FrameIndex) const override;
unsigned isStoreToStackSlot(const MachineInstr &MI,
int &FrameIndex) const override;
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator Position,
const DebugLoc &DL, MCRegister DestinationRegister,
MCRegister SourceRegister, bool KillSource) const override;
void
storeRegToStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator Position,
unsigned SourceRegister, bool IsKill, int FrameIndex,
const TargetRegisterClass *RegisterClass,
const TargetRegisterInfo *RegisterInfo) const override;
void
loadRegFromStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator Position,
unsigned DestinationRegister, int FrameIndex,
const TargetRegisterClass *RegisterClass,
const TargetRegisterInfo *RegisterInfo) const override;
bool expandPostRAPseudo(MachineInstr &MI) const override;
bool getMemOperandWithOffset(const MachineInstr &LdSt,
const MachineOperand *&BaseOp,
int64_t &Offset,
const TargetRegisterInfo *TRI) const override;
bool getMemOperandWithOffsetWidth(const MachineInstr &LdSt,
const MachineOperand *&BaseOp,
int64_t &Offset, unsigned &Width,
const TargetRegisterInfo *TRI) const;
std::pair<unsigned, unsigned>
decomposeMachineOperandsTargetFlags(unsigned TF) const override;
ArrayRef<std::pair<unsigned, const char *>>
getSerializableDirectMachineOperandTargetFlags() const override;
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TrueBlock,
MachineBasicBlock *&FalseBlock,
SmallVectorImpl<MachineOperand> &Condition,
bool AllowModify) const override;
unsigned removeBranch(MachineBasicBlock &MBB,
int *BytesRemoved = nullptr) const override;
// For a comparison instruction, return the source registers in SrcReg and
// SrcReg2 if having two register operands, and the value it compares against
// in CmpValue. Return true if the comparison instruction can be analyzed.
bool analyzeCompare(const MachineInstr &MI, unsigned &SrcReg,
unsigned &SrcReg2, int &CmpMask,
int &CmpValue) const override;
// See if the comparison instruction can be converted into something more
// efficient. E.g., on Lanai register-register instructions can set the flag
// register, obviating the need for a separate compare.
bool optimizeCompareInstr(MachineInstr &CmpInstr, unsigned SrcReg,
unsigned SrcReg2, int CmpMask, int CmpValue,
const MachineRegisterInfo *MRI) const override;
// Analyze the given select instruction, returning true if it cannot be
// understood. It is assumed that MI->isSelect() is true.
//
// When successful, return the controlling condition and the operands that
// determine the true and false result values.
//
// Result = SELECT Cond, TrueOp, FalseOp
//
// Lanai can optimize certain select instructions, for example by predicating
// the instruction defining one of the operands and sets Optimizable to true.
bool analyzeSelect(const MachineInstr &MI,
SmallVectorImpl<MachineOperand> &Cond, unsigned &TrueOp,
unsigned &FalseOp, bool &Optimizable) const override;
// Given a select instruction that was understood by analyzeSelect and
// returned Optimizable = true, attempt to optimize MI by merging it with one
// of its operands. Returns NULL on failure.
//
// When successful, returns the new select instruction. The client is
// responsible for deleting MI.
//
// If both sides of the select can be optimized, the TrueOp is modifed.
// PreferFalse is not used.
MachineInstr *optimizeSelect(MachineInstr &MI,
SmallPtrSetImpl<MachineInstr *> &SeenMIs,
bool PreferFalse) const override;
bool reverseBranchCondition(
SmallVectorImpl<MachineOperand> &Condition) const override;
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TrueBlock,
MachineBasicBlock *FalseBlock,
ArrayRef<MachineOperand> Condition,
const DebugLoc &DL,
int *BytesAdded = nullptr) const override;
};
static inline bool isSPLSOpcode(unsigned Opcode) {
switch (Opcode) {
case Lanai::LDBs_RI:
case Lanai::LDBz_RI:
case Lanai::LDHs_RI:
case Lanai::LDHz_RI:
case Lanai::STB_RI:
case Lanai::STH_RI:
return true;
default:
return false;
}
}
static inline bool isRMOpcode(unsigned Opcode) {
switch (Opcode) {
case Lanai::LDW_RI:
case Lanai::SW_RI:
return true;
default:
return false;
}
}
static inline bool isRRMOpcode(unsigned Opcode) {
switch (Opcode) {
case Lanai::LDBs_RR:
case Lanai::LDBz_RR:
case Lanai::LDHs_RR:
case Lanai::LDHz_RR:
case Lanai::LDWz_RR:
case Lanai::LDW_RR:
case Lanai::STB_RR:
case Lanai::STH_RR:
case Lanai::SW_RR:
return true;
default:
return false;
}
}
} // namespace llvm
#endif // LLVM_LIB_TARGET_LANAI_LANAIINSTRINFO_H