- When an unconditional branch is expanded into an indirect branch, if there is no scavenged register, an SGPR pair needs spilling to enable the destination PC calculation. In addition, before jumping into the destination, that clobbered SGPR pair need restoring. - As SGPR cannot be spilled to or restored from memory directly, the spilling/restoring of that SGPR pair reuses the regular SGPR spilling support but without spilling it into memory. As that spilling and restoring points are fully controlled, we only need to spill that SGPR into the temporary VGPR, which needs spilling into its emergency slot. - The target-specific hook is revised to take additional restore block, where the restoring code is filled. After that, the relaxation will place that restore block directly before the destination block and insert an unconditional branch in any fall-through block into the destination block. Reviewed By: arsenm Differential Revision: https://reviews.llvm.org/D106449
122 lines
4.2 KiB
C++
122 lines
4.2 KiB
C++
//===-- AVRInstrInfo.h - AVR 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 AVR implementation of the TargetInstrInfo class.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_AVR_INSTR_INFO_H
|
|
#define LLVM_AVR_INSTR_INFO_H
|
|
|
|
#include "llvm/CodeGen/TargetInstrInfo.h"
|
|
|
|
#include "AVRRegisterInfo.h"
|
|
|
|
#define GET_INSTRINFO_HEADER
|
|
#include "AVRGenInstrInfo.inc"
|
|
#undef GET_INSTRINFO_HEADER
|
|
|
|
namespace llvm {
|
|
|
|
namespace AVRCC {
|
|
|
|
/// AVR specific condition codes.
|
|
/// These correspond to `AVR_*_COND` in `AVRInstrInfo.td`.
|
|
/// They must be kept in synch.
|
|
enum CondCodes {
|
|
COND_EQ, //!< Equal
|
|
COND_NE, //!< Not equal
|
|
COND_GE, //!< Greater than or equal
|
|
COND_LT, //!< Less than
|
|
COND_SH, //!< Unsigned same or higher
|
|
COND_LO, //!< Unsigned lower
|
|
COND_MI, //!< Minus
|
|
COND_PL, //!< Plus
|
|
COND_INVALID
|
|
};
|
|
|
|
} // end of namespace AVRCC
|
|
|
|
namespace AVRII {
|
|
|
|
/// Specifies a target operand flag.
|
|
enum TOF {
|
|
MO_NO_FLAG,
|
|
|
|
/// On a symbol operand, this represents the lo part.
|
|
MO_LO = (1 << 1),
|
|
|
|
/// On a symbol operand, this represents the hi part.
|
|
MO_HI = (1 << 2),
|
|
|
|
/// On a symbol operand, this represents it has to be negated.
|
|
MO_NEG = (1 << 3)
|
|
};
|
|
|
|
} // end of namespace AVRII
|
|
|
|
/// Utilities related to the AVR instruction set.
|
|
class AVRInstrInfo : public AVRGenInstrInfo {
|
|
public:
|
|
explicit AVRInstrInfo();
|
|
|
|
const AVRRegisterInfo &getRegisterInfo() const { return RI; }
|
|
const MCInstrDesc &getBrCond(AVRCC::CondCodes CC) const;
|
|
AVRCC::CondCodes getCondFromBranchOpc(unsigned Opc) const;
|
|
AVRCC::CondCodes getOppositeCondition(AVRCC::CondCodes CC) const;
|
|
unsigned getInstSizeInBytes(const MachineInstr &MI) const override;
|
|
|
|
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
|
|
const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg,
|
|
bool KillSrc) const override;
|
|
void storeRegToStackSlot(MachineBasicBlock &MBB,
|
|
MachineBasicBlock::iterator MI, Register SrcReg,
|
|
bool isKill, int FrameIndex,
|
|
const TargetRegisterClass *RC,
|
|
const TargetRegisterInfo *TRI) const override;
|
|
void loadRegFromStackSlot(MachineBasicBlock &MBB,
|
|
MachineBasicBlock::iterator MI, Register DestReg,
|
|
int FrameIndex, const TargetRegisterClass *RC,
|
|
const TargetRegisterInfo *TRI) const override;
|
|
unsigned isLoadFromStackSlot(const MachineInstr &MI,
|
|
int &FrameIndex) const override;
|
|
unsigned isStoreToStackSlot(const MachineInstr &MI,
|
|
int &FrameIndex) const override;
|
|
|
|
// Branch analysis.
|
|
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
|
|
MachineBasicBlock *&FBB,
|
|
SmallVectorImpl<MachineOperand> &Cond,
|
|
bool AllowModify = false) const override;
|
|
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
|
|
MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond,
|
|
const DebugLoc &DL,
|
|
int *BytesAdded = 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;
|
|
|
|
void insertIndirectBranch(MachineBasicBlock &MBB,
|
|
MachineBasicBlock &NewDestBB,
|
|
MachineBasicBlock &RestoreBB, const DebugLoc &DL,
|
|
int64_t BrOffset, RegScavenger *RS) const override;
|
|
|
|
private:
|
|
const AVRRegisterInfo RI;
|
|
};
|
|
|
|
} // end namespace llvm
|
|
|
|
#endif // LLVM_AVR_INSTR_INFO_H
|