[llvm] [RISCV][TII] Add and use new hook fo optimize/canonicalize instructions after MachineCopyPropagation (PR #137973)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Apr 30 07:35:15 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-regalloc
Author: Alex Bradbury (asb)
<details>
<summary>Changes</summary>
PR #<!-- -->136875 was posted as a draft PR that handled a subset of these cases, using the CompressPat mechanism. The consensus from that discussion (and a conclusion I agree with) is that it would be beneficial doing this optimisation earlier on, and in a way that isn't limited just to cases that can be handled by instruction compression.
The most common source for instructions that can be optimized/canonicalized in this way is through tail duplication followed by machine copy propagation. For RISC-V, choosing a more canonical instruction allows it to be compressed when it couldn't be before. There is the potential that it would make other MI-level optimisations easier.
This modifies ~910 instructions across an llvm-test-suite build including SPEC2017, targeting rva22u64. Looking at the diff, it seems there's room for eliminating instructions or further propagating after this.
Coverage of instructions is based on observations from a script written to find redundant or improperly canonicalized instructions (though I aim to support all instructions in a 'group' at once, e.g. MUL* even if I only saw some variants of MUL in practice).
---
The obvious thing to bikeshed is the name of the hook. I do worry based on the name, it might be assumed to be a more generic form of other hooks like `optimizeCompareInstr` or `optimizeSelect`. Alternate names welcome. `optimizeMutatedInstruction` might capture the idea that this is intended to be run after you mutate the operands of an instruction in order to optimize/canonicalize it to a "better" one if possible.
This ended up covering rather a lot more instructions than I originally thought, so I'd appreciate extra eyes checking there are no silly mistakes in the matched patterns.
---
Patch is 26.46 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/137973.diff
5 Files Affected:
- (modified) llvm/include/llvm/CodeGen/TargetInstrInfo.h (+10)
- (modified) llvm/lib/CodeGen/MachineCopyPropagation.cpp (+6)
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfo.cpp (+218)
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfo.h (+2)
- (added) llvm/test/CodeGen/RISCV/machine-copyprop-optimizeinstr.mir (+685)
``````````diff
diff --git a/llvm/include/llvm/CodeGen/TargetInstrInfo.h b/llvm/include/llvm/CodeGen/TargetInstrInfo.h
index 0aac02d3dc786..3b33989d28c77 100644
--- a/llvm/include/llvm/CodeGen/TargetInstrInfo.h
+++ b/llvm/include/llvm/CodeGen/TargetInstrInfo.h
@@ -510,6 +510,16 @@ class TargetInstrInfo : public MCInstrInfo {
return false;
}
+ /// If possible, converts the instruction to a more 'optimized'/canonical
+ /// form. Returns true if the instruction was modified.
+ ///
+ /// This function is only called after register allocation. The MI will be
+ /// modified in place. This is called by passes such as
+ /// MachineCopyPropagation, where their mutation of the MI operands may
+ /// expose opportunities to convert the instruction to a simpler form (e.g.
+ /// a load of 0).
+ virtual bool optimizeInstruction(MachineInstr &MI) const { return false; }
+
/// A pair composed of a register and a sub-register index.
/// Used to give some type checking when modeling Reg:SubReg.
struct RegSubRegPair {
diff --git a/llvm/lib/CodeGen/MachineCopyPropagation.cpp b/llvm/lib/CodeGen/MachineCopyPropagation.cpp
index ff75b87b23128..6f1e6e46eef8b 100644
--- a/llvm/lib/CodeGen/MachineCopyPropagation.cpp
+++ b/llvm/lib/CodeGen/MachineCopyPropagation.cpp
@@ -867,6 +867,12 @@ void MachineCopyPropagation::forwardUses(MachineInstr &MI) {
make_range(Copy->getIterator(), std::next(MI.getIterator())))
KMI.clearRegisterKills(CopySrcReg, TRI);
+ // Attempt to canonicalize/optimize the instruction now its arguments have
+ // been mutated.
+ if (TII->optimizeInstruction(MI)) {
+ LLVM_DEBUG(dbgs() << "MCP: After optimizeInstruction: " << MI << "\n");
+ }
+
++NumCopyForwards;
Changed = true;
}
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index c4a2784263af0..3e2549d4b17bd 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -2344,6 +2344,21 @@ static unsigned getSHXADDShiftAmount(unsigned Opc) {
}
}
+// Returns the shift amount from a SHXADD.UW instruction. Returns 0 if the
+// instruction is not a SHXADD.UW.
+static unsigned getSHXADDUWShiftAmount(unsigned Opc) {
+ switch (Opc) {
+ default:
+ return 0;
+ case RISCV::SH1ADD_UW:
+ return 1;
+ case RISCV::SH2ADD_UW:
+ return 2;
+ case RISCV::SH3ADD_UW:
+ return 3;
+ }
+}
+
// Look for opportunities to combine (sh3add Z, (add X, (slli Y, 5))) into
// (sh3add (sh2add Y, Z), X).
static bool getSHXADDPatterns(const MachineInstr &Root,
@@ -3850,6 +3865,209 @@ MachineInstr *RISCVInstrInfo::commuteInstructionImpl(MachineInstr &MI,
return TargetInstrInfo::commuteInstructionImpl(MI, NewMI, OpIdx1, OpIdx2);
}
+bool RISCVInstrInfo::optimizeInstruction(MachineInstr &MI) const {
+ switch (MI.getOpcode()) {
+ default:
+ break;
+ case RISCV::OR:
+ case RISCV::XOR:
+ // Normalize:
+ // [x]or rd, zero, rs => [x]or rd, rs, zero
+ if (MI.getOperand(1).getReg() == RISCV::X0) {
+ MachineOperand MO1 = MI.getOperand(1);
+ MI.removeOperand(1);
+ MI.addOperand(MO1);
+ }
+ // [x]or rd, rs, zero => addi rd, rs, 0
+ if (MI.getOperand(2).getReg() == RISCV::X0) {
+ MI.getOperand(2).ChangeToImmediate(0);
+ MI.setDesc(get(RISCV::ADDI));
+ return true;
+ }
+ // xor rd, rs, rs => li rd, rs, 0
+ if (MI.getOpcode() == RISCV::XOR && MI.getOperand(1).getReg() == MI.getOperand(2).getReg()) {
+ MI.getOperand(2).ChangeToImmediate(0);
+ MI.setDesc(get(RISCV::ADDI));
+ return true;
+ }
+ break;
+ case RISCV::ADDW:
+ // Normalize:
+ // addw rd, zero, rs => addw rd, rs, zero
+ if (MI.getOperand(1).getReg() == RISCV::X0) {
+ MachineOperand MO1 = MI.getOperand(1);
+ MI.removeOperand(1);
+ MI.addOperand(MO1);
+ }
+ // addw rd, rs, zero => addiw rd, rs, 0
+ if (MI.getOperand(2).getReg() == RISCV::X0) {
+ MI.getOperand(2).ChangeToImmediate(0);
+ MI.setDesc(get(RISCV::ADDIW));
+ return true;
+ }
+ break;
+ case RISCV::SUB:
+ case RISCV::PACK:
+ case RISCV::PACKW:
+ // sub rd, rs, zero => addi rd, rs, 0
+ // pack[w] rd, rs, zero => addi rd, rs, zero
+ if (MI.getOperand(2).getReg() == RISCV::X0) {
+ MI.getOperand(2).ChangeToImmediate(0);
+ MI.setDesc(get(RISCV::ADDI));
+ return true;
+ }
+ break;
+ case RISCV::SUBW:
+ // subw rd, rs, zero => addiw rd, rs, 0
+ if (MI.getOperand(2).getReg() == RISCV::X0) {
+ MI.getOperand(2).ChangeToImmediate(0);
+ MI.setDesc(get(RISCV::ADDIW));
+ return true;
+ }
+ break;
+ case RISCV::SH1ADD:
+ case RISCV::SH1ADD_UW:
+ case RISCV::SH2ADD:
+ case RISCV::SH2ADD_UW:
+ case RISCV::SH3ADD:
+ case RISCV::SH3ADD_UW:
+ // shNadd[.uw] rd, zero, rs => addi rd, rs, 0
+ if (MI.getOperand(1).getReg() == RISCV::X0) {
+ MI.removeOperand(1);
+ MI.addOperand(MachineOperand::CreateImm(0));
+ MI.setDesc(get(RISCV::ADDI));
+ return true;
+ }
+ // shNadd[.uw] rd, rs, zero => slli[.uw] rd, rs, N
+ if (MI.getOperand(2).getReg() == RISCV::X0) {
+ MI.removeOperand(2);
+ unsigned Opc = MI.getOpcode();
+ if (Opc == RISCV::SH1ADD_UW || Opc == RISCV::SH2ADD_UW || Opc == RISCV::SH3ADD_UW) {
+ MI.addOperand(MachineOperand::CreateImm(getSHXADDUWShiftAmount(Opc)));
+ MI.setDesc(get(RISCV::SLLI_UW));
+ return true;
+ }
+ MI.addOperand(MachineOperand::CreateImm(getSHXADDShiftAmount(Opc)));
+ MI.setDesc(get(RISCV::SLLI));
+ return true;
+ }
+ break;
+ case RISCV::ANDI:
+ // andi rd, zero, C => li rd, 0
+ if (MI.getOperand(1).getReg() == RISCV::X0) {
+ MI.getOperand(2).setImm(0);
+ MI.setDesc(get(RISCV::ADDI));
+ return true;
+ }
+ break;
+ case RISCV::AND:
+ case RISCV::MUL:
+ case RISCV::MULH:
+ case RISCV::MULHSU:
+ case RISCV::MULHU:
+ case RISCV::MULW:
+ // and rd, rs, zero => li rd, 0
+ // and rd, zero, rs => li rd, 0
+ // mul* rd, rs, zero => li rd, 0
+ // mul* rd, zero, rs => li rd, 0
+ if (MI.getOperand(1).getReg() == RISCV::X0) {
+ MI.removeOperand(2);
+ MI.addOperand(MachineOperand::CreateImm(0));
+ MI.setDesc(get(RISCV::ADDI));
+ return true;
+ }
+ if (MI.getOperand(2).getReg() == RISCV::X0) {
+ MI.removeOperand(1);
+ MI.addOperand(MachineOperand::CreateImm(0));
+ MI.setDesc(get(RISCV::ADDI));
+ return true;
+ }
+ break;
+ case RISCV::SLLI:
+ case RISCV::SRLI:
+ case RISCV::SRAI:
+ case RISCV::SLLIW:
+ case RISCV::SRLIW:
+ case RISCV::SRAIW:
+ case RISCV::SLLI_UW:
+ // shiftimm rd, zero, N => li rd, 0
+ if (MI.getOperand(1).getReg() == RISCV::X0) {
+ MI.getOperand(2).setImm(0);
+ MI.setDesc(get(RISCV::ADDI));
+ return true;
+ }
+ break;
+ case RISCV::ORI:
+ case RISCV::XORI:
+ // [x]ori rd, zero, N => li rd, N
+ if (MI.getOperand(1).getReg() == RISCV::X0) {
+ MI.setDesc(get(RISCV::ADDI));
+ return true;
+ }
+ break;
+ case RISCV::SLTIU:
+ // seqz rd, zero => li rd, 1
+ if (MI.getOperand(1).getReg() == RISCV::X0 && MI.getOperand(2).getImm() == 1) {
+ MI.setDesc(get(RISCV::ADDI));
+ return true;
+ }
+ break;
+ case RISCV::SLTU:
+ case RISCV::ADD_UW:
+ // snez rd, zero => li rd, 0
+ // zext.w rd, zero => li rd, 0
+ if (MI.getOperand(1).getReg() == RISCV::X0 && MI.getOperand(2).getReg() == RISCV::X0) {
+ MI.getOperand(2).ChangeToImmediate(0);
+ MI.setDesc(get(RISCV::ADDI));
+ return true;
+ }
+ // add.uw rd, zero, rs => add.uw rd, rs, zero (canonical zext.w)
+ if (MI.getOpcode() == RISCV::ADD_UW && MI.getOperand(1).getReg() == RISCV::X0) {
+ MachineOperand MO1 = MI.getOperand(1);
+ MI.removeOperand(1);
+ MI.addOperand(MO1);
+ }
+ break;
+ case RISCV::SEXT_H:
+ case RISCV::SEXT_B:
+ case RISCV::ZEXT_H_RV32:
+ case RISCV::ZEXT_H_RV64:
+ // sext.[hb] rd, zero => li rd, 0
+ // zext.h rd, zero => li rd, 0
+ if (MI.getOperand(1).getReg() == RISCV::X0) {
+ MI.addOperand(MachineOperand::CreateImm(0));
+ MI.setDesc(get(RISCV::ADDI));
+ return true;
+ }
+ break;
+ case RISCV::SLL:
+ case RISCV::SRL:
+ case RISCV::SRA:
+ case RISCV::SLLW:
+ case RISCV::SRLW:
+ case RISCV::SRAW:
+ // shift rd, zero, rs => li rd, 0
+ if (MI.getOperand(1).getReg() == RISCV::X0) {
+ MI.getOperand(2).ChangeToImmediate(0);
+ MI.setDesc(get(RISCV::ADDI));
+ return true;
+ }
+ break;
+ case RISCV::MIN:
+ case RISCV::MINU:
+ case RISCV::MAX:
+ case RISCV::MAXU:
+ // min|max rd, rs, rs => addi rd, rs, 0
+ if (MI.getOperand(1).getReg() == MI.getOperand(2).getReg()) {
+ MI.getOperand(2).ChangeToImmediate(0);
+ MI.setDesc(get(RISCV::ADDI));
+ return true;
+ }
+ break;
+ }
+ return false;
+}
+
#undef CASE_RVV_OPCODE_UNMASK_LMUL
#undef CASE_RVV_OPCODE_MASK_LMUL
#undef CASE_RVV_OPCODE_LMUL
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.h b/llvm/lib/Target/RISCV/RISCVInstrInfo.h
index 67e457d64f6e3..ccca9b7120e02 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.h
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.h
@@ -242,6 +242,8 @@ class RISCVInstrInfo : public RISCVGenInstrInfo {
unsigned OpIdx1,
unsigned OpIdx2) const override;
+ bool optimizeInstruction(MachineInstr &MI) const override;
+
MachineInstr *convertToThreeAddress(MachineInstr &MI, LiveVariables *LV,
LiveIntervals *LIS) const override;
diff --git a/llvm/test/CodeGen/RISCV/machine-copyprop-optimizeinstr.mir b/llvm/test/CodeGen/RISCV/machine-copyprop-optimizeinstr.mir
new file mode 100644
index 0000000000000..ed4e7cb8df6b5
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/machine-copyprop-optimizeinstr.mir
@@ -0,0 +1,685 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
+# RUN: llc -o - %s -mtriple=riscv64 -run-pass=machine-cp -mcp-use-is-copy-instr | FileCheck %s
+
+---
+name: or1
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: or1
+ ; CHECK: renamable $x10 = ADDI $x12, 0
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ renamable $x11 = COPY $x12
+ renamable $x10 = OR renamable $x11, $x0
+ PseudoRET implicit $x10
+...
+---
+name: or2
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: or2
+ ; CHECK: renamable $x10 = ADDI $x12, 0
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ renamable $x11 = COPY $x12
+ renamable $x10 = OR $x0, renamable $x11
+ PseudoRET implicit $x10
+...
+---
+name: xor1
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: xor1
+ ; CHECK: renamable $x10 = ADDI $x12, 0
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ renamable $x11 = COPY $x12
+ renamable $x10 = XOR renamable $x11, $x0
+ PseudoRET implicit $x10
+...
+---
+name: xor2
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: xor2
+ ; CHECK: renamable $x10 = ADDI $x12, 0
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ renamable $x11 = COPY $x12
+ renamable $x10 = XOR $x0, renamable $x11
+ PseudoRET implicit $x10
+...
+---
+name: addw1
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: addw1
+ ; CHECK: renamable $x10 = ADDIW $x12, 0
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ renamable $x11 = COPY $x0
+ renamable $x10 = ADDW renamable $x11, $x12
+ PseudoRET implicit $x10
+...
+---
+name: addw2
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: addw2
+ ; CHECK: renamable $x10 = ADDIW $x12, 0
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ renamable $x11 = COPY $x0
+ renamable $x10 = ADDW $x12, renamable $x11
+ PseudoRET implicit $x10
+...
+---
+name: sub
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: sub
+ ; CHECK: renamable $x10 = ADDI $x12, 0
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ renamable $x11 = COPY $x12
+ renamable $x10 = SUB renamable $x11, $x0
+ PseudoRET implicit $x10
+...
+---
+name: pack
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: pack
+ ; CHECK: renamable $x10 = ADDI $x12, 0
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ renamable $x11 = COPY $x12
+ renamable $x10 = PACK renamable $x11, $x0
+ PseudoRET implicit $x10
+...
+---
+name: packw
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: packw
+ ; CHECK: renamable $x10 = ADDI $x12, 0
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ renamable $x11 = COPY $x12
+ renamable $x10 = PACKW renamable $x11, $x0
+ PseudoRET implicit $x10
+...
+---
+name: subw
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: subw
+ ; CHECK: renamable $x10 = ADDIW $x12, 0
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ renamable $x11 = COPY $x12
+ renamable $x10 = SUBW renamable $x11, $x0
+ PseudoRET implicit $x10
+...
+---
+name: sh1add1
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: sh1add1
+ ; CHECK: renamable $x10 = ADDI $x12, 0
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ renamable $x11 = COPY $x12
+ renamable $x10 = SH1ADD $x0, renamable $x11
+ PseudoRET implicit $x10
+...
+---
+name: sh1add2
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: sh1add2
+ ; CHECK: renamable $x10 = SLLI $x12, 1
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ renamable $x11 = COPY $x12
+ renamable $x10 = SH1ADD renamable $x11, $x0
+ PseudoRET implicit $x10
+...
+---
+name: sh1add.uw1
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: sh1add.uw1
+ ; CHECK: renamable $x10 = ADDI $x12, 0
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ renamable $x11 = COPY $x12
+ renamable $x10 = SH1ADD_UW $x0, renamable $x11
+ PseudoRET implicit $x10
+...
+---
+name: sh1add.uw2
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: sh1add.uw2
+ ; CHECK: renamable $x10 = SLLI_UW $x12, 1
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ renamable $x11 = COPY $x12
+ renamable $x10 = SH1ADD_UW renamable $x11, $x0
+ PseudoRET implicit $x10
+...
+---
+name: sh2add1
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: sh2add1
+ ; CHECK: renamable $x10 = ADDI $x12, 0
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ renamable $x11 = COPY $x12
+ renamable $x10 = SH2ADD $x0, renamable $x11
+ PseudoRET implicit $x10
+...
+---
+name: sh2add2
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: sh2add2
+ ; CHECK: renamable $x10 = SLLI $x12, 2
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ renamable $x11 = COPY $x12
+ renamable $x10 = SH2ADD renamable $x11, $x0
+ PseudoRET implicit $x10
+...
+---
+name: sh2add.uw1
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: sh2add.uw1
+ ; CHECK: renamable $x10 = ADDI $x12, 0
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ renamable $x11 = COPY $x12
+ renamable $x10 = SH2ADD_UW $x0, renamable $x11
+ PseudoRET implicit $x10
+...
+---
+name: sh2add.uw2
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: sh2add.uw2
+ ; CHECK: renamable $x10 = SLLI_UW $x12, 2
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ renamable $x11 = COPY $x12
+ renamable $x10 = SH2ADD_UW renamable $x11, $x0
+ PseudoRET implicit $x10
+...
+---
+name: sh3add1
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: sh3add1
+ ; CHECK: renamable $x10 = ADDI $x12, 0
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ renamable $x11 = COPY $x12
+ renamable $x10 = SH3ADD $x0, renamable $x11
+ PseudoRET implicit $x10
+...
+---
+name: sh3add2
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: sh3add2
+ ; CHECK: renamable $x10 = SLLI $x12, 3
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ renamable $x11 = COPY $x12
+ renamable $x10 = SH3ADD renamable $x11, $x0
+ PseudoRET implicit $x10
+...
+---
+name: sh3add.uw1
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: sh3add.uw1
+ ; CHECK: renamable $x10 = ADDI $x12, 0
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ renamable $x11 = COPY $x12
+ renamable $x10 = SH3ADD_UW $x0, renamable $x11
+ PseudoRET implicit $x10
+...
+---
+name: sh3add.uw2
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: sh3add.uw2
+ ; CHECK: renamable $x10 = SLLI_UW $x12, 3
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ renamable $x11 = COPY $x12
+ renamable $x10 = SH3ADD_UW renamable $x11, $x0
+ PseudoRET implicit $x10
+...
+---
+name: andi
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: andi
+ ; CHECK: renamable $x10 = ADDI $x0, 0
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ renamable $x11 = COPY $x0
+ renamable $x10 = ANDI renamable $x11, 13
+ PseudoRET implicit $x10
+...
+---
+name: and1
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: and1
+ ; CHECK: renamable $x10 = ADDI $x0, 0
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ renamable $x11 = COPY $x12
+ renamable $x10 = AND renamable $x11, $x0
+ PseudoRET implicit $x10
+...
+---
+name: and2
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: and2
+ ; CHECK: renamable $x10 = ADDI $x0, 0
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ renamable $x11 = COPY $x12
+ renamable $x10 = AND $x0, renamable $x11
+ PseudoRET implicit $x10
+...
+---
+name: mul1
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: mul1
+ ; CHECK: renamable $x10 = ADDI $x0, 0
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ renamable $x11 = COPY $x12
+ renamable $x10 = MUL renamable $x11, $x0
+ PseudoRET implicit $x10
+...
+---
+name: mul2
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: mul2
+ ; CHECK: renamable $x10 = ADDI $x0, 0
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ renamable $x11 = COPY $x12
+ renamable $x10 = MUL $x0, renamable $x11
+ PseudoRET implicit $x10
+...
+---
+name: mulh1
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: mulh1
+ ; CHECK: renamable $x10 = ADDI $x0, 0
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ renamable $x11 = COPY $x12
+ renamable $x10 = MULH renamable $x11, $x0
+ PseudoRET implicit $x10
+...
+---
+name: mulh2
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: mulh2
+ ; CHECK: renamable $x10 = ADDI $x0, 0
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ renamable $x11 = COPY $x12
+ renamable $x10 = MULH $x0, renamable $x11
+ PseudoRET implicit $x10
+...
+---
+name: mulhsu1
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: mulhsu1
+ ; CHECK: renamable $x10 = ADDI $x0, 0
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ renamable $x11 = COPY $x12
+ renamable $x10 = MULHSU renamable $x11, $x0
+ PseudoRET implicit $x10
+...
+---
+name: mulhsu2
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: mulhsu2
+ ; CHECK: renamable $x10 = ADDI $x0, 0
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ renamable $x11 = COPY $x12
+ renamable $x10 = MULHSU $x0, renamable $x11
+ PseudoRET implicit $x10
+...
+---
+name: mulhu1
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: mulhu1
+ ; CHECK: renamable $x10 = ADDI $x0, 0
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ renamable $x11 = COPY $x12
+ renamable $x10 = MULHU renamable $x11, $x0
+ PseudoRET implicit $x10
+...
+---
+name: mulhu2
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: mulhu2
+ ; CHECK: renamable $x10 = ADDI $x0, 0
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ renamable $x11 = COPY $x12
+ renamable $x10 = MULHU $x0, renamable $x11
+ PseudoRET implicit $x10
+...
+---
+name: mulw1
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: mulw1
+ ; CHECK: renamable $x10 = ADDI $x0, 0
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ renamable $x11 = COPY $x12
+ renamable $x10 = MULW renamable $x11, $x0
+ PseudoRET implicit $x10
+...
+---
+name: mulw2
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: mulw2
+ ; CHECK: renamable $x10 = ADDI $x0, 0
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ renamable $x11 = COPY $x12
+ renamable $x10 = MULW $x0, renamable $x11
+ PseudoRET implicit $x10
+...
+---
+name: slli
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: slli
+ ; CHECK: renamable $x10 = ADDI $x0, 0
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ renamable $x11 = COPY $x0
+ renamable $x10 = SLLI renamable $x11, 13
+ PseudoRET implicit $x10
+...
+---
+name: srli
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: srli
+ ; CHECK: renamable $x10 = ADDI $x0, 0
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ renamable $x11 = COPY $x0
+ renamable $x10 = SRLI renamable $x11, 13
+ PseudoRET implicit $x10
+...
+---
+name: srai
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: srai
+ ; CHECK: renamable $x10 = A...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/137973
More information about the llvm-commits
mailing list