65816-llvm-mos/src/llvm/lib/Target/W65816/W65816InstrInfo.h
Scott Duensing e65fedc8e1 Checkpoint
2026-05-13 15:48:34 -05:00

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