Skip to content
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

[RISCV][GISel] Implement instruction selection for G_PHI and G_BRCOND. #66970

Closed
wants to merge 1 commit into from

Conversation

topperc
Copy link
Collaborator

@topperc topperc commented Sep 21, 2023

This uses a naive lowering for G_BRCOND to a BNE instruction comparing the register to X0.

This uses a naive lowering for G_BRCOND to a BNE instruction comparing
the register to X0.
@llvmbot
Copy link
Collaborator

llvmbot commented Sep 21, 2023

@llvm/pr-subscribers-llvm-globalisel

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

Changes

This uses a naive lowering for G_BRCOND to a BNE instruction comparing the register to X0.


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

3 Files Affected:

  • (modified) llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp (+39-4)
  • (added) llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/phi-rv32.mir (+88)
  • (added) llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/phi-rv64.mir (+88)
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index 4c246d7de1da952..9fef49cdfd1ffff 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -42,8 +42,7 @@ class RISCVInstructionSelector : public InstructionSelector {
 
 private:
   const TargetRegisterClass *
-  getRegClassForTypeOnBank(LLT Ty, const RegisterBank &RB,
-                           bool GetAllRegSet = false) const;
+  getRegClassForTypeOnBank(LLT Ty, const RegisterBank &RB) const;
 
   bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;
   bool selectCopy(MachineInstr &MI, MachineRegisterInfo &MRI) const;
@@ -136,7 +135,34 @@ bool RISCVInstructionSelector::select(MachineInstr &MI) {
   MachineRegisterInfo &MRI = MF.getRegInfo();
   MachineIRBuilder MIB(MI);
 
-  if (!isPreISelGenericOpcode(Opc)) {
+  if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) {
+    if (Opc == TargetOpcode::PHI || Opc == TargetOpcode::G_PHI) {
+      const Register DefReg = MI.getOperand(0).getReg();
+      const LLT DefTy = MRI.getType(DefReg);
+
+      const RegClassOrRegBank &RegClassOrBank =
+        MRI.getRegClassOrRegBank(DefReg);
+
+      const TargetRegisterClass *DefRC
+        = RegClassOrBank.dyn_cast<const TargetRegisterClass *>();
+      if (!DefRC) {
+        if (!DefTy.isValid()) {
+          LLVM_DEBUG(dbgs() << "PHI operand has no type, not a gvreg?\n");
+          return false;
+        }
+
+        const RegisterBank &RB = *RegClassOrBank.get<const RegisterBank *>();
+        DefRC = getRegClassForTypeOnBank(DefTy, RB);
+        if (!DefRC) {
+          LLVM_DEBUG(dbgs() << "PHI operand has unexpected size/bank\n");
+          return false;
+        }
+      }
+
+      MI.setDesc(TII.get(TargetOpcode::PHI));
+      return RBI.constrainGenericRegister(DefReg, *DefRC, MRI);
+    }
+
     // Certain non-generic instructions also need some special handling.
     if (MI.isCopy())
       return selectCopy(MI, MRI);
@@ -205,6 +231,15 @@ bool RISCVInstructionSelector::select(MachineInstr &MI) {
     if (!selectConstant(MI, MIB, MRI))
       return false;
     break;
+  case TargetOpcode::G_BRCOND: {
+    // TODO: Fold with G_ICMP.
+    auto Bcc = MIB.buildInstr(RISCV::BNE)
+      .addReg(MI.getOperand(0).getReg())
+      .addReg(RISCV::X0)
+      .addMBB(MI.getOperand(1).getMBB());
+    MI.eraseFromParent();
+    return constrainSelectedInstRegOperands(*Bcc, TII, TRI, RBI);
+  }
   default:
     return false;
   }
@@ -224,7 +259,7 @@ void RISCVInstructionSelector::renderNegImm(MachineInstrBuilder &MIB,
 }
 
 const TargetRegisterClass *RISCVInstructionSelector::getRegClassForTypeOnBank(
-    LLT Ty, const RegisterBank &RB, bool GetAllRegSet) const {
+    LLT Ty, const RegisterBank &RB) const {
   if (RB.getID() == RISCV::GPRRegBankID) {
     if (Ty.getSizeInBits() <= 32 || (STI.is64Bit() && Ty.getSizeInBits() == 64))
       return &RISCV::GPRRegClass;
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/phi-rv32.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/phi-rv32.mir
new file mode 100644
index 000000000000000..bc36cbfced584ef
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/phi-rv32.mir
@@ -0,0 +1,88 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -march=riscv32 -run-pass=instruction-select -simplify-mir -verify-machineinstrs %s -o - \
+# RUN: | FileCheck -check-prefix=RV32I %s
+
+---
+name:            phi_i32
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  ; RV32I-LABEL: name: phi_i32
+  ; RV32I: bb.0:
+  ; RV32I-NEXT:   liveins: $x10, $x11, $x12
+  ; RV32I-NEXT: {{  $}}
+  ; RV32I-NEXT:   [[COPY:%[0-9]+]]:gpr = COPY $x10
+  ; RV32I-NEXT:   [[COPY1:%[0-9]+]]:gpr = COPY $x11
+  ; RV32I-NEXT:   [[COPY2:%[0-9]+]]:gpr = COPY $x12
+  ; RV32I-NEXT:   [[ANDI:%[0-9]+]]:gpr = ANDI [[COPY]], 1
+  ; RV32I-NEXT:   BNE [[ANDI]], $x0, %bb.2
+  ; RV32I-NEXT:   PseudoBR %bb.1
+  ; RV32I-NEXT: {{  $}}
+  ; RV32I-NEXT: bb.1:
+  ; RV32I-NEXT: {{  $}}
+  ; RV32I-NEXT: bb.2:
+  ; RV32I-NEXT:   [[PHI:%[0-9]+]]:gpr = PHI [[COPY2]], %bb.1, [[COPY1]], %bb.0
+  ; RV32I-NEXT:   $x10 = COPY [[PHI]]
+  ; RV32I-NEXT:   PseudoRET implicit $x10
+  bb.0:
+    liveins: $x10, $x11, $x12
+
+    %0:gprb(s32) = COPY $x10
+    %1:gprb(s32) = COPY $x11
+    %2:gprb(s32) = COPY $x12
+    %3:gprb(s32) = G_CONSTANT i32 1
+    %4:gprb(s32) = G_AND %0, %3
+    G_BRCOND %4(s32), %bb.2
+    G_BR %bb.1
+
+  bb.1:
+
+  bb.2:
+    %5:gprb(s32) = G_PHI %2(s32), %bb.1, %1(s32), %bb.0
+    $x10 = COPY %5(s32)
+    PseudoRET implicit $x10
+
+...
+---
+name:            phi_ptr
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  ; RV32I-LABEL: name: phi_ptr
+  ; RV32I: bb.0.entry:
+  ; RV32I-NEXT:   liveins: $x10, $x11, $x12
+  ; RV32I-NEXT: {{  $}}
+  ; RV32I-NEXT:   [[COPY:%[0-9]+]]:gpr = COPY $x10
+  ; RV32I-NEXT:   [[COPY1:%[0-9]+]]:gpr = COPY $x11
+  ; RV32I-NEXT:   [[COPY2:%[0-9]+]]:gpr = COPY $x12
+  ; RV32I-NEXT:   [[ANDI:%[0-9]+]]:gpr = ANDI [[COPY]], 1
+  ; RV32I-NEXT:   BNE [[ANDI]], $x0, %bb.2
+  ; RV32I-NEXT:   PseudoBR %bb.1
+  ; RV32I-NEXT: {{  $}}
+  ; RV32I-NEXT: bb.1:
+  ; RV32I-NEXT: {{  $}}
+  ; RV32I-NEXT: bb.2:
+  ; RV32I-NEXT:   [[PHI:%[0-9]+]]:gpr = PHI [[COPY2]], %bb.1, [[COPY1]], %bb.0
+  ; RV32I-NEXT:   $x10 = COPY [[PHI]]
+  ; RV32I-NEXT:   PseudoRET implicit $x10
+  bb.0.entry:
+    liveins: $x10, $x11, $x12
+
+    %0:gprb(s32) = COPY $x10
+    %1:gprb(p0) = COPY $x11
+    %2:gprb(p0) = COPY $x12
+    %3:gprb(s32) = G_CONSTANT i32 1
+    %4:gprb(s32) = G_AND %0, %3
+    G_BRCOND %4(s32), %bb.2
+    G_BR %bb.1
+
+  bb.1:
+
+  bb.2:
+    %5:gprb(p0) = G_PHI %2(p0), %bb.1, %1(p0), %bb.0
+    $x10 = COPY %5(p0)
+    PseudoRET implicit $x10
+
+...
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/phi-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/phi-rv64.mir
new file mode 100644
index 000000000000000..3f960985b617e14
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/phi-rv64.mir
@@ -0,0 +1,88 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -march=riscv64 -run-pass=instruction-select -simplify-mir -verify-machineinstrs %s -o - \
+# RUN: | FileCheck -check-prefix=RV64I %s
+
+---
+name:            phi_i64
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  ; RV64I-LABEL: name: phi_i64
+  ; RV64I: bb.0:
+  ; RV64I-NEXT:   liveins: $x10, $x11, $x12
+  ; RV64I-NEXT: {{  $}}
+  ; RV64I-NEXT:   [[COPY:%[0-9]+]]:gpr = COPY $x10
+  ; RV64I-NEXT:   [[COPY1:%[0-9]+]]:gpr = COPY $x11
+  ; RV64I-NEXT:   [[COPY2:%[0-9]+]]:gpr = COPY $x12
+  ; RV64I-NEXT:   [[ANDI:%[0-9]+]]:gpr = ANDI [[COPY]], 1
+  ; RV64I-NEXT:   BNE [[ANDI]], $x0, %bb.2
+  ; RV64I-NEXT:   PseudoBR %bb.1
+  ; RV64I-NEXT: {{  $}}
+  ; RV64I-NEXT: bb.1:
+  ; RV64I-NEXT: {{  $}}
+  ; RV64I-NEXT: bb.2:
+  ; RV64I-NEXT:   [[PHI:%[0-9]+]]:gpr = PHI [[COPY2]], %bb.1, [[COPY1]], %bb.0
+  ; RV64I-NEXT:   $x10 = COPY [[PHI]]
+  ; RV64I-NEXT:   PseudoRET implicit $x10
+  bb.0:
+    liveins: $x10, $x11, $x12
+
+    %0:gprb(s64) = COPY $x10
+    %1:gprb(s64) = COPY $x11
+    %2:gprb(s64) = COPY $x12
+    %3:gprb(s64) = G_CONSTANT i64 1
+    %4:gprb(s64) = G_AND %0, %3
+    G_BRCOND %4(s64), %bb.2
+    G_BR %bb.1
+
+  bb.1:
+
+  bb.2:
+    %5:gprb(s64) = G_PHI %2(s64), %bb.1, %1(s64), %bb.0
+    $x10 = COPY %5(s64)
+    PseudoRET implicit $x10
+
+...
+---
+name:            phi_ptr
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  ; RV64I-LABEL: name: phi_ptr
+  ; RV64I: bb.0:
+  ; RV64I-NEXT:   liveins: $x10, $x11, $x12
+  ; RV64I-NEXT: {{  $}}
+  ; RV64I-NEXT:   [[COPY:%[0-9]+]]:gpr = COPY $x10
+  ; RV64I-NEXT:   [[COPY1:%[0-9]+]]:gpr = COPY $x11
+  ; RV64I-NEXT:   [[COPY2:%[0-9]+]]:gpr = COPY $x12
+  ; RV64I-NEXT:   [[ANDI:%[0-9]+]]:gpr = ANDI [[COPY]], 1
+  ; RV64I-NEXT:   BNE [[ANDI]], $x0, %bb.2
+  ; RV64I-NEXT:   PseudoBR %bb.1
+  ; RV64I-NEXT: {{  $}}
+  ; RV64I-NEXT: bb.1:
+  ; RV64I-NEXT: {{  $}}
+  ; RV64I-NEXT: bb.2:
+  ; RV64I-NEXT:   [[PHI:%[0-9]+]]:gpr = PHI [[COPY2]], %bb.1, [[COPY1]], %bb.0
+  ; RV64I-NEXT:   $x10 = COPY [[PHI]]
+  ; RV64I-NEXT:   PseudoRET implicit $x10
+  bb.0:
+    liveins: $x10, $x11, $x12
+
+    %0:gprb(s64) = COPY $x10
+    %1:gprb(p0) = COPY $x11
+    %2:gprb(p0) = COPY $x12
+    %3:gprb(s64) = G_CONSTANT i64 1
+    %4:gprb(s64) = G_AND %0, %3
+    G_BRCOND %4(s64), %bb.2
+    G_BR %bb.1
+
+  bb.1:
+
+  bb.2:
+    %5:gprb(p0) = G_PHI %2(p0), %bb.1, %1(p0), %bb.0
+    $x10 = COPY %5(p0)
+    PseudoRET implicit $x10
+
+...

Comment on lines +34 to +35
%3:gprb(s32) = G_CONSTANT i32 1
%4:gprb(s32) = G_AND %0, %3
Copy link
Contributor

Choose a reason for hiding this comment

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

Do you actually need these?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

No. I just ran instruction selection on the output of the regbankselect test for G_PHI which also had them. We don't have a post legalizer combiner enabled right now. Should that remove them through computeKnownBits?

Copy link
Contributor

Choose a reason for hiding this comment

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

It's fine, they're harmless.

Comment on lines +34 to +35
%3:gprb(s32) = G_CONSTANT i32 1
%4:gprb(s32) = G_AND %0, %3
Copy link
Contributor

Choose a reason for hiding this comment

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

It's fine, they're harmless.

Comment on lines +236 to +239
auto Bcc = MIB.buildInstr(RISCV::BNE)
.addReg(MI.getOperand(0).getReg())
.addReg(RISCV::X0)
.addMBB(MI.getOperand(1).getMBB());
Copy link
Contributor

Choose a reason for hiding this comment

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

I think you can do something like this:

  auto Bcc =
      MIB.buildInstr(RISCV::BNE, {}, {MI.getOperand(0), Register(RISCV::X0)})
          .addMBB(MI.getOperand(1).getMBB());

MachineIRBuilder's SrcOp can interpret MachineOperands as register implicitly. You can also pass it RegisterClasses if you need to implicitly create a vreg.

@topperc
Copy link
Collaborator Author

topperc commented Sep 22, 2023

Commited 98eb28b

@topperc topperc closed this Sep 22, 2023
@topperc topperc deleted the pr/gisel-brcond-phi branch September 22, 2023 20:23
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.

None yet

3 participants