[llvm] [RISCV][GISel] Emit G_CONSTANT 0 as a copy from X0. (PR #67202)

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 22 15:59:25 PDT 2023


https://github.com/topperc updated https://github.com/llvm/llvm-project/pull/67202

>From 82db63fdf4d5ced24cab31ff86bdbfa0287bce06 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Fri, 22 Sep 2023 15:54:48 -0700
Subject: [PATCH 1/2] [RISCV][GISel] Add test showing missed opportunity to use
 X0 for the LHS of sub for negate.

I had to disable the late copy propagation pass that can see through
the ADDI we were previously emitting. We really want to get this
in the register coalescer if not even earlier.
---
 .../CodeGen/RISCV/GlobalISel/alu-roundtrip.ll | 42 ++++++++++++++++++-
 1 file changed, 40 insertions(+), 2 deletions(-)

diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/alu-roundtrip.ll b/llvm/test/CodeGen/RISCV/GlobalISel/alu-roundtrip.ll
index 4fe1691714bb958..be25efdc78d255d 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/alu-roundtrip.ll
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/alu-roundtrip.ll
@@ -1,8 +1,8 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
 ; RUN: llc -mtriple=riscv32 -mattr=+m -global-isel -verify-machineinstrs < %s \
-; RUN:   | FileCheck %s --check-prefix=RV32IM
+; RUN:   -riscv-enable-copy-propagation=false | FileCheck %s --check-prefix=RV32IM
 ; RUN: llc -mtriple=riscv64 -mattr=+m -global-isel -verify-machineinstrs < %s \
-; RUN:   | FileCheck %s --check-prefix=RV64IM
+; RUN:   -riscv-enable-copy-propagation=false | FileCheck %s --check-prefix=RV64IM
 
 ; Extends to 32 bits exhaustively tested for add only.
 
@@ -130,6 +130,23 @@ entry:
   ret i32 %0
 }
 
+define i32 @neg_i32(i32 %a) {
+; RV32IM-LABEL: neg_i32:
+; RV32IM:       # %bb.0: # %entry
+; RV32IM-NEXT:    li a1, 0
+; RV32IM-NEXT:    sub a0, a1, a0
+; RV32IM-NEXT:    ret
+;
+; RV64IM-LABEL: neg_i32:
+; RV64IM:       # %bb.0: # %entry
+; RV64IM-NEXT:    li a1, 0
+; RV64IM-NEXT:    subw a0, a1, a0
+; RV64IM-NEXT:    ret
+entry:
+  %0 = sub i32 0, %a
+  ret i32 %0
+}
+
 define i32 @sll_i32(i32 %a, i32 %b) {
 ; RV32IM-LABEL: sll_i32:
 ; RV32IM:       # %bb.0: # %entry
@@ -461,6 +478,27 @@ entry:
   ret i64 %0
 }
 
+define i64 @neg_i64(i64 %a) {
+; RV32IM-LABEL: neg_i64:
+; RV32IM:       # %bb.0: # %entry
+; RV32IM-NEXT:    li a3, 0
+; RV32IM-NEXT:    sub a2, a3, a0
+; RV32IM-NEXT:    sltu a0, a3, a0
+; RV32IM-NEXT:    sub a1, a3, a1
+; RV32IM-NEXT:    sub a1, a1, a0
+; RV32IM-NEXT:    mv a0, a2
+; RV32IM-NEXT:    ret
+;
+; RV64IM-LABEL: neg_i64:
+; RV64IM:       # %bb.0: # %entry
+; RV64IM-NEXT:    li a1, 0
+; RV64IM-NEXT:    sub a0, a1, a0
+; RV64IM-NEXT:    ret
+entry:
+  %0 = sub i64 0, %a
+  ret i64 %0
+}
+
 ; TODO: Handle G_SELECT, which is needed to have i64 shifts working on RV32.
 
 define i64 @and_i64(i64 %a, i64 %b) {

>From ea2fa405166a13cb712d6272dc1bf2c0a3bf77cc Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Fri, 22 Sep 2023 15:41:18 -0700
Subject: [PATCH 2/2] [RISCV][GISel] Emit G_CONSTANT 0 as a copy from X0.

We need to use a COPY so the register coalescer can replace reads
of the register we copy to with X0. This is needed so that we use
X0 on instructions that don't have an immediate form.
---
 .../RISCV/GISel/RISCVInstructionSelector.cpp     | 16 +++++++++-------
 .../CodeGen/RISCV/GlobalISel/alu-roundtrip.ll    | 16 ++++++----------
 .../GlobalISel/instruction-select/constant32.mir |  4 ++--
 .../GlobalISel/instruction-select/constant64.mir |  8 ++++----
 4 files changed, 21 insertions(+), 23 deletions(-)

diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index a6163396b72d72f..4a4be79528545f8 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -228,9 +228,7 @@ bool RISCVInstructionSelector::select(MachineInstr &MI) {
     MI.setDesc(TII.get(TargetOpcode::COPY));
     return true;
   case TargetOpcode::G_CONSTANT:
-    if (!selectConstant(MI, MIB, MRI))
-      return false;
-    break;
+    return selectConstant(MI, MIB, MRI);
   case TargetOpcode::G_BRCOND: {
     // TODO: Fold with G_ICMP.
     auto Bcc =
@@ -242,10 +240,6 @@ bool RISCVInstructionSelector::select(MachineInstr &MI) {
   default:
     return false;
   }
-
-  MI.eraseFromParent();
-
-  return true;
 }
 
 void RISCVInstructionSelector::renderNegImm(MachineInstrBuilder &MIB,
@@ -312,6 +306,13 @@ bool RISCVInstructionSelector::selectConstant(MachineInstr &MI,
   Register FinalReg = MI.getOperand(0).getReg();
   int64_t Imm = MI.getOperand(1).getCImm()->getSExtValue();
 
+  if (Imm == 0) {
+    MI.getOperand(1).ChangeToRegister(RISCV::X0, false);
+    RBI.constrainGenericRegister(FinalReg, RISCV::GPRRegClass, MRI);
+    MI.setDesc(TII.get(TargetOpcode::COPY));
+    return true;
+  }
+
   RISCVMatInt::InstSeq Seq =
       RISCVMatInt::generateInstSeq(Imm, Subtarget->getFeatureBits());
   unsigned NumInsts = Seq.size();
@@ -358,6 +359,7 @@ bool RISCVInstructionSelector::selectConstant(MachineInstr &MI,
     SrcReg = DstReg;
   }
 
+  MI.eraseFromParent();
   return true;
 }
 
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/alu-roundtrip.ll b/llvm/test/CodeGen/RISCV/GlobalISel/alu-roundtrip.ll
index be25efdc78d255d..c503d6541b0a577 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/alu-roundtrip.ll
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/alu-roundtrip.ll
@@ -133,14 +133,12 @@ entry:
 define i32 @neg_i32(i32 %a) {
 ; RV32IM-LABEL: neg_i32:
 ; RV32IM:       # %bb.0: # %entry
-; RV32IM-NEXT:    li a1, 0
-; RV32IM-NEXT:    sub a0, a1, a0
+; RV32IM-NEXT:    neg a0, a0
 ; RV32IM-NEXT:    ret
 ;
 ; RV64IM-LABEL: neg_i32:
 ; RV64IM:       # %bb.0: # %entry
-; RV64IM-NEXT:    li a1, 0
-; RV64IM-NEXT:    subw a0, a1, a0
+; RV64IM-NEXT:    negw a0, a0
 ; RV64IM-NEXT:    ret
 entry:
   %0 = sub i32 0, %a
@@ -481,18 +479,16 @@ entry:
 define i64 @neg_i64(i64 %a) {
 ; RV32IM-LABEL: neg_i64:
 ; RV32IM:       # %bb.0: # %entry
-; RV32IM-NEXT:    li a3, 0
-; RV32IM-NEXT:    sub a2, a3, a0
-; RV32IM-NEXT:    sltu a0, a3, a0
-; RV32IM-NEXT:    sub a1, a3, a1
+; RV32IM-NEXT:    neg a2, a0
+; RV32IM-NEXT:    snez a0, a0
+; RV32IM-NEXT:    neg a1, a1
 ; RV32IM-NEXT:    sub a1, a1, a0
 ; RV32IM-NEXT:    mv a0, a2
 ; RV32IM-NEXT:    ret
 ;
 ; RV64IM-LABEL: neg_i64:
 ; RV64IM:       # %bb.0: # %entry
-; RV64IM-NEXT:    li a1, 0
-; RV64IM-NEXT:    sub a0, a1, a0
+; RV64IM-NEXT:    neg a0, a0
 ; RV64IM-NEXT:    ret
 entry:
   %0 = sub i64 0, %a
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/constant32.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/constant32.mir
index e1715c7a330d0ea..4af5d1c6173b44a 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/constant32.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/constant32.mir
@@ -115,8 +115,8 @@ body:            |
     ; CHECK-LABEL: name: const_i32_0
     ; CHECK: liveins: $x10
     ; CHECK-NEXT: {{  $}}
-    ; CHECK-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI $x0, 0
-    ; CHECK-NEXT: $x10 = COPY [[ADDI]]
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x0
+    ; CHECK-NEXT: $x10 = COPY [[COPY]]
     ; CHECK-NEXT: PseudoRET implicit $x10
     %0:gprb(s32) = G_CONSTANT i32 0
     $x10 = COPY %0(s32)
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/constant64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/constant64.mir
index 6c6410f2f9293d6..bcd4a225a321129 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/constant64.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/constant64.mir
@@ -118,8 +118,8 @@ body:            |
     ; CHECK-LABEL: name: const_i64_0
     ; CHECK: liveins: $x10
     ; CHECK-NEXT: {{  $}}
-    ; CHECK-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI $x0, 0
-    ; CHECK-NEXT: $x10 = COPY [[ADDI]]
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x0
+    ; CHECK-NEXT: $x10 = COPY [[COPY]]
     ; CHECK-NEXT: PseudoRET implicit $x10
     %0:gprb(s64) = G_CONSTANT i64 0
     $x10 = COPY %0(s64)
@@ -245,8 +245,8 @@ body:            |
     ; CHECK-LABEL: name: const_i32_0
     ; CHECK: liveins: $x10
     ; CHECK-NEXT: {{  $}}
-    ; CHECK-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI $x0, 0
-    ; CHECK-NEXT: $x10 = COPY [[ADDI]]
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x0
+    ; CHECK-NEXT: $x10 = COPY [[COPY]]
     ; CHECK-NEXT: PseudoRET implicit $x10
     %0:gprb(s32) = G_CONSTANT i32 0
     %1:gprb(s64) = G_ANYEXT %0(s32)



More information about the llvm-commits mailing list