Skip to content

[RISCV][GISel] Add instruction selection for G_SEXT, G_ZEXT, and G_SEXT_INREG #67359

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Sep 25, 2023

Conversation

mshockwave
Copy link
Member

@mshockwave mshockwave commented Sep 25, 2023

G_SEXT and G_ZEXT are supported via patterns imported from SDISel; G_SEXT_INREG is selected using hand-written code as there is no (functional) rule at this moment to import G_SEXT_INREG from ISD::SEXT_INREG.

Credit helps from @topperc on G_SEXT and G_ZEXT.

…XT_INREG

G_SEXT and G_ZEXT are supported via patterns imported from SDISel;
G_SEXT_INREG is selected using hand-written code as there is no
(functional) rule at this moment to import G_SEXT_INREG from sext_inreg.
@llvmbot
Copy link
Member

llvmbot commented Sep 25, 2023

@llvm/pr-subscribers-llvm-globalisel

@llvm/pr-subscribers-backend-risc-v

Changes

G_SEXT and G_ZEXT are supported via patterns imported from SDISel; G_SEXT_INREG is selected using hand-written code as there is no (functional) rule at this moment to import G_SEXT_INREG from ISD::SEXT_INREG.


Full diff: https://github.com/llvm/llvm-project/pull/67359.diff

5 Files Affected:

  • (modified) llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp (+29)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfo.td (+6)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfoZb.td (+2)
  • (added) llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/sext-rv64.mir (+32)
  • (added) llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/zext-rv64.mir (+24)
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index 4a4be79528545f8..0149a8772f7d5e2 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -48,6 +48,7 @@ class RISCVInstructionSelector : public InstructionSelector {
   bool selectCopy(MachineInstr &MI, MachineRegisterInfo &MRI) const;
   bool selectConstant(MachineInstr &MI, MachineIRBuilder &MIB,
                       MachineRegisterInfo &MRI) const;
+  bool selectSExtInreg(MachineInstr &MI, MachineIRBuilder &MIB) const;
 
   bool earlySelectShift(unsigned Opc, MachineInstr &I, MachineIRBuilder &MIB,
                         const MachineRegisterInfo &MRI);
@@ -237,6 +238,8 @@ bool RISCVInstructionSelector::select(MachineInstr &MI) {
     MI.eraseFromParent();
     return constrainSelectedInstRegOperands(*Bcc, TII, TRI, RBI);
   }
+  case TargetOpcode::G_SEXT_INREG:
+    return selectSExtInreg(MI, MIB);
   default:
     return false;
   }
@@ -363,6 +366,32 @@ bool RISCVInstructionSelector::selectConstant(MachineInstr &MI,
   return true;
 }
 
+bool RISCVInstructionSelector::selectSExtInreg(MachineInstr &MI,
+                                               MachineIRBuilder &MIB) const {
+  if (!STI.isRV64())
+    return false;
+
+  const MachineOperand &Size = MI.getOperand(2);
+  // Only Size == 32 (i.e. shift by 32 bits) is acceptable at this point.
+  if (!Size.isImm() || Size.getImm() != 32)
+    return false;
+
+  const MachineOperand &Src = MI.getOperand(1);
+  const MachineOperand &Dst = MI.getOperand(0);
+  assert(Src.isReg() && Dst.isReg());
+  // addiw rd, rs, 0 (i.e. sext.w rd, rs)
+  MachineInstr *NewMI = MIB.buildInstr(RISCV::ADDIW)
+                            .addDef(Dst.getReg())
+                            .addReg(Src.getReg())
+                            .addImm(0U);
+
+  if (!constrainSelectedInstRegOperands(*NewMI, TII, TRI, RBI))
+    return false;
+
+  MI.eraseFromParent();
+  return true;
+}
+
 namespace llvm {
 InstructionSelector *
 createRISCVInstructionSelector(const RISCVTargetMachine &TM,
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index abbeff78b6e2864..12ec4e2c9b46b2c 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -1774,6 +1774,12 @@ let Predicates = [IsRV64], hasSideEffects = 0, mayLoad = 0, mayStore = 0,
 def PseudoZEXT_W : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "zext.w", "$rd, $rs">;
 } // Predicates = [IsRV64], ...
 
+let Predicates = [IsRV64] in
+def: Pat<(i64 (sext i32:$rs)), (ADDIW GPR:$rs, 0)>;
+
+let Predicates = [IsRV64, NotHasStdExtZba] in
+def: Pat<(i64 (zext i32:$rs)), (SRLI (SLLI GPR:$rs, 32), 32)>;
+
 /// Loads
 
 class LdPat<PatFrag LoadOp, RVInst Inst, ValueType vt = XLenVT>
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td
index a21c3d132636bea..8467acdd8148411 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td
@@ -727,6 +727,8 @@ def : Pat<(mul_const_oneuse GPR:$r, (XLenVT 81)),
 } // Predicates = [HasStdExtZba]
 
 let Predicates = [HasStdExtZba, IsRV64] in {
+def : Pat<(i64 (zext i32:$rs)), (ADD_UW GPR:$rs, (XLenVT X0))>;
+
 def : Pat<(i64 (shl (and GPR:$rs1, 0xFFFFFFFF), uimm5:$shamt)),
           (SLLI_UW GPR:$rs1, uimm5:$shamt)>;
 // Match a shifted 0xffffffff mask. Use SRLI to clear the LSBs and SLLI_UW to
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/sext-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/sext-rv64.mir
new file mode 100644
index 000000000000000..50b1257c4ffec74
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/sext-rv64.mir
@@ -0,0 +1,32 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 2
+# RUN: llc -mtriple=riscv64 -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s
+---
+name:            sext_32_64
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:            |
+  bb.0:
+    ; CHECK-LABEL: name: sext_32_64
+    ; CHECK: [[LUI:%[0-9]+]]:gpr = LUI 524288
+    ; CHECK-NEXT: [[ADDIW:%[0-9]+]]:gpr = ADDIW [[LUI]], 0
+    ; CHECK-NEXT: $x8 = COPY [[ADDIW]]
+    %0:gprb(s32) = G_CONSTANT i32 -2147483648
+    %1:gprb(s64) = G_SEXT %0
+    $x8 = COPY %1(s64)
+...
+---
+name:            sext_inreg_64_32
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:            |
+  bb.0:
+    ; CHECK-LABEL: name: sext_inreg_64_32
+    ; CHECK: [[LUI:%[0-9]+]]:gpr = LUI 524288
+    ; CHECK-NEXT: [[ADDIW:%[0-9]+]]:gpr = ADDIW [[LUI]], 0
+    ; CHECK-NEXT: $x8 = COPY [[ADDIW]]
+    %0:gprb(s64) = G_CONSTANT i64 -2147483648
+    %1:gprb(s64) = G_SEXT_INREG %0, 32
+    $x8 = COPY %1(s64)
+...
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/zext-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/zext-rv64.mir
new file mode 100644
index 000000000000000..687be8a13932fe0
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/zext-rv64.mir
@@ -0,0 +1,24 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 2
+# RUN: llc -mtriple=riscv64 -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s
+# RUN: llc -mtriple=riscv64 -run-pass=instruction-select -verify-machineinstrs -mattr='+zba' %s -o - | FileCheck %s --check-prefix=ZBA
+---
+name:            zext_32_64
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:            |
+  bb.0:
+    ; CHECK-LABEL: name: zext_32_64
+    ; CHECK: [[LUI:%[0-9]+]]:gpr = LUI 524288
+    ; CHECK-NEXT: [[SLLI:%[0-9]+]]:gpr = SLLI [[LUI]], 32
+    ; CHECK-NEXT: [[SRLI:%[0-9]+]]:gpr = SRLI [[SLLI]], 32
+    ; CHECK-NEXT: $x8 = COPY [[SRLI]]
+    ;
+    ; ZBA-LABEL: name: zext_32_64
+    ; ZBA: [[LUI:%[0-9]+]]:gpr = LUI 524288
+    ; ZBA-NEXT: [[ADD_UW:%[0-9]+]]:gpr = ADD_UW [[LUI]], $x0
+    ; ZBA-NEXT: $x8 = COPY [[ADD_UW]]
+    %0:gprb(s32) = G_CONSTANT i32 -2147483648
+    %1:gprb(s64) = G_ZEXT %0
+    $x8 = COPY %1(s64)
+...

 - Moved newly created isel patterns into RISCVGISel.td
 - Some minor fixes in `selectSExtInreg`
Copy link
Collaborator

@topperc topperc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@mshockwave mshockwave merged commit 0d7c340 into llvm:main Sep 25, 2023
@mshockwave mshockwave deleted the patch-gisel-ext branch September 25, 2023 22:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants