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
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to