1 //===- MipsMulMulBugPass.cpp - Mips VR4300 mulmul bugfix pass -------------===//
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
7 //===----------------------------------------------------------------------===//
9 // Early revisions of the VR4300 have a hardware bug where two consecutive
10 // multiplications can produce an incorrect result in the second multiply.
12 // This pass scans for mul instructions in each basic block and inserts
13 // a nop whenever the following conditions are met:
15 // - The current instruction is a single or double-precision floating-point
17 // - The next instruction is either a mul instruction (any kind)
18 // or a branch instruction.
19 //===----------------------------------------------------------------------===//
22 #include "MipsInstrInfo.h"
23 #include "MipsSubtarget.h"
24 #include "llvm/CodeGen/MachineBasicBlock.h"
25 #include "llvm/CodeGen/MachineFunction.h"
26 #include "llvm/CodeGen/MachineFunctionPass.h"
27 #include "llvm/Support/CommandLine.h"
28 #include "llvm/Support/Debug.h"
29 #include "llvm/Target/TargetMachine.h"
31 #define DEBUG_TYPE "mips-vr4300-mulmul-fix"
37 class MipsMulMulBugFix
: public MachineFunctionPass
{
39 MipsMulMulBugFix() : MachineFunctionPass(ID
) {
40 initializeMipsMulMulBugFixPass(*PassRegistry::getPassRegistry());
43 StringRef
getPassName() const override
{ return "Mips VR4300 mulmul bugfix"; }
45 MachineFunctionProperties
getRequiredProperties() const override
{
46 return MachineFunctionProperties().set(
47 MachineFunctionProperties::Property::NoVRegs
);
50 bool runOnMachineFunction(MachineFunction
&MF
) override
;
55 bool fixMulMulBB(MachineBasicBlock
&MBB
, const MipsInstrInfo
&MipsII
);
60 INITIALIZE_PASS(MipsMulMulBugFix
, "mips-vr4300-mulmul-fix",
61 "Mips VR4300 mulmul bugfix", false, false)
63 char MipsMulMulBugFix::ID
= 0;
65 bool MipsMulMulBugFix::runOnMachineFunction(MachineFunction
&MF
) {
66 const MipsInstrInfo
&MipsII
=
67 *static_cast<const MipsInstrInfo
*>(MF
.getSubtarget().getInstrInfo());
69 bool Modified
= false;
72 Modified
|= fixMulMulBB(MBB
, MipsII
);
77 static bool isFirstMul(const MachineInstr
&MI
) {
78 switch (MI
.getOpcode()) {
89 static bool isSecondMulOrBranch(const MachineInstr
&MI
) {
90 if (MI
.isBranch() || MI
.isIndirectBranch() || MI
.isCall())
93 switch (MI
.getOpcode()) {
109 bool MipsMulMulBugFix::fixMulMulBB(MachineBasicBlock
&MBB
,
110 const MipsInstrInfo
&MipsII
) {
111 bool Modified
= false;
113 MachineBasicBlock::instr_iterator NextMII
;
115 // Iterate through the instructions in the basic block
116 for (MachineBasicBlock::instr_iterator MII
= MBB
.instr_begin(),
118 MII
!= E
; MII
= NextMII
) {
120 NextMII
= next_nodbg(MII
, E
);
122 // Trigger when the current instruction is a mul and the next instruction
123 // is either a mul or a branch in case the branch target start with a mul
124 if (NextMII
!= E
&& isFirstMul(*MII
) && isSecondMulOrBranch(*NextMII
)) {
125 LLVM_DEBUG(dbgs() << "Found mulmul!\n");
127 const MCInstrDesc
&NewMCID
= MipsII
.get(Mips::NOP
);
128 BuildMI(MBB
, NextMII
, DebugLoc(), NewMCID
);
136 FunctionPass
*llvm::createMipsMulMulBugPass() { return new MipsMulMulBugFix(); }