This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG2edcde00cb39: [MIPS] Add -mfix4300 flag to enable vr4300
mulmul bugfix pass (authored by Random06457, committed by atanasyan).
Changed prior to commit:
https://reviews.llvm.org/D116238?vs=396171&id=396774#toc
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D116238/new/
https://reviews.llvm.org/D116238
Files:
clang/include/clang/Driver/Options.td
clang/lib/Driver/ToolChains/Clang.cpp
llvm/lib/Target/Mips/CMakeLists.txt
llvm/lib/Target/Mips/Mips.h
llvm/lib/Target/Mips/MipsMulMulBugPass.cpp
llvm/lib/Target/Mips/MipsTargetMachine.cpp
llvm/test/CodeGen/Mips/vr4300-mulbranch.ll
llvm/test/CodeGen/Mips/vr4300-mulmul.ll
Index: llvm/test/CodeGen/Mips/vr4300-mulmul.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/Mips/vr4300-mulmul.ll
@@ -0,0 +1,24 @@
+; RUN: llc -march=mips -mfix4300 -verify-machineinstrs < %s | FileCheck %s
+
+; Function Attrs: mustprogress nofree norecurse nosync nounwind readnone willreturn
+define dso_local float @fun_s(float %x) local_unnamed_addr #0 {
+entry:
+; CHECK-LABEL: fun_s
+; CHECK: mul.s
+; CHECK-NEXT: nop
+; CHECK: mul.s
+ %mul = fmul float %x, %x
+ %mul1 = fmul float %mul, %x
+ ret float %mul1
+}
+
+define dso_local double @fun_d(double %x) local_unnamed_addr #0 {
+entry:
+; CHECK-LABEL: fun_d
+; CHECK: mul.d
+; CHECK-NEXT: nop
+; CHECK: mul.d
+ %mul = fmul double %x, %x
+ %mul1 = fmul double %mul, %x
+ ret double %mul1
+}
Index: llvm/test/CodeGen/Mips/vr4300-mulbranch.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/Mips/vr4300-mulbranch.ll
@@ -0,0 +1,27 @@
+; RUN: llc -march=mips -mfix4300 -verify-machineinstrs < %s | FileCheck %s
+
+; Function Attrs: nounwind
+define dso_local void @fun_s(float %a) local_unnamed_addr #0 {
+entry:
+; CHECK-LABEL: fun_s
+; CHECK: mul.s
+; CHECK-NEXT: nop
+ %mul = fmul float %a, %a
+ tail call void @foo_s(float %mul) #2
+ ret void
+}
+
+declare dso_local void @foo_s(float) local_unnamed_addr #1
+
+; Function Attrs: nounwind
+define dso_local void @fun_d(double %a) local_unnamed_addr #0 {
+entry:
+; CHECK-LABEL: fun_d
+; CHECK: mul.d
+; CHECK-NEXT: nop
+ %mul = fmul double %a, %a
+ tail call void @foo_d(double %mul) #2
+ ret void
+}
+
+declare dso_local void @foo_d(double) local_unnamed_addr #1
Index: llvm/lib/Target/Mips/MipsTargetMachine.cpp
===================================================================
--- llvm/lib/Target/Mips/MipsTargetMachine.cpp
+++ llvm/lib/Target/Mips/MipsTargetMachine.cpp
@@ -45,6 +45,10 @@
#define DEBUG_TYPE "mips"
+static cl::opt<bool>
+ EnableMulMulFix("mfix4300", cl::init(false),
+ cl::desc("Enable the VR4300 mulmul bug fix."), cl::Hidden);
+
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMipsTarget() {
// Register the target.
RegisterTargetMachine<MipsebTargetMachine> X(getTheMipsTarget());
@@ -58,6 +62,7 @@
initializeMipsBranchExpansionPass(*PR);
initializeMicroMipsSizeReducePass(*PR);
initializeMipsPreLegalizerCombinerPass(*PR);
+ initializeMipsMulMulBugFixPass(*PR);
}
static std::string computeDataLayout(const Triple &TT, StringRef CPU,
@@ -292,6 +297,11 @@
// instructions which can be remapped to a 16 bit instruction.
addPass(createMicroMipsSizeReducePass());
+ // This pass inserts a nop instruction between two back-to-back multiplication
+ // instructions when the "mfix4300" flag is passed.
+ if (EnableMulMulFix)
+ addPass(createMipsMulMulBugPass());
+
// The delay slot filler pass can potientially create forbidden slot hazards
// for MIPSR6 and therefore it should go before MipsBranchExpansion pass.
addPass(createMipsDelaySlotFillerPass());
Index: llvm/lib/Target/Mips/MipsMulMulBugPass.cpp
===================================================================
--- /dev/null
+++ llvm/lib/Target/Mips/MipsMulMulBugPass.cpp
@@ -0,0 +1,134 @@
+//===- MipsMulMulBugPass.cpp - Mips VR4300 mulmul bugfix pass -------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Early revisions of the VR4300 have a hardware bug where two consecutive
+// multiplications can produce an incorrect result in the second multiply.
+//
+// This pass scans for mul instructions in each basic block and inserts
+// a nop whenever the following conditions are met:
+//
+// - The current instruction is a single or double-precision floating-point
+// mul instruction.
+// - The next instruction is either a mul instruction (any kind)
+// or a branch instruction.
+//===----------------------------------------------------------------------===//
+
+#include "Mips.h"
+#include "MipsInstrInfo.h"
+#include "MipsSubtarget.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Target/TargetMachine.h"
+
+#define DEBUG_TYPE "mips-vr4300-mulmul-fix"
+
+using namespace llvm;
+
+namespace {
+
+class MipsMulMulBugFix : public MachineFunctionPass {
+public:
+ MipsMulMulBugFix() : MachineFunctionPass(ID) {
+ initializeMipsMulMulBugFixPass(*PassRegistry::getPassRegistry());
+ }
+
+ StringRef getPassName() const override { return "Mips VR4300 mulmul bugfix"; }
+
+ MachineFunctionProperties getRequiredProperties() const override {
+ return MachineFunctionProperties().set(
+ MachineFunctionProperties::Property::NoVRegs);
+ }
+
+ bool runOnMachineFunction(MachineFunction &MF) override;
+
+ static char ID;
+
+private:
+ bool fixMulMulBB(MachineBasicBlock &MBB, const MipsInstrInfo &MipsII);
+};
+
+} // namespace
+
+INITIALIZE_PASS(MipsMulMulBugFix, "mips-vr4300-mulmul-fix",
+ "Mips VR4300 mulmul bugfix", false, false)
+
+char MipsMulMulBugFix::ID = 0;
+
+bool MipsMulMulBugFix::runOnMachineFunction(MachineFunction &MF) {
+ const MipsInstrInfo &MipsII =
+ *static_cast<const MipsInstrInfo *>(MF.getSubtarget().getInstrInfo());
+
+ bool Modified = false;
+
+ for (auto &MBB : MF)
+ Modified |= fixMulMulBB(MBB, MipsII);
+
+ return Modified;
+}
+
+static bool isFirstMul(const MachineInstr &MI) {
+ switch (MI.getOpcode()) {
+ case Mips::FMUL_S:
+ case Mips::FMUL_D:
+ case Mips::FMUL_D32:
+ case Mips::FMUL_D64:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool isSecondMulOrBranch(const MachineInstr &MI) {
+ if (MI.isBranch() || MI.isIndirectBranch() || MI.isCall())
+ return true;
+
+ switch (MI.getOpcode()) {
+ case Mips::MUL:
+ case Mips::FMUL_S:
+ case Mips::FMUL_D:
+ case Mips::FMUL_D32:
+ case Mips::FMUL_D64:
+ case Mips::MULT:
+ case Mips::MULTu:
+ case Mips::DMULT:
+ case Mips::DMULTu:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool MipsMulMulBugFix::fixMulMulBB(MachineBasicBlock &MBB,
+ const MipsInstrInfo &MipsII) {
+ bool Modified = false;
+
+ // Iterate through the instructions in the basic block
+ for (MachineBasicBlock::instr_iterator MII = MBB.instr_begin(),
+ E = MBB.instr_end();
+ MII != E; ++MII) {
+
+ MachineBasicBlock::instr_iterator NextMII = std::next(MII);
+
+ // Trigger when the current instruction is a mul and the next instruction
+ // is either a mul or a branch in case the branch target start with a mul
+ if (NextMII != E && isFirstMul(*MII) && isSecondMulOrBranch(*NextMII)) {
+ LLVM_DEBUG(dbgs() << "Found mulmul!");
+
+ const MCInstrDesc &NewMCID = MipsII.get(Mips::NOP);
+ BuildMI(MBB, NextMII, DebugLoc(), NewMCID);
+ Modified = true;
+ }
+ }
+
+ return Modified;
+}
+
+FunctionPass *llvm::createMipsMulMulBugPass() { return new MipsMulMulBugFix(); }
Index: llvm/lib/Target/Mips/Mips.h
===================================================================
--- llvm/lib/Target/Mips/Mips.h
+++ llvm/lib/Target/Mips/Mips.h
@@ -38,6 +38,7 @@
FunctionPass *createMicroMipsSizeReducePass();
FunctionPass *createMipsExpandPseudoPass();
FunctionPass *createMipsPreLegalizeCombiner();
+ FunctionPass *createMipsMulMulBugPass();
InstructionSelector *createMipsInstructionSelector(const MipsTargetMachine &,
MipsSubtarget &,
@@ -47,6 +48,7 @@
void initializeMipsBranchExpansionPass(PassRegistry &);
void initializeMicroMipsSizeReducePass(PassRegistry &);
void initializeMipsPreLegalizerCombinerPass(PassRegistry&);
+ void initializeMipsMulMulBugFixPass(PassRegistry&);
} // end namespace llvm;
#endif
Index: llvm/lib/Target/Mips/CMakeLists.txt
===================================================================
--- llvm/lib/Target/Mips/CMakeLists.txt
+++ llvm/lib/Target/Mips/CMakeLists.txt
@@ -59,6 +59,7 @@
MipsTargetMachine.cpp
MipsTargetObjectFile.cpp
MicroMipsSizeReduction.cpp
+ MipsMulMulBugPass.cpp
LINK_COMPONENTS
Analysis
Index: clang/lib/Driver/ToolChains/Clang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -1929,6 +1929,11 @@
}
}
+ if (Arg *A = Args.getLastArg(options::OPT_mfix4300)) {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-mfix4300");
+ }
+
if (Arg *A = Args.getLastArg(options::OPT_G)) {
StringRef v = A->getValue();
CmdArgs.push_back("-mllvm");
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -3617,6 +3617,7 @@
Group<m_mips_Features_Group>;
def mno_check_zero_division : Flag<["-"], "mno-check-zero-division">,
Group<m_mips_Features_Group>;
+def mfix4300 : Flag<["-"], "mfix4300">, Group<m_mips_Features_Group>;
def mcompact_branches_EQ : Joined<["-"], "mcompact-branches=">,
Group<m_mips_Features_Group>;
def mbranch_likely : Flag<["-"], "mbranch-likely">, Group<m_Group>,
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits