[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