[llvm] [RISCV][GlobalISel] Legalize readcyclecounter/readsteadycounter (PR #217535)

Kane Wang via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 20 02:16:40 PDT 2026


================
@@ -889,6 +895,38 @@ bool RISCVLegalizerInfo::legalizeVAStart(MachineInstr &MI,
   return true;
 }
 
+bool RISCVLegalizerInfo::legalizeReadCounter(
+    MachineInstr &MI, MachineIRBuilder &MIRBuilder) const {
+  assert((MI.getOpcode() == TargetOpcode::G_READCYCLECOUNTER ||
+          MI.getOpcode() == TargetOpcode::G_READSTEADYCOUNTER) &&
+         "Unexpected opcode");
+  assert(!STI.is64Bit() && "READCYCLECOUNTER/READSTEADYCOUNTER only "
+                           "has custom type legalization on riscv32");
+
+  // On RV32 a 64-bit counter CSR must be read as two 32-bit halves. Lower to
+  // the ReadCounterWide target pseudo.
+  bool IsCycle = MI.getOpcode() == TargetOpcode::G_READCYCLECOUNTER;
+  int64_t LoCounter = IsCycle ? RISCVSysReg::cycle : RISCVSysReg::time;
+  int64_t HiCounter = IsCycle ? RISCVSysReg::cycleh : RISCVSysReg::timeh;
+
+  MachineRegisterInfo &MRI = *MIRBuilder.getMRI();
+  auto CreateGPR = [&]() {
+    Register R = MRI.createGenericVirtualRegister(LLT::scalar(32));
+    MRI.setRegClass(R, &RISCV::GPRRegClass);
+    return R;
+  };
+  Register LoReg = CreateGPR();
+  Register HiReg = CreateGPR();
+
+  Register DstReg = MI.getOperand(0).getReg();
+  MIRBuilder.setDebugLoc(MI.getDebugLoc());
+  MIRBuilder.buildInstr(RISCV::ReadCounterWide, {LoReg, HiReg},
----------------
ReVe1uv wrote:

> It seems this pseudo only exists due to the inability to introduce control flow in SelectionDAG. This case could directly emit the loop

Done. The legalizer now directly emits the csrrs/bne loop instead of lowering to the ReadCounterWide pseudo.

https://github.com/llvm/llvm-project/pull/217535


More information about the llvm-commits mailing list