-
Notifications
You must be signed in to change notification settings - Fork 10.8k
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
Conversation
This uses a naive lowering for G_BRCOND to a BNE instruction comparing the register to X0.
@llvm/pr-subscribers-llvm-globalisel @llvm/pr-subscribers-backend-risc-v ChangesThis 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:
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
+
+...
|
%3:gprb(s32) = G_CONSTANT i32 1 | ||
%4:gprb(s32) = G_AND %0, %3 |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
%3:gprb(s32) = G_CONSTANT i32 1 | ||
%4:gprb(s32) = G_AND %0, %3 |
There was a problem hiding this comment.
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.
auto Bcc = MIB.buildInstr(RISCV::BNE) | ||
.addReg(MI.getOperand(0).getReg()) | ||
.addReg(RISCV::X0) | ||
.addMBB(MI.getOperand(1).getMBB()); |
There was a problem hiding this comment.
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 RegisterClass
es if you need to implicitly create a vreg.
Commited 98eb28b |
This uses a naive lowering for G_BRCOND to a BNE instruction comparing the register to X0.