[llvm] 4045b62 - [RISCV] Add macrofusion infrastructure and one example usage.

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 23 08:40:29 PDT 2022


Author: Craig Topper
Date: 2022-06-23T08:38:39-07:00
New Revision: 4045b62d4cc9b366f349aa2786beaaddce179311

URL: https://github.com/llvm/llvm-project/commit/4045b62d4cc9b366f349aa2786beaaddce179311
DIFF: https://github.com/llvm/llvm-project/commit/4045b62d4cc9b366f349aa2786beaaddce179311.diff

LOG: [RISCV] Add macrofusion infrastructure and one example usage.

This adds the macrofusion plumbing and support fusing LUI+ADDI(W).

This is similar to D73643, but handles a different case. Other cases
can be added in the future.

Reviewed By: reames

Differential Revision: https://reviews.llvm.org/D128393

Added: 
    llvm/lib/Target/RISCV/RISCVMacroFusion.cpp
    llvm/lib/Target/RISCV/RISCVMacroFusion.h
    llvm/test/CodeGen/RISCV/macro-fusion-lui-addi.ll

Modified: 
    llvm/lib/Target/RISCV/CMakeLists.txt
    llvm/lib/Target/RISCV/RISCV.td
    llvm/lib/Target/RISCV/RISCVSubtarget.cpp
    llvm/lib/Target/RISCV/RISCVSubtarget.h
    llvm/lib/Target/RISCV/RISCVTargetMachine.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/RISCV/CMakeLists.txt b/llvm/lib/Target/RISCV/CMakeLists.txt
index 6e49b17c12b48..774152cf9e41b 100644
--- a/llvm/lib/Target/RISCV/CMakeLists.txt
+++ b/llvm/lib/Target/RISCV/CMakeLists.txt
@@ -33,6 +33,7 @@ add_llvm_target(RISCVCodeGen
   RISCVISelLowering.cpp
   RISCVLegalizerInfo.cpp
   RISCVMachineFunctionInfo.cpp
+  RISCVMacroFusion.cpp
   RISCVMCInstLower.cpp
   RISCVMergeBaseOffset.cpp
   RISCVRedundantCopyElimination.cpp

diff  --git a/llvm/lib/Target/RISCV/RISCV.td b/llvm/lib/Target/RISCV/RISCV.td
index 2303578a28012..657f89ca18411 100644
--- a/llvm/lib/Target/RISCV/RISCV.td
+++ b/llvm/lib/Target/RISCV/RISCV.td
@@ -435,6 +435,10 @@ def FeatureUnalignedScalarMem
                       "true", "Has reasonably performant unaligned scalar "
                       "loads and stores">;
 
+def TuneLUIADDIFusion
+    : SubtargetFeature<"lui-addi-fusion", "HasLUIADDIFusion",
+                       "true", "Enable LUI+ADDI macrofusion">;
+
 def TuneNoDefaultUnroll
     : SubtargetFeature<"no-default-unroll", "EnableDefaultUnroll", "false",
                        "Disable default unroll preference.">;

diff  --git a/llvm/lib/Target/RISCV/RISCVMacroFusion.cpp b/llvm/lib/Target/RISCV/RISCVMacroFusion.cpp
new file mode 100644
index 0000000000000..3b9177bc1635b
--- /dev/null
+++ b/llvm/lib/Target/RISCV/RISCVMacroFusion.cpp
@@ -0,0 +1,67 @@
+//===- RISCVMacroFusion.cpp - RISCV Macro Fusion --------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file This file contains the RISCV implementation of the DAG scheduling
+/// mutation to pair instructions back to back.
+//
+//===----------------------------------------------------------------------===//
+//
+#include "RISCVMacroFusion.h"
+#include "RISCVSubtarget.h"
+#include "llvm/CodeGen/MacroFusion.h"
+#include "llvm/CodeGen/TargetInstrInfo.h"
+
+using namespace llvm;
+
+// Fuse LUI followed by ADDI or ADDIW.
+// rd = imm[31:0] which decomposes to
+// lui rd, imm[31:12]
+// addi(w) rd, rd, imm[11:0]
+static bool isLUIADDI(const MachineInstr *FirstMI,
+                      const MachineInstr &SecondMI) {
+  if (SecondMI.getOpcode() != RISCV::ADDI &&
+      SecondMI.getOpcode() != RISCV::ADDIW)
+    return false;
+
+  // Assume the 1st instr to be a wildcard if it is unspecified.
+  if (!FirstMI)
+    return true;
+
+  if (FirstMI->getOpcode() != RISCV::LUI)
+    return false;
+
+  // The first operand of ADDI might be a frame index.
+  if (!SecondMI.getOperand(1).isReg())
+    return false;
+
+  Register FirstDest = FirstMI->getOperand(0).getReg();
+
+  // Destination of LUI should be the ADDI(W) source register.
+  if (SecondMI.getOperand(1).getReg() != FirstDest)
+    return false;
+
+  // If the FirstMI destination is non-virtual, it should match the SecondMI
+  // destination.
+  return FirstDest.isVirtual() || SecondMI.getOperand(0).getReg() == FirstDest;
+}
+
+static bool shouldScheduleAdjacent(const TargetInstrInfo &TII,
+                                   const TargetSubtargetInfo &TSI,
+                                   const MachineInstr *FirstMI,
+                                   const MachineInstr &SecondMI) {
+  const RISCVSubtarget &ST = static_cast<const RISCVSubtarget &>(TSI);
+
+  if (ST.hasLUIADDIFusion() && isLUIADDI(FirstMI, SecondMI))
+    return true;
+
+  return false;
+}
+
+std::unique_ptr<ScheduleDAGMutation> llvm::createRISCVMacroFusionDAGMutation() {
+  return createMacroFusionDAGMutation(shouldScheduleAdjacent);
+}

diff  --git a/llvm/lib/Target/RISCV/RISCVMacroFusion.h b/llvm/lib/Target/RISCV/RISCVMacroFusion.h
new file mode 100644
index 0000000000000..c238dacc37f64
--- /dev/null
+++ b/llvm/lib/Target/RISCV/RISCVMacroFusion.h
@@ -0,0 +1,28 @@
+//===- RISCVMacroFusion.h - RISCV Macro Fusion ----------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file This file contains the RISCV definition of the DAG scheduling mutation
+/// to pair instructions back to back.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_RISCV_RISCVMACROFUSION_H
+#define LLVM_LIB_TARGET_RISCV_RISCVMACROFUSION_H
+
+#include "llvm/CodeGen/MachineScheduler.h"
+
+namespace llvm {
+
+/// Note that you have to add:
+///   DAG.addMutation(createRISCVMacroFusionDAGMutation());
+/// to RISCVPassConfig::createMachineScheduler() to have an effect.
+std::unique_ptr<ScheduleDAGMutation> createRISCVMacroFusionDAGMutation();
+
+} // namespace llvm
+
+#endif

diff  --git a/llvm/lib/Target/RISCV/RISCVSubtarget.cpp b/llvm/lib/Target/RISCV/RISCVSubtarget.cpp
index dbdd4cb769165..7589b44b81d3c 100644
--- a/llvm/lib/Target/RISCV/RISCVSubtarget.cpp
+++ b/llvm/lib/Target/RISCV/RISCVSubtarget.cpp
@@ -15,6 +15,7 @@
 #include "RISCVCallLowering.h"
 #include "RISCVFrameLowering.h"
 #include "RISCVLegalizerInfo.h"
+#include "RISCVMacroFusion.h"
 #include "RISCVRegisterBankInfo.h"
 #include "RISCVTargetMachine.h"
 #include "llvm/MC/TargetRegistry.h"
@@ -207,3 +208,8 @@ bool RISCVSubtarget::enableSubRegLiveness() const {
   // load/store.
   return hasVInstructions();
 }
+
+void RISCVSubtarget::getPostRAMutations(
+    std::vector<std::unique_ptr<ScheduleDAGMutation>> &Mutations) const {
+  Mutations.push_back(createRISCVMacroFusionDAGMutation());
+}

diff  --git a/llvm/lib/Target/RISCV/RISCVSubtarget.h b/llvm/lib/Target/RISCV/RISCVSubtarget.h
index 664de38d62f54..e8dc9b31d91c3 100644
--- a/llvm/lib/Target/RISCV/RISCVSubtarget.h
+++ b/llvm/lib/Target/RISCV/RISCVSubtarget.h
@@ -93,6 +93,7 @@ class RISCVSubtarget : public RISCVGenSubtargetInfo {
   bool EnableDefaultUnroll = true;
   bool EnableSaveRestore = false;
   bool EnableUnalignedScalarMem = false;
+  bool HasLUIADDIFusion = false;
   unsigned XLen = 32;
   unsigned ZvlLen = 0;
   MVT XLenVT = MVT::i32;
@@ -184,6 +185,7 @@ class RISCVSubtarget : public RISCVGenSubtargetInfo {
   bool enableDefaultUnroll() const { return EnableDefaultUnroll; }
   bool enableSaveRestore() const { return EnableSaveRestore; }
   bool enableUnalignedScalarMem() const { return EnableUnalignedScalarMem; }
+  bool hasLUIADDIFusion() const { return HasLUIADDIFusion; }
   MVT getXLenVT() const { return XLenVT; }
   unsigned getXLen() const { return XLen; }
   unsigned getFLen() const {
@@ -215,6 +217,8 @@ class RISCVSubtarget : public RISCVGenSubtargetInfo {
     return UserReservedRegister[i];
   }
 
+  bool hasMacroFusion() const { return hasLUIADDIFusion(); }
+
   // Vector codegen related methods.
   bool hasVInstructions() const { return HasStdExtZve32x; }
   bool hasVInstructionsI64() const { return HasStdExtZve64x; }
@@ -257,6 +261,9 @@ class RISCVSubtarget : public RISCVGenSubtargetInfo {
   bool useRVVForFixedLengthVectors() const;
 
   bool enableSubRegLiveness() const override;
+
+  void getPostRAMutations(std::vector<std::unique_ptr<ScheduleDAGMutation>>
+                              &Mutations) const override;
 };
 } // End llvm namespace
 

diff  --git a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
index 726eb6ff00b0f..b2707b753e87a 100644
--- a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
+++ b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
@@ -14,6 +14,7 @@
 #include "MCTargetDesc/RISCVBaseInfo.h"
 #include "RISCV.h"
 #include "RISCVMachineFunctionInfo.h"
+#include "RISCVMacroFusion.h"
 #include "RISCVTargetObjectFile.h"
 #include "RISCVTargetTransformInfo.h"
 #include "TargetInfo/RISCVTargetInfo.h"
@@ -141,6 +142,28 @@ class RISCVPassConfig : public TargetPassConfig {
     return getTM<RISCVTargetMachine>();
   }
 
+  ScheduleDAGInstrs *
+  createMachineScheduler(MachineSchedContext *C) const override {
+    const RISCVSubtarget &ST = C->MF->getSubtarget<RISCVSubtarget>();
+    if (ST.hasMacroFusion()) {
+      ScheduleDAGMILive *DAG = createGenericSchedLive(C);
+      DAG->addMutation(createRISCVMacroFusionDAGMutation());
+      return DAG;
+    }
+    return nullptr;
+  }
+
+  ScheduleDAGInstrs *
+  createPostMachineScheduler(MachineSchedContext *C) const override {
+    const RISCVSubtarget &ST = C->MF->getSubtarget<RISCVSubtarget>();
+    if (ST.hasMacroFusion()) {
+      ScheduleDAGMI *DAG = createGenericSchedPostRA(C);
+      DAG->addMutation(createRISCVMacroFusionDAGMutation());
+      return DAG;
+    }
+    return nullptr;
+  }
+
   void addIRPasses() override;
   bool addPreISel() override;
   bool addInstSelector() override;

diff  --git a/llvm/test/CodeGen/RISCV/macro-fusion-lui-addi.ll b/llvm/test/CodeGen/RISCV/macro-fusion-lui-addi.ll
new file mode 100644
index 0000000000000..b9719f0f66c08
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/macro-fusion-lui-addi.ll
@@ -0,0 +1,28 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+;RUN: llc < %s -mtriple=riscv64 -mattr=+f -mcpu=sifive-u74 -target-abi=lp64f \
+;RUN:   | FileCheck %s --check-prefix=NOFUSION
+;RUN: llc < %s -mtriple=riscv64 -mattr=+f,+lui-addi-fusion -mcpu=sifive-u74 \
+;RUN:   -target-abi=lp64f | FileCheck %s --check-prefix=FUSION
+
+ at .str = private constant [4 x i8] c"%f\0A\00", align 1
+
+define void @foo(i32 signext %0, i32 signext %1) {
+; NOFUSION-LABEL: foo:
+; NOFUSION:       # %bb.0:
+; NOFUSION-NEXT:    lui a0, %hi(.L.str)
+; NOFUSION-NEXT:    fcvt.s.w fa0, a1
+; NOFUSION-NEXT:    addi a0, a0, %lo(.L.str)
+; NOFUSION-NEXT:    tail bar at plt
+;
+; FUSION-LABEL: foo:
+; FUSION:       # %bb.0:
+; FUSION-NEXT:    fcvt.s.w fa0, a1
+; FUSION-NEXT:    lui a0, %hi(.L.str)
+; FUSION-NEXT:    addi a0, a0, %lo(.L.str)
+; FUSION-NEXT:    tail bar at plt
+  %3 = sitofp i32 %1 to float
+  tail call void @bar(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), float %3)
+  ret void
+}
+
+declare void @bar(i8*, float)


        


More information about the llvm-commits mailing list