217 lines
10 KiB
C++
217 lines
10 KiB
C++
//==-- W65816.h - Top-level interface for W65816 representation --*- 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 entry points for global functions defined in the
|
|
// LLVM W65816 backend.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_LIB_TARGET_W65816_W65816_H
|
|
#define LLVM_LIB_TARGET_W65816_W65816_H
|
|
|
|
#include "MCTargetDesc/W65816MCTargetDesc.h"
|
|
#include "llvm/Target/TargetMachine.h"
|
|
|
|
namespace W65816CC {
|
|
// 65816 branch condition codes. Encoded as i8 immediate operands in
|
|
// the BR_CC SDNode and tablegen patterns.
|
|
//
|
|
// 0..7 map to single Bxx instructions. 8..11 are pseudo codes that
|
|
// expand to a two-branch sequence — needed for SETGT/SETLE/SETUGT/
|
|
// SETULE when the operand we'd swap to LHS is a load (no
|
|
// pattern-match for load on LHS without spilling A). Only used in
|
|
// SELECT_CC16's custom inserter; never reaches a single Bxx.
|
|
enum CondCode {
|
|
COND_EQ = 0, // BEQ
|
|
COND_NE = 1, // BNE
|
|
COND_HS = 2, // BCS (unsigned >=)
|
|
COND_LO = 3, // BCC (unsigned <)
|
|
COND_MI = 4, // BMI (negative, signed <)
|
|
COND_PL = 5, // BPL (non-negative, signed >=)
|
|
COND_VS = 6, // BVS (overflow)
|
|
COND_VC = 7, // BVC (no overflow)
|
|
// Multi-branch pseudo codes (handled by SELECT_CC16 inserter):
|
|
COND_GT_MB = 8, // signed > : take if (PL && NE)
|
|
COND_LE_MB = 9, // signed <= : take if (MI || EQ)
|
|
COND_HI_MB = 10, // unsigned > : take if (HS && NE)
|
|
COND_LS_MB = 11, // unsigned <=: take if (LO || EQ)
|
|
COND_INVALID = -1
|
|
};
|
|
} // namespace W65816CC
|
|
|
|
namespace llvm {
|
|
|
|
class FunctionPass;
|
|
class ModulePass;
|
|
class W65816TargetMachine;
|
|
class PassRegistry;
|
|
|
|
FunctionPass *createW65816ISelDag(W65816TargetMachine &TM,
|
|
CodeGenOptLevel OptLevel);
|
|
|
|
// Post-RA cleanup: removes redundant STAfi+LDAfi same-slot pairs that
|
|
// the greedy allocator emits when materialising a COPY $a -> vreg as
|
|
// a spill/reload cycle, even though A still holds the value. See
|
|
// W65816StackSlotCleanup.cpp.
|
|
FunctionPass *createW65816StackSlotCleanup();
|
|
|
|
// Post-PEI cleanup: coalesces adjacent SEP/REP toggles emitted by
|
|
// STA8fi expansions when two i8 stores sit back-to-back. Each STA8fi
|
|
// emits SEP/STA/REP; consecutive expansions produce REP/SEP toggles
|
|
// that cancel. See W65816SepRepCleanup.cpp.
|
|
FunctionPass *createW65816SepRepCleanup();
|
|
|
|
// Pre-emit pass: expands long conditional branches into the
|
|
// `INVERTED_Bxx skip ; BRA target ; skip:` pattern when the byte
|
|
// distance to the target exceeds the +/-128 reach of an 8-bit-PCREL
|
|
// branch. The unconditional BRA is then auto-relaxed to BRL by
|
|
// the assembler when its target is also far. See W65816BranchExpand.cpp.
|
|
FunctionPass *createW65816BranchExpand();
|
|
|
|
// Pre-RA pass: when a tied-def Acc16 instruction has a source vreg
|
|
// whose value is also used after the consumer, fast regalloc fails
|
|
// to preserve it (the tied physreg gets overwritten). We insert
|
|
// explicit STAfi/LDAfi spill+reload around the consumer to fix this.
|
|
// See W65816TiedDefSpill.cpp.
|
|
FunctionPass *createW65816TiedDefSpill();
|
|
|
|
// Pre-RA pass: same trigger as TiedDefSpill, but bridges via X/Y
|
|
// (Idx16) instead of stack when the post-consumer range is free of
|
|
// X/Y clobbers. Saves 6 cycles + 2 bytes per bridge versus the stack
|
|
// route. See W65816ABridgeViaX.cpp.
|
|
FunctionPass *createW65816ABridgeViaX();
|
|
|
|
// Pre-RA pass: promote Acc16 vregs (= {A}) to Wide16 (= {A, IMG0..7}).
|
|
// Lets greedy regalloc spread i16 pressure across A and the DP-backed
|
|
// imaginaries. See W65816WidenAcc16.cpp.
|
|
FunctionPass *createW65816WidenAcc16();
|
|
|
|
// Post-RA peephole: replace STAfi/LDAfi spill pairs (5+5 cyc) with
|
|
// TAX/TXA bridges (2+2 cyc) when X is dead during the spill window.
|
|
// Targets fast-regalloc's habit of spilling A unnecessarily; the
|
|
// 3x speedup is the biggest single per-iteration win we can get
|
|
// without switching to a smarter allocator. See W65816SpillToX.cpp.
|
|
FunctionPass *createW65816SpillToX();
|
|
|
|
// Pre-emit peephole: rewrite `LDY #neg ; (LDA|STA) (sr,S),Y` to
|
|
// pre-add the offset to the pointer with Y=0. The 65816 spec for
|
|
// (sr,S),Y is a 24-bit add (DBR | (mem16(sr+S) + Y)) MOD $1000000,
|
|
// so signed-negative Y crosses bank boundaries. See W65816NegYIndY.cpp.
|
|
FunctionPass *createW65816NegYIndY();
|
|
|
|
// IR pass: finishes the SjLjEHPrepare lowering by inserting a setjmp
|
|
// at function entry and a dispatch block, then erasing the eh.sjlj.*
|
|
// intrinsics our backend doesn't lower natively. Runs after
|
|
// SjLjEHPrepare in addPassesToHandleExceptions. See
|
|
// W65816SjLjFinalize.cpp.
|
|
FunctionPass *createW65816SjLjFinalize();
|
|
|
|
// IR pass: detect `mul i32 X, Y` where the top 16 bits of both X and Y
|
|
// are provably zero (via IR-level computeKnownBits, which traces
|
|
// through PHIs) and rewrite to a call to `__umulhisi3` (16x16 -> 32).
|
|
// IR-level analysis catches cases SDAG can't, because IndVarSimplify
|
|
// widens narrow loop counters to i32 before SDAG sees them, hiding the
|
|
// zext that a SDAG-level combine would key off. See W65816NarrowI32Mul.cpp.
|
|
FunctionPass *createW65816NarrowI32Mul();
|
|
|
|
// Post-LSR IR pass: detect pointer-walking loops over GlobalAddress
|
|
// bases and rewrite to forward-counter + indexed GEP form. LSR's
|
|
// transform is faster for pointer-arg loops (single ptr increment per
|
|
// iter via [dp],Y), but for global-array access the W65816 has cheap
|
|
// `lda <global>, X` indexed addressing that we'd rather use. See
|
|
// W65816UnLSR.cpp.
|
|
FunctionPass *createW65816UnLSR();
|
|
|
|
// Post-RA, pre-PEI pass: rewrite high-traffic i16 FrameIndex accesses
|
|
// to use IMG8..15 DP slots ($C0..$CE) instead of stack-rel spills.
|
|
// Picks K = (number of free IMG8..15) hottest FIs and rewrites their
|
|
// STAfi/LDAfi/ADCfi/etc. pseudos to STA_DP/LDA_DP/ADC_DP/etc. with
|
|
// the corresponding DP address. Net win when access count > 5 (the
|
|
// per-slot save/restore in ImgCalleeSave is ~20 cyc / 12 B). See
|
|
// W65816PromoteFiToImg.cpp.
|
|
FunctionPass *createW65816PromoteFiToImg();
|
|
|
|
// Pre-emit pass: merge value-equivalent stack slots. LLVM's
|
|
// StackSlotColoring merges slots with non-overlapping liveness;
|
|
// this pass catches the case where two slots ARE simultaneously
|
|
// live but always hold the same value — typically the PHI src/dst
|
|
// pair PHI-elim leaves at the back-edge of a loop body. Renames
|
|
// X→Y function-wide when every STA X has a "twin" STA Y of the
|
|
// same source value, and erases the resulting LDA-X-STA-Y self-
|
|
// copy. See W65816StackSlotMerge.cpp.
|
|
FunctionPass *createW65816StackSlotMerge();
|
|
|
|
// Pre-emit pass: rewrite top-N stack-rel slot offsets to IMG0..IMG7
|
|
// DP slots ($D0..$DE). Caller-save semantics — function must only
|
|
// call IMG-safe libgcc helpers (verified to not touch $D0..$DE).
|
|
// See W65816StackRelToImg.cpp.
|
|
FunctionPass *createW65816StackRelToImg();
|
|
|
|
// Pre-RA pass that lowers Wide32 register pairs into pairs of i16
|
|
// vregs. Without this, greedy/basic regalloc can't fit the pair-
|
|
// pressure of i64-via-2-i32-via-Wide32 traffic in i64-heavy
|
|
// functions (RegAllocBase crashes during allocatePhysRegs). After
|
|
// this pass, only i16 vregs reach regalloc, and the pair structure
|
|
// lives only in the LDAptr32S / STAptr32S / STBptr32S pseudos which
|
|
// take 2 i16 ptr operands directly.
|
|
FunctionPass *createW65816LowerWide32();
|
|
|
|
// Pre-emit peephole: detect the post-PEI 6-instruction `i32 += 1`
|
|
// pattern (LDA-ADCi16imm-STA-LDA-ADCEi16imm-STA on consecutive i16
|
|
// stack-rel halves) and rewrite to LDA-INA-STA + INC_HI_IF_CARRY.
|
|
// Saves ~13 cyc per pointer increment in the common no-carry path.
|
|
// See W65816I32IncFold.cpp.
|
|
FunctionPass *createW65816I32IncFold();
|
|
|
|
// Post-RA, pre-PEI pass that emits prologue save + epilogue restore for
|
|
// IMG8..IMG15 if the function uses them. Makes IMG8..IMG15 behave as
|
|
// callee-saved at the asm level without going through LLVM's CSR
|
|
// mechanism (which would shift regalloc decisions and break other
|
|
// tests). See W65816ImgCalleeSave.cpp.
|
|
FunctionPass *createW65816ImgCalleeSave();
|
|
|
|
// Early IR pass: stamp the "w65816-layer2"="true"|"false" function
|
|
// attribute on every Function based on the per-TU cl::opt value of
|
|
// -mllvm -w65816-dbr-safe-ptrs. Stamps EVERY function on every TU
|
|
// compile, so that under LTO the per-TU provenance survives bitcode
|
|
// merge. Phase 1.12 of GAP_CLOSURE_PLAN.md. See W65816Layer2Gate.cpp.
|
|
FunctionPass *createW65816Layer2Stamp();
|
|
|
|
// LTO-time gate ModulePass. Walks every function in the post-link
|
|
// module and hard-fails if any two functions disagree on the
|
|
// "w65816-layer2" attribute -- catches Layer 2 / non-Layer 2 mixing
|
|
// before it produces silent miscompiles. Invoke first in any LTO
|
|
// pipeline (planned: scripts/ltoLink.sh under Phase 5.2). See
|
|
// W65816Layer2Gate.cpp.
|
|
ModulePass *createW65816Layer2Gate();
|
|
|
|
void initializeW65816AsmPrinterPass(PassRegistry &);
|
|
void initializeW65816DAGToDAGISelLegacyPass(PassRegistry &);
|
|
void initializeW65816StackSlotCleanupPass(PassRegistry &);
|
|
void initializeW65816I32IncFoldPass(PassRegistry &);
|
|
void initializeW65816SepRepCleanupPass(PassRegistry &);
|
|
void initializeW65816BranchExpandPass(PassRegistry &);
|
|
void initializeW65816TiedDefSpillPass(PassRegistry &);
|
|
void initializeW65816ABridgeViaXPass(PassRegistry &);
|
|
void initializeW65816UnLSRPass(PassRegistry &);
|
|
void initializeW65816WidenAcc16Pass(PassRegistry &);
|
|
void initializeW65816SpillToXPass(PassRegistry &);
|
|
void initializeW65816NegYIndYPass(PassRegistry &);
|
|
void initializeW65816SjLjFinalizePass(PassRegistry &);
|
|
void initializeW65816LowerWide32Pass(PassRegistry &);
|
|
void initializeW65816ImgCalleeSavePass(PassRegistry &);
|
|
void initializeW65816NarrowI32MulPass(PassRegistry &);
|
|
void initializeW65816PromoteFiToImgPass(PassRegistry &);
|
|
void initializeW65816StackSlotMergePass(PassRegistry &);
|
|
void initializeW65816StackRelToImgPass(PassRegistry &);
|
|
void initializeW65816Layer2StampPass(PassRegistry &);
|
|
void initializeW65816Layer2GatePass(PassRegistry &);
|
|
|
|
} // namespace llvm
|
|
|
|
#endif
|