ksyx updated this revision to Diff 347603.
ksyx marked 2 inline comments as done.
ksyx retitled this revision from "[RISCV][Clang] Add -mno-idiv option to 
disable hardware int division" to "[RISCV][Clang] Add -mno-div option to 
disable hardware int division".
ksyx edited the summary of this revision.
ksyx added a reviewer: craig.topper.
ksyx added a comment.

- remove redundant macro definition
- split mul and div handling in `RISCVISelLowering.cpp`
- rename `no-idiv` into `no-div`


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D102839/new/

https://reviews.llvm.org/D102839

Files:
  clang/include/clang/Driver/Options.td
  clang/lib/Basic/Targets/RISCV.cpp
  clang/lib/Basic/Targets/RISCV.h
  clang/lib/Driver/ToolChains/Arch/RISCV.cpp
  clang/test/Driver/riscv-no-div.c
  llvm/lib/Target/RISCV/RISCV.td
  llvm/lib/Target/RISCV/RISCVISelLowering.cpp
  llvm/lib/Target/RISCV/RISCVInstrInfoM.td
  llvm/lib/Target/RISCV/RISCVSubtarget.h
  llvm/test/CodeGen/RISCV/no-div.ll
  llvm/test/MC/RISCV/rv32m-no-div-div.s
  llvm/test/MC/RISCV/rv32m-no-div-mul.s
  llvm/test/MC/RISCV/rv64m-no-div-div.s
  llvm/test/MC/RISCV/rv64m-no-div-mul.s

Index: llvm/test/MC/RISCV/rv64m-no-div-mul.s
===================================================================
--- /dev/null
+++ llvm/test/MC/RISCV/rv64m-no-div-mul.s
@@ -0,0 +1,5 @@
+# RUN: llvm-mc %s -triple=riscv64 -mattr=+m,+no-div -riscv-no-aliases 2>&1 \
+# RUN:     | FileCheck -check-prefixes=CHECK-INST %s
+
+# CHECK-INST: mulw ra, sp, gp
+mulw ra, sp, gp
Index: llvm/test/MC/RISCV/rv64m-no-div-div.s
===================================================================
--- /dev/null
+++ llvm/test/MC/RISCV/rv64m-no-div-div.s
@@ -0,0 +1,14 @@
+# RUN: not llvm-mc %s -triple=riscv64 -mattr=+m,+no-div -riscv-no-aliases 2>&1 \
+# RUN:     | FileCheck -check-prefixes=CHECK-ERROR %s
+
+# CHECK-ERROR: 5:1: error: instruction requires the following: Hardware integral division not disabled
+divw tp, t0, t1
+
+# CHECK-ERROR: 8:1: error: instruction requires the following: Hardware integral division not disabled
+divuw t2, s0, s2
+
+# CHECK-ERROR: 11:1: error: instruction requires the following: Hardware integral division not disabled
+remw a0, a1, a2
+
+# CHECK-ERROR: 14:1: error: instruction requires the following: Hardware integral division not disabled
+remuw a3, a4, a5
Index: llvm/test/MC/RISCV/rv32m-no-div-mul.s
===================================================================
--- /dev/null
+++ llvm/test/MC/RISCV/rv32m-no-div-mul.s
@@ -0,0 +1,14 @@
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+m,+no-div -riscv-no-aliases 2>&1 \
+# RUN:     | FileCheck -check-prefixes=CHECK-INST %s
+
+# CHECK-INST: mul a4, ra, s0
+mul a4, ra, s0
+
+# CHECK-INST: mulh ra, zero, zero
+mulh x1, x0, x0
+
+# CHECK-INST: mulhsu t0, t2, t1
+mulhsu t0, t2, t1
+
+# CHECK-INST: mulhu a5, a4, a3
+mulhu a5, a4, a3
Index: llvm/test/MC/RISCV/rv32m-no-div-div.s
===================================================================
--- /dev/null
+++ llvm/test/MC/RISCV/rv32m-no-div-div.s
@@ -0,0 +1,14 @@
+# RUN: not llvm-mc %s -triple=riscv32 -mattr=+m,+no-div -riscv-no-aliases 2>&1 \
+# RUN:     | FileCheck -check-prefixes=CHECK-ERROR %s
+
+# CHECK-ERROR: 5:1: error: instruction requires the following: Hardware integral division not disabled
+div s0, s0, s0
+
+# CHECK-ERROR: 8:1: error: instruction requires the following: Hardware integral division not disabled
+divu gp, a0, a1
+
+# CHECK-ERROR: 11:1: error: instruction requires the following: Hardware integral division not disabled
+rem s2, s2, s8
+
+# CHECK-ERROR: 14:1: error: instruction requires the following: Hardware integral division not disabled
+remu x18, x18, x24
Index: llvm/test/CodeGen/RISCV/no-div.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/RISCV/no-div.ll
@@ -0,0 +1,45 @@
+; RUN: llc -mtriple=riscv32 -mattr=+m,+no-div -verify-machineinstrs < %s \
+; RUN:  | not FileCheck -check-prefix=CHECK-DIV %s
+; RUN: llc -mtriple=riscv64 -mattr=+m,+no-div -verify-machineinstrs < %s \
+; RUN:  | not FileCheck -check-prefix=CHECK-DIV %s
+; RUN: llc -mtriple=riscv32 -mattr=+m,+no-div -verify-machineinstrs < %s \
+; RUN:  | not FileCheck -check-prefix=CHECK-REM %s
+; RUN: llc -mtriple=riscv64 -mattr=+m,+no-div -verify-machineinstrs < %s \
+; RUN:  | not FileCheck -check-prefix=CHECK-REM %s
+
+; RUN: llc -mtriple=riscv32 -mattr=+m,+no-div -verify-machineinstrs < %s \
+; RUN:  | not FileCheck -check-prefix=CHECK-UDIV %s
+; RUN: llc -mtriple=riscv64 -mattr=+m,+no-div -verify-machineinstrs < %s \
+; RUN:  | not FileCheck -check-prefix=CHECK-UDIV %s
+; RUN: llc -mtriple=riscv32 -mattr=+m,+no-div -verify-machineinstrs < %s \
+; RUN:  | not FileCheck -check-prefix=CHECK-UREM %s
+; RUN: llc -mtriple=riscv64 -mattr=+m,+no-div -verify-machineinstrs < %s \
+; RUN:  | not FileCheck -check-prefix=CHECK-UREM %s
+
+; RUN: llc -mtriple=riscv32 -mattr=+m,+no-div -verify-machineinstrs < %s \
+; RUN:  | FileCheck -check-prefix=CHECK-MUL %s
+; RUN: llc -mtriple=riscv64 -mattr=+m,+no-div -verify-machineinstrs < %s \
+; RUN:  | FileCheck -check-prefix=CHECK-MUL %s
+
+; RUN: llc -mtriple=riscv32 -mattr=+m -verify-machineinstrs < %s \
+; RUN:  | FileCheck -check-prefixes=CHECK-MUL,CHECK-UDIV,CHECK-DIV,CHECK-UREM,CHECK-REM %s
+; RUN: llc -mtriple=riscv64 -mattr=+m -verify-machineinstrs < %s \
+; RUN:  | FileCheck -check-prefixes=CHECK-MUL,CHECK-UDIV,CHECK-DIV,CHECK-UREM,CHECK-REM %s
+
+; This test makes sure even when both M extension no-div option enabled,
+; the compile would not fail. Instead, it will use a fallback solution like
+; calling builtin library functions.
+
+define i32 @foo(i32 %a, i32 %b) {
+    ; CHECK-UDIV: divu{{w?}} {{[as]}}{{[0-9]}}, {{[as]}}{{[0-9]}}, {{[as]}}{{[0-9]}}
+    %1 = udiv i32 %a, %b
+    ; CHECK-DIV: div{{w?}} {{[as]}}{{[0-9]}}, {{[as]}}{{[0-9]}}, {{[as]}}{{[0-9]}}
+    %2 = sdiv i32 %a, %1
+    ; CHECK-MUL: mul{{w?}} {{[as]}}{{[0-9]}}, {{[as]}}{{[0-9]}}, {{[as]}}{{[0-9]}}
+    %3 = mul i32 %b, %2
+    ; CHECK-UREM: remu{{w?}} {{[as]}}{{[0-9]}}, {{[as]}}{{[0-9]}}, {{[as]}}{{[0-9]}}
+    %4 = urem i32 %3, %b
+    ; CHECK-REM: rem {{[as]}}{{[0-9]}}, {{[as]}}{{[0-9]}}, {{[as]}}{{[0-9]}}
+    %5 = srem i32 %4, %a
+    ret i32 %5
+}
Index: llvm/lib/Target/RISCV/RISCVSubtarget.h
===================================================================
--- llvm/lib/Target/RISCV/RISCVSubtarget.h
+++ llvm/lib/Target/RISCV/RISCVSubtarget.h
@@ -60,6 +60,7 @@
   bool EnableLinkerRelax = false;
   bool EnableRVCHintInstrs = true;
   bool EnableSaveRestore = false;
+  bool DisableHardwareIntDiv = false;
   unsigned XLen = 32;
   MVT XLenVT = MVT::i32;
   RISCVABI::ABI TargetABI = RISCVABI::ABI_Unknown;
@@ -127,6 +128,7 @@
   bool enableLinkerRelax() const { return EnableLinkerRelax; }
   bool enableRVCHintInstrs() const { return EnableRVCHintInstrs; }
   bool enableSaveRestore() const { return EnableSaveRestore; }
+  bool disableHardwareIntDiv() const { return DisableHardwareIntDiv; }
   MVT getXLenVT() const { return XLenVT; }
   unsigned getXLen() const { return XLen; }
   RISCVABI::ABI getTargetABI() const { return TargetABI; }
Index: llvm/lib/Target/RISCV/RISCVInstrInfoM.td
===================================================================
--- llvm/lib/Target/RISCV/RISCVInstrInfoM.td
+++ llvm/lib/Target/RISCV/RISCVInstrInfoM.td
@@ -33,6 +33,9 @@
               Sched<[WriteIMul, ReadIMul, ReadIMul]>;
 def MULHU   : ALU_rr<0b0000001, 0b011, "mulhu">,
               Sched<[WriteIMul, ReadIMul, ReadIMul]>;
+} // Predicates = [HasStdExtM]
+
+let Predicates = [HasStdExtM, HasIntDiv] in {
 def DIV     : ALU_rr<0b0000001, 0b100, "div">,
               Sched<[WriteIDiv, ReadIDiv, ReadIDiv]>;
 def DIVU    : ALU_rr<0b0000001, 0b101, "divu">,
@@ -41,11 +44,14 @@
               Sched<[WriteIDiv, ReadIDiv, ReadIDiv]>;
 def REMU    : ALU_rr<0b0000001, 0b111, "remu">,
               Sched<[WriteIDiv, ReadIDiv, ReadIDiv]>;
-} // Predicates = [HasStdExtM]
+} // Predicates = [HasStdExtM, HasIntDiv]
 
 let Predicates = [HasStdExtM, IsRV64] in {
 def MULW    : ALUW_rr<0b0000001, 0b000, "mulw">,
               Sched<[WriteIMul32, ReadIMul32, ReadIMul32]>;
+} // Predicates = [HasStdExtM, IsRV64]
+
+let Predicates = [HasStdExtM, IsRV64, HasIntDiv] in {
 def DIVW    : ALUW_rr<0b0000001, 0b100, "divw">,
               Sched<[WriteIDiv32, ReadIDiv32, ReadIDiv32]>;
 def DIVUW   : ALUW_rr<0b0000001, 0b101, "divuw">,
@@ -54,7 +60,7 @@
               Sched<[WriteIDiv32, ReadIDiv32, ReadIDiv32]>;
 def REMUW   : ALUW_rr<0b0000001, 0b111, "remuw">,
               Sched<[WriteIDiv32, ReadIDiv32, ReadIDiv32]>;
-} // Predicates = [HasStdExtM, IsRV64]
+} // Predicates = [HasStdExtM, IsRV64, HasIntDiv]
 
 //===----------------------------------------------------------------------===//
 // Pseudo-instructions and codegen patterns
@@ -65,16 +71,21 @@
 def : PatGprGpr<mulhs, MULH>;
 def : PatGprGpr<mulhu, MULHU>;
 def : PatGprGpr<riscv_mulhsu, MULHSU>;
+} // Predicates = [HasStdExtM]
+
+let Predicates = [HasStdExtM, HasIntDiv] in {
 def : PatGprGpr<sdiv, DIV>;
 def : PatGprGpr<udiv, DIVU>;
 def : PatGprGpr<srem, REM>;
 def : PatGprGpr<urem, REMU>;
-} // Predicates = [HasStdExtM]
+} // Predicates = [HasStdExtM, HasIntDiv]
 
 let Predicates = [HasStdExtM, IsRV64] in {
 def : Pat<(sext_inreg (mul GPR:$rs1, GPR:$rs2), i32),
           (MULW GPR:$rs1, GPR:$rs2)>;
+} // Predicates = [HasStdExtM, IsRV64]
 
+let Predicates = [HasStdExtM, IsRV64, HasIntDiv] in {
 def : PatGprGpr<riscv_divw, DIVW>;
 def : PatGprGpr<riscv_divuw, DIVUW>;
 def : PatGprGpr<riscv_remuw, REMUW>;
@@ -94,7 +105,7 @@
 // produce a result where res[63:32]=0 and res[31]=1.
 def : Pat<(srem (sexti32 (i64 GPR:$rs1)), (sexti32 (i64 GPR:$rs2))),
           (REMW GPR:$rs1, GPR:$rs2)>;
-} // Predicates = [HasStdExtM, IsRV64]
+} // Predicates = [HasStdExtM, IsRV64, HasIntDiv]
 
 let Predicates = [HasStdExtM, IsRV64, NotHasStdExtZba] in {
 // Special case for calculating the full 64-bit product of a 32x32 unsigned
Index: llvm/lib/Target/RISCV/RISCVISelLowering.cpp
===================================================================
--- llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -205,15 +205,22 @@
     setOperationAction(ISD::MUL, XLenVT, Expand);
     setOperationAction(ISD::MULHS, XLenVT, Expand);
     setOperationAction(ISD::MULHU, XLenVT, Expand);
+  } else {
+    if (Subtarget.is64Bit()) {
+      setOperationAction(ISD::MUL, MVT::i32, Custom);
+      setOperationAction(ISD::MUL, MVT::i128, Custom);
+    } else {
+      setOperationAction(ISD::MUL, MVT::i64, Custom);
+    }
+  }
+
+  if (!Subtarget.hasStdExtM() || Subtarget.disableHardwareIntDiv()) {
     setOperationAction(ISD::SDIV, XLenVT, Expand);
     setOperationAction(ISD::UDIV, XLenVT, Expand);
     setOperationAction(ISD::SREM, XLenVT, Expand);
     setOperationAction(ISD::UREM, XLenVT, Expand);
   } else {
     if (Subtarget.is64Bit()) {
-      setOperationAction(ISD::MUL, MVT::i32, Custom);
-      setOperationAction(ISD::MUL, MVT::i128, Custom);
-
       setOperationAction(ISD::SDIV, MVT::i8, Custom);
       setOperationAction(ISD::UDIV, MVT::i8, Custom);
       setOperationAction(ISD::UREM, MVT::i8, Custom);
@@ -223,8 +230,6 @@
       setOperationAction(ISD::SDIV, MVT::i32, Custom);
       setOperationAction(ISD::UDIV, MVT::i32, Custom);
       setOperationAction(ISD::UREM, MVT::i32, Custom);
-    } else {
-      setOperationAction(ISD::MUL, MVT::i64, Custom);
     }
   }
 
Index: llvm/lib/Target/RISCV/RISCV.td
===================================================================
--- llvm/lib/Target/RISCV/RISCV.td
+++ llvm/lib/Target/RISCV/RISCV.td
@@ -19,6 +19,13 @@
                            AssemblerPredicate<(all_of FeatureStdExtM),
                            "'M' (Integer Multiplication and Division)">;
 
+def FeatureNoIntDiv : SubtargetFeature<"no-div", "DisableHardwareIntDiv", "true",
+                                       "Disable hardware integral division"
+                                       "instructions from M Extension.">;
+def HasIntDiv : Predicate<"!Subtarget->disableHardwareIntDiv()">,
+                          AssemblerPredicate<(all_of (not FeatureNoIntDiv)),
+                          "Hardware integral division not disabled">;
+
 def FeatureStdExtA
     : SubtargetFeature<"a", "HasStdExtA", "true",
                        "'A' (Atomic Instructions)">;
Index: clang/test/Driver/riscv-no-div.c
===================================================================
--- /dev/null
+++ clang/test/Driver/riscv-no-div.c
@@ -0,0 +1,37 @@
+// RUN: %clang -target riscv32-unknown-elf %s -mno-div -S -o - 2>&1 \
+// RUN:   | not FileCheck -check-prefix=CHECK-NOERROR %s
+
+// RUN: %clang -target riscv64-unknown-elf %s -mno-div -S -o - 2>&1 \
+// RUN:   | not FileCheck -check-prefix=CHECK-NOERROR %s
+
+// RUN: %clang -target riscv32-unknown-elf %s -mno-div -S -o - 2>&1 \
+// RUN:   | not FileCheck -check-prefix=CHECK-DIV %s
+
+// RUN: %clang -target riscv64-unknown-elf %s -mno-div -S -o - 2>&1 \
+// RUN:   | not FileCheck -check-prefix=CHECK-DIV %s
+
+// RUN: %clang -target riscv32-unknown-elf %s -mno-div -S -o - 2>&1 \
+// RUN:   | not FileCheck -check-prefix=CHECK-REM %s
+
+// RUN: %clang -target riscv64-unknown-elf %s -mno-div -S -o - 2>&1 \
+// RUN:   | not FileCheck -check-prefix=CHECK-REM %s
+
+// RUN: %clang -target riscv32-unknown-elf %s -mno-div -S -o - 2>&1 \
+// RUN:   | FileCheck -check-prefix=CHECK-MUL %s
+
+// RUN: %clang -target riscv64-unknown-elf %s -mno-div -S -o - 2>&1 \
+// RUN:   | FileCheck -check-prefix=CHECK-MUL %s
+
+// RUN: %clang -target riscv32-unknown-elf %s -S -o - 2>&1 \
+// RUN:   | FileCheck -check-prefixes=CHECK-MUL,CHECK-DIV,CHECK-REM %s
+
+// RUN: %clang -target riscv64-unknown-elf %s -S -o - 2>&1 \
+// RUN:   | FileCheck -check-prefixes=CHECK-MUL,CHECK-DIV,CHECK-REM %s
+
+int foo(int x, int y) {
+    // CHECK-NOERROR: is not a recognized feature for this target
+    // CHECK-DIV: div{{w?}} a{{[0-9]}}, a{{[0-9]}}, a{{[0-9]}}
+    // CHECK-REM: rem{{w?}} a{{[0-9]}}, a{{[0-9]}}, a{{[0-9]}}
+    // CHECK-MUL: mul{{w?}} a{{[0-9]}}, a{{[0-9]}}, a{{[0-9]}}
+    return (x/y)*(x%y);
+}
Index: clang/lib/Driver/ToolChains/Arch/RISCV.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Arch/RISCV.cpp
+++ clang/lib/Driver/ToolChains/Arch/RISCV.cpp
@@ -570,6 +570,12 @@
   // Now add any that the user explicitly requested on the command line,
   // which may override the defaults.
   handleTargetFeaturesGroup(Args, Features, options::OPT_m_riscv_Features_Group);
+  for (auto &Feature : Features)
+    if (Feature == "-div") {
+      Feature = "+no-div";
+    } else if (Feature == "+div") {
+      Feature = "-no-div";
+    }
 }
 
 StringRef riscv::getRISCVABI(const ArgList &Args, const llvm::Triple &Triple) {
Index: clang/lib/Basic/Targets/RISCV.h
===================================================================
--- clang/lib/Basic/Targets/RISCV.h
+++ clang/lib/Basic/Targets/RISCV.h
@@ -46,6 +46,7 @@
   bool HasZfh = false;
   bool HasZvamo = false;
   bool HasZvlsseg = false;
+  bool DisableHardwareIntDiv = false;
 
   static const Builtin::Info BuiltinInfo[];
 
Index: clang/lib/Basic/Targets/RISCV.cpp
===================================================================
--- clang/lib/Basic/Targets/RISCV.cpp
+++ clang/lib/Basic/Targets/RISCV.cpp
@@ -144,8 +144,10 @@
   if (HasM) {
     Builder.defineMacro("__riscv_m", "2000000");
     Builder.defineMacro("__riscv_mul");
-    Builder.defineMacro("__riscv_div");
-    Builder.defineMacro("__riscv_muldiv");
+    if (!DisableHardwareIntDiv) {
+      Builder.defineMacro("__riscv_div");
+      Builder.defineMacro("__riscv_muldiv");
+    }
   }
 
   if (HasA) {
@@ -278,6 +280,7 @@
       .Case("experimental-zfh", HasZfh)
       .Case("experimental-zvamo", HasZvamo)
       .Case("experimental-zvlsseg", HasZvlsseg)
+      .Case("no-div", DisableHardwareIntDiv)
       .Default(false);
 }
 
@@ -327,6 +330,8 @@
       HasZvamo = true;
     else if (Feature == "+experimental-zvlsseg")
       HasZvlsseg = true;
+    else if (Feature == "+no-div")
+      DisableHardwareIntDiv = true;
   }
 
   return true;
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -3146,6 +3146,10 @@
   HelpText<"Enable using library calls for save and restore">;
 def mno_save_restore : Flag<["-"], "mno-save-restore">, Group<m_riscv_Features_Group>,
   HelpText<"Disable using library calls for save and restore">;
+def mno_div : Flag<["-"], "mno-div">, Group<m_riscv_Features_Group>,
+  HelpText<"Disable hardware integral division instructions in M extension">;
+def mdiv : Flag<["-"], "mdiv">, Group<m_riscv_Features_Group>,
+  HelpText<"Enable hardware integral division instructions in M extension">;
 def mcmodel_EQ_medlow : Flag<["-"], "mcmodel=medlow">, Group<m_riscv_Features_Group>,
   Flags<[CC1Option]>, Alias<mcmodel_EQ>, AliasArgs<["small"]>,
   HelpText<"Equivalent to -mcmodel=small, compatible with RISC-V gcc.">;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to