diff --git a/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp b/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp
--- a/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp
@@ -37,9 +37,14 @@
     break;
   case ISD::Constant: {
     int64_t Imm = cast<ConstantSDNode>(Node)->getSExtValue();
+    if (Imm == 0 && Node->getSimpleValueType(0) == GRLenVT) {
+      SDValue New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL,
+                                           LoongArch::R0, GRLenVT);
+      ReplaceNode(Node, New.getNode());
+      return;
+    }
     SDNode *Result = nullptr;
     SDValue SrcReg = CurDAG->getRegister(LoongArch::R0, GRLenVT);
-
     // The instructions in the sequence are handled here.
     for (LoongArchMatInt::Inst &Inst : LoongArchMatInt::generateInstSeq(Imm)) {
       SDValue SDImm = CurDAG->getTargetConstant(Inst.Imm, DL, GRLenVT);
diff --git a/llvm/test/CodeGen/LoongArch/imm.ll b/llvm/test/CodeGen/LoongArch/imm.ll
--- a/llvm/test/CodeGen/LoongArch/imm.ll
+++ b/llvm/test/CodeGen/LoongArch/imm.ll
@@ -1,5 +1,13 @@
 ; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s
 
+define i64 @imm0() {
+; CHECK-LABEL: imm0:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    move $a0, $zero
+; CHECK-NEXT:    jirl $zero, $ra, 0
+  ret i64 0
+}
+
 define i64 @imm7ff0000000000000() {
 ; CHECK-LABEL: imm7ff0000000000000:
 ; CHECK:       # %bb.0: