LLVM 19.0.0git
Macros | Functions | Variables
MipsBranchExpansion.cpp File Reference

This pass do two things: More...

#include "MCTargetDesc/MipsABIInfo.h"
#include "MCTargetDesc/MipsBaseInfo.h"
#include "MCTargetDesc/MipsMCNaCl.h"
#include "MCTargetDesc/MipsMCTargetDesc.h"
#include "Mips.h"
#include "MipsInstrInfo.h"
#include "MipsMachineFunction.h"
#include "MipsSubtarget.h"
#include "MipsTargetMachine.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Target/TargetMachine.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <iterator>
#include <utility>

Go to the source code of this file.

Macros

#define DEBUG_TYPE   "mips-branch-expansion"
 

Functions

 STATISTIC (NumInsertedNops, "Number of nops inserted")
 
 STATISTIC (LongBranches, "Number of long branches.")
 
 INITIALIZE_PASS (MipsBranchExpansion, DEBUG_TYPE, "Expand out of range branch instructions and fix forbidden" " slot hazards", false, false) FunctionPass *llvm
 Returns a pass that clears pipeline hazards.
 
static Iter getNextMachineInstrInBB (Iter Position)
 
static std::pair< Iter, boolgetNextMachineInstr (Iter Position, MachineBasicBlock *Parent)
 
static MachineBasicBlockgetTargetMBB (const MachineInstr &Br)
 Iterate over list of Br's operands and search for a MachineBasicBlock operand.
 
static ReverseIter getNonDebugInstr (ReverseIter B, const ReverseIter &E)
 
static void emitGPDisp (MachineFunction &F, const MipsInstrInfo *TII)
 

Variables

static cl::opt< boolSkipLongBranch ("skip-mips-long-branch", cl::init(false), cl::desc("MIPS: Skip branch expansion pass."), cl::Hidden)
 
static cl::opt< boolForceLongBranch ("force-mips-long-branch", cl::init(false), cl::desc("MIPS: Expand all branches to long format."), cl::Hidden)
 

Detailed Description

This pass do two things:

The reason why this pass combines these two tasks is that one of these two tasks can break the result of the previous one.

Example of that is a situation where at first, no branch should be expanded, but after adding at least one nop somewhere in the code to prevent a forbidden slot hazard, offset of some branches may go out of range. In that case it is necessary to check again if there is some branch that needs expansion. On the other hand, expanding some branch may cause a control transfer instruction to appear in the forbidden slot, which is a hazard that should be fixed. This pass alternates between this two tasks untill no changes are made. Only then we can be sure that all branches are expanded properly, and no hazard situations exist.

Regarding branch expanding:

When branch instruction like beqzc or bnezc has offset that is too large to fit into its immediate field, it has to be expanded to another instruction or series of instructions.

FIXME: Fix pc-region jump instructions which cross 256MB segment boundaries. TODO: Handle out of range bc, b (pseudo) instructions.

Regarding compact branch hazard prevention:

Hazards handled: forbidden slots for MIPSR6, FPU slots for MIPS3 and below, load delay slots for MIPS1.

A forbidden slot hazard occurs when a compact branch instruction is executed and the adjacent instruction in memory is a control transfer instruction such as a branch or jump, ERET, ERETNC, DERET, WAIT and PAUSE.

For example:

0x8004 bnec a1,v0,<P+0x18> 0x8008 beqc a1,a2,<P+0x54>

In such cases, the processor is required to signal a Reserved Instruction exception.

Here, if the instruction at 0x8004 is executed, the processor will raise an exception as there is a control transfer instruction at 0x8008.

There are two sources of forbidden slot hazards:

A) A previous pass has created a compact branch directly. B) Transforming a delay slot branch into compact branch. This case can be difficult to process as lookahead for hazards is insufficient, as backwards delay slot fillling can also produce hazards in previously processed instuctions.

In future this pass can be extended (or new pass can be created) to handle other pipeline hazards, such as various MIPS1 hazards, processor errata that require instruction reorganization, etc.

This pass has to run after the delay slot filler as that pass can introduce pipeline hazards such as compact branch hazard, hence the existing hazard recognizer is not suitable.

Definition in file MipsBranchExpansion.cpp.

Macro Definition Documentation

◆ DEBUG_TYPE

#define DEBUG_TYPE   "mips-branch-expansion"

Definition at line 108 of file MipsBranchExpansion.cpp.

Function Documentation

◆ emitGPDisp()

static void emitGPDisp ( MachineFunction F,
const MipsInstrInfo TII 
)
static

◆ getNextMachineInstr()

static std::pair< Iter, bool > getNextMachineInstr ( Iter  Position,
MachineBasicBlock Parent 
)
static

◆ getNextMachineInstrInBB()

static Iter getNextMachineInstrInBB ( Iter  Position)
static

Definition at line 197 of file MipsBranchExpansion.cpp.

References I, and Insn.

Referenced by getNextMachineInstr().

◆ getNonDebugInstr()

static ReverseIter getNonDebugInstr ( ReverseIter  B,
const ReverseIter &  E 
)
static

Definition at line 243 of file MipsBranchExpansion.cpp.

References B.

◆ getTargetMBB()

static MachineBasicBlock * getTargetMBB ( const MachineInstr Br)
static

Iterate over list of Br's operands and search for a MachineBasicBlock operand.

Definition at line 230 of file MipsBranchExpansion.cpp.

References llvm::MachineInstr::getDesc(), llvm::MachineOperand::getMBB(), llvm::MCInstrDesc::getNumOperands(), llvm::MachineInstr::getOperand(), I, llvm::MachineOperand::isMBB(), and llvm_unreachable.

◆ INITIALIZE_PASS()

INITIALIZE_PASS ( MipsBranchExpansion  ,
DEBUG_TYPE  ,
"Expand out of range branch instructions and fix forbidden" " slot hazards"  ,
false  ,
false   
)

Returns a pass that clears pipeline hazards.

Definition at line 185 of file MipsBranchExpansion.cpp.

◆ STATISTIC() [1/2]

STATISTIC ( LongBranches  ,
"Number of long branches."   
)

◆ STATISTIC() [2/2]

STATISTIC ( NumInsertedNops  ,
"Number of nops inserted"   
)

Variable Documentation

◆ ForceLongBranch

cl::opt< bool > ForceLongBranch("force-mips-long-branch", cl::init(false), cl::desc("MIPS: Expand all branches to long format."), cl::Hidden) ( "force-mips-long-branch"  ,
cl::init(false)  ,
cl::desc("MIPS: Expand all branches to long format.")  ,
cl::Hidden   
)
static

◆ SkipLongBranch

cl::opt< bool > SkipLongBranch("skip-mips-long-branch", cl::init(false), cl::desc("MIPS: Skip branch expansion pass."), cl::Hidden) ( "skip-mips-long-branch"  ,
cl::init(false)  ,
cl::desc("MIPS: Skip branch expansion pass.")  ,
cl::Hidden   
)
static