123 lines
5.9 KiB
C++
123 lines
5.9 KiB
C++
//===-- W65816InstrInfo.h - W65816 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 W65816 implementation of the TargetInstrInfo class.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_LIB_TARGET_W65816_W65816INSTRINFO_H
|
|
#define LLVM_LIB_TARGET_W65816_W65816INSTRINFO_H
|
|
|
|
#include "W65816RegisterInfo.h"
|
|
#include "llvm/CodeGen/TargetInstrInfo.h"
|
|
|
|
#define GET_INSTRINFO_HEADER
|
|
#include "W65816GenInstrInfo.inc"
|
|
|
|
namespace llvm {
|
|
|
|
class W65816Subtarget;
|
|
|
|
class W65816InstrInfo : public W65816GenInstrInfo {
|
|
const W65816RegisterInfo RI;
|
|
virtual void anchor();
|
|
|
|
public:
|
|
explicit W65816InstrInfo(const W65816Subtarget &STI);
|
|
|
|
const W65816RegisterInfo &getRegisterInfo() const { return RI; }
|
|
|
|
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
|
const DebugLoc &DL, Register DestReg, Register SrcReg,
|
|
bool KillSrc, bool RenamableDest = false,
|
|
bool RenamableSrc = false) const override;
|
|
|
|
void storeRegToStackSlot(
|
|
MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg,
|
|
bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg,
|
|
MachineInstr::MIFlag Flags = MachineInstr::NoFlags) const override;
|
|
void loadRegFromStackSlot(
|
|
MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg,
|
|
int FrameIdx, const TargetRegisterClass *RC, Register VReg,
|
|
unsigned SubReg = 0,
|
|
MachineInstr::MIFlag Flags = MachineInstr::NoFlags) const override;
|
|
|
|
// Override the default rematerializability check to recognise LDAfi
|
|
// from a *fixed* (immutable) frame index — i.e. an arg slot — as
|
|
// trivially rematerializable. Without this, the greedy allocator
|
|
// spills arg loads to a fresh local slot the moment A is needed for
|
|
// anything else, then reloads from the local slot at every use.
|
|
// With it, the allocator just re-emits `LDA arg_slot,S` at each use
|
|
// and the `STA local; LDA local; LDA local` cluster collapses to a
|
|
// single `LDA arg_slot,S`. Spill-slot LDAfi (regular FI) is *not*
|
|
// rematerializable — that loads a computed value.
|
|
bool isReMaterializableImpl(const MachineInstr &MI) const override;
|
|
|
|
// Tell the framework which pseudos are direct stack-slot loads/stores.
|
|
// MachineCSE, machine-licm, and peephole-opt use these hooks to elide
|
|
// redundant store/load pairs and to hoist invariants. Without them,
|
|
// patterns like `STAfi A, slot; LDAfi slot, A` (introduced by the
|
|
// greedy allocator's COPY-of-physreg expansion) survive into final
|
|
// asm as `sta x,s; lda x,s` no-op pairs.
|
|
Register isLoadFromStackSlot(const MachineInstr &MI,
|
|
int &FrameIndex) const override;
|
|
Register isStoreToStackSlot(const MachineInstr &MI,
|
|
int &FrameIndex) const override;
|
|
|
|
// Byte-accurate size of an instruction (or an upper bound for
|
|
// pseudos that AsmPrinter expands to multiple MC instructions).
|
|
// Used by W65816BranchExpand to compute branch distances precisely
|
|
// enough to decide when to lengthen a conditional branch. Real
|
|
// instructions with a Size set in tablegen get that value;
|
|
// pseudos that emit nothing (PHI, COPY, ADJCALLSTACKDOWN/UP,
|
|
// KILL, IMPLICIT_DEF, REG_SEQUENCE, BUNDLE, etc.) report 0 bytes;
|
|
// codegen pseudos with Size==0 in tablegen but a non-trivial
|
|
// AsmPrinter expansion get an upper-bound estimate.
|
|
unsigned getInstSizeInBytes(const MachineInstr &MI) const override;
|
|
|
|
// PEI uses this to track the running SP shift inside a call
|
|
// sequence and pass it to eliminateFrameIndex as SPAdj. Our
|
|
// ADJCALLSTACKDOWN does NOT physically shift SP — the PUSH16/PUSH16X
|
|
// pseudos do that incrementally as args get pushed. Override the
|
|
// default so PEI knows: ADJCALLSTACKDOWN/UP contribute 0 (no SP
|
|
// shift), PUSH16/PUSH16X contribute +2 each (one byte-pair pushed).
|
|
// Without this override, PEI applies the full ADJCALLSTACKDOWN
|
|
// amount as SPAdj at the very *start* of the call sequence,
|
|
// producing FI offsets that pretend SP has already shifted — and
|
|
// any STAfi/LDAfi to a *local* before the actual PUSH16 happens
|
|
// ends up writing past the locals into the caller's stack
|
|
// (corrupting the return address, observed for `int eval(int a,
|
|
// int b, int c) { return a*b + c; }` under fast regalloc).
|
|
int getSPAdjust(const MachineInstr &MI) const override;
|
|
|
|
// Branch-control hooks. These now decode our real branch opcodes
|
|
// (BEQ/BNE/BCS/BCC/BMI/BPL/BVS/BVC and BRA/BRL/JMP_Abs) so
|
|
// BranchFolder and MachineBlockPlacement can rearrange blocks.
|
|
// Cond is encoded as a single Imm operand holding the conditional
|
|
// branch's opcode; reverseBranchCondition flips it via opcode map.
|
|
// JMP_AbsInd / JML_Long return "unanalyzable" — they're indirect or
|
|
// bank-crossing, which the layout passes can't reason about.
|
|
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
|
|
MachineBasicBlock *&FBB,
|
|
SmallVectorImpl<MachineOperand> &Cond,
|
|
bool AllowModify) const override;
|
|
unsigned removeBranch(MachineBasicBlock &MBB,
|
|
int *BytesRemoved = nullptr) const override;
|
|
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
|
|
MachineBasicBlock *FBB,
|
|
ArrayRef<MachineOperand> Cond, const DebugLoc &DL,
|
|
int *BytesAdded = nullptr) const override;
|
|
bool reverseBranchCondition(
|
|
SmallVectorImpl<MachineOperand> &Cond) const override;
|
|
MachineBasicBlock *getBranchDestBlock(
|
|
const MachineInstr &MI) const override;
|
|
};
|
|
|
|
} // namespace llvm
|
|
|
|
#endif
|