LLVM 24.0.0git
MipsMulMulBugPass.cpp
Go to the documentation of this file.
1//===- MipsMulMulBugPass.cpp - Mips VR4300 mulmul bugfix pass -------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Early revisions of the VR4300 have a hardware bug where two consecutive
10// multiplications can produce an incorrect result in the second multiply.
11//
12// This pass scans for mul instructions in each basic block and inserts
13// a nop whenever the following conditions are met:
14//
15// - The current instruction is a single or double-precision floating-point
16// mul instruction.
17// - The next instruction is either a mul instruction (any kind)
18// or a branch instruction.
19//===----------------------------------------------------------------------===//
20
21#include "Mips.h"
22#include "MipsInstrInfo.h"
23#include "MipsSubtarget.h"
29#include "llvm/IR/Analysis.h"
30#include "llvm/Pass.h"
31#include "llvm/Support/Debug.h"
33
34#define DEBUG_TYPE "mips-mulmul-bug-fix"
35
36using namespace llvm;
37
38namespace {
39
40class MipsMulMulBugFixLegacy : public MachineFunctionPass {
41public:
42 MipsMulMulBugFixLegacy() : MachineFunctionPass(ID) {}
43
44 StringRef getPassName() const override { return "Mips VR4300 mulmul bugfix"; }
45
46 MachineFunctionProperties getRequiredProperties() const override {
47 return MachineFunctionProperties().setNoVRegs();
48 }
49
50 bool runOnMachineFunction(MachineFunction &MF) override;
51
52 void getAnalysisUsage(AnalysisUsage &AU) const override {
53 AU.setPreservesCFG();
55 }
56
57 static char ID;
58};
59
60} // namespace
61
62INITIALIZE_PASS(MipsMulMulBugFixLegacy, "mips-mulmul-bug-fix",
63 "Mips VR4300 mulmul bugfix", false, false)
64
65char MipsMulMulBugFixLegacy::ID = 0;
66
68 switch (MI.getOpcode()) {
69 case Mips::FMUL_S:
70 case Mips::FMUL_D:
71 case Mips::FMUL_D32:
72 case Mips::FMUL_D64:
73 return true;
74 default:
75 return false;
76 }
77}
78
79static bool isSecondMulOrBranch(const MachineInstr &MI) {
80 if (MI.isBranch() || MI.isIndirectBranch() || MI.isCall())
81 return true;
82
83 switch (MI.getOpcode()) {
84 case Mips::MUL:
85 case Mips::FMUL_S:
86 case Mips::FMUL_D:
87 case Mips::FMUL_D32:
88 case Mips::FMUL_D64:
89 case Mips::MULT:
90 case Mips::MULTu:
91 case Mips::DMULT:
92 case Mips::DMULTu:
93 return true;
94 default:
95 return false;
96 }
97}
98
100 bool Modified = false;
101
103
104 // Iterate through the instructions in the basic block
105 for (MachineBasicBlock::instr_iterator MII = MBB.instr_begin(),
106 E = MBB.instr_end();
107 MII != E; MII = NextMII) {
108
109 NextMII = next_nodbg(MII, E);
110
111 // Trigger when the current instruction is a mul and the next instruction
112 // is either a mul or a branch in case the branch target start with a mul
113 if (NextMII != E && isFirstMul(*MII) && isSecondMulOrBranch(*NextMII)) {
114 LLVM_DEBUG(dbgs() << "Found mulmul!\n");
115
116 const MCInstrDesc &NewMCID = MipsII.get(Mips::NOP);
117 BuildMI(MBB, NextMII, DebugLoc(), NewMCID);
118 Modified = true;
119 }
120 }
121
122 return Modified;
123}
124
126 const MipsInstrInfo &MipsII =
127 *static_cast<const MipsInstrInfo *>(MF.getSubtarget().getInstrInfo());
128
129 bool Modified = false;
130
131 for (auto &MBB : MF)
133
134 return Modified;
135}
136
138 return new MipsMulMulBugFixLegacy();
139}
140
141bool MipsMulMulBugFixLegacy::runOnMachineFunction(MachineFunction &MF) {
142 return fixMulMulBugInMF(MF);
143}
144
145PreservedAnalyses
aarch64 promote const
MachineBasicBlock & MBB
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
IRTranslator LLVM IR MI
static bool fixMulMulBB(MachineBasicBlock &MBB, const MipsInstrInfo &MipsII)
static bool isSecondMulOrBranch(const MachineInstr &MI)
static INITIALIZE_PASS(MipsMulMulBugFixLegacy, "mips-mulmul-bug-fix", "Mips VR4300 mulmul bugfix", false, false) char MipsMulMulBugFixLegacy bool isFirstMul(const MachineInstr &MI)
static bool fixMulMulBugInMF(MachineFunction &MF)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
#define LLVM_DEBUG(...)
Definition Debug.h:119
Represent the analysis usage information of a pass.
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition Pass.cpp:280
Represents analyses that only rely on functions' control flow.
Definition Analysis.h:73
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:312
Describe properties that are true of each instruction in the target description file.
Instructions::iterator instr_iterator
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
Properties which a MachineFunction may have at a given point in time.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Representation of each machine instruction.
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
Definition Analysis.h:151
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
Pass manager infrastructure for declaring and invalidating analyses.
MipsII - This namespace holds all of the target specific flags that instruction info tracks.
This is an optimization pass for GlobalISel generic memory operations.
IterT next_nodbg(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It, then continue incrementing it while it points to a debug instruction.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
FunctionPass * createMipsMulMulBugFixLegacyPass()