[llvm-branch-commits] [llvm] release/22.x: [LoongArch] Fix incorrect indexing of incoming byval arguments in tail call eligibility check (#188006) (PR #188666)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Wed Mar 25 19:49:40 PDT 2026


https://github.com/heiher created https://github.com/llvm/llvm-project/pull/188666

Backport only the LoongArch part of ab17b5408ac83a03807b6f0ea22f51dfb84b0b8a, skip the RISC-V part due to unresolvable conflicts.

Requested by: @heiher

>From 692e4b087bf47ac670c272fd781be1c1e5ce3c98 Mon Sep 17 00:00:00 2001
From: hev <wangrui at loongson.cn>
Date: Wed, 25 Mar 2026 23:26:08 +0800
Subject: [PATCH] [LoongArch] Fix incorrect indexing of incoming byval
 arguments in tail call eligibility check (#188006)

The loop that validates byval arguments in
`isEligibleForTailCallOptimization()` incorrectly used the loop index
`i` when accessing `getIncomingByValArgs()`, even though `j` is the
index tracking the number of encountered byval arguments.

This mismatch could lead to out-of-bounds access or incorrect type
comparisons when non-byval arguments are interleaved with byval
arguments, causing the tail call eligibility check to fail or behave
incorrectly.

Fix this by using `j` consistently as the index into the incoming byval
argument list and only incrementing it after the bounds check.

Fixes #187832

(cherry picked from commit ab17b5408ac83a03807b6f0ea22f51dfb84b0b8a)
---
 .../LoongArch/LoongArchISelLowering.cpp       |  7 +--
 llvm/test/CodeGen/LoongArch/issue187832.ll    | 48 +++++++++++++++++++
 2 files changed, 52 insertions(+), 3 deletions(-)
 create mode 100644 llvm/test/CodeGen/LoongArch/issue187832.ll

diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index 755e2afa2bf04..8b0754599f13d 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -8358,13 +8358,14 @@ bool LoongArchTargetLowering::isEligibleForTailCallOptimization(
     return false;
 
   // Do not tail call opt if caller's and callee's byval arguments do not match.
-  for (unsigned i = 0, j = 0; i < Outs.size(); i++) {
+  for (unsigned i = 0, j = 0; i < Outs.size(); ++i) {
     if (!Outs[i].Flags.isByVal())
       continue;
-    if (j++ >= LoongArchFI->getIncomingByValArgsSize())
+    if (j >= LoongArchFI->getIncomingByValArgsSize())
       return false;
-    if (LoongArchFI->getIncomingByValArgs(i).getValueType() != Outs[i].ArgVT)
+    if (LoongArchFI->getIncomingByValArgs(j).getValueType() != Outs[i].ArgVT)
       return false;
+    ++j;
   }
 
   // The callee has to preserve all registers the caller needs to preserve.
diff --git a/llvm/test/CodeGen/LoongArch/issue187832.ll b/llvm/test/CodeGen/LoongArch/issue187832.ll
new file mode 100644
index 0000000000000..b483a7640e171
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/issue187832.ll
@@ -0,0 +1,48 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc -mtriple=loongarch32 %s -o - | FileCheck %s --check-prefix=LA32
+; RUN: llc -mtriple=loongarch64 %s -o - | FileCheck %s --check-prefix=LA64
+
+%Box = type { i32, i32, i32, i8, [3 x i8], i32, i8, [1 x i8], i16, i16, i8, [5 x i8], { i64, ptr }, { i64, ptr }, { i64, ptr } }
+
+define void @test(ptr byval(%Box) %0) nounwind {
+; LA32-LABEL: test:
+; LA32:       # %bb.0:
+; LA32-NEXT:    addi.w $sp, $sp, -112
+; LA32-NEXT:    st.w $ra, $sp, 108 # 4-byte Folded Spill
+; LA32-NEXT:    st.w $fp, $sp, 104 # 4-byte Folded Spill
+; LA32-NEXT:    addi.w $fp, $sp, 24
+; LA32-NEXT:    ori $a2, $zero, 80
+; LA32-NEXT:    move $a0, $fp
+; LA32-NEXT:    move $a1, $zero
+; LA32-NEXT:    bl memcpy
+; LA32-NEXT:    st.w $zero, $sp, 8
+; LA32-NEXT:    st.w $zero, $sp, 4
+; LA32-NEXT:    st.w $zero, $sp, 0
+; LA32-NEXT:    move $a0, $zero
+; LA32-NEXT:    move $a1, $zero
+; LA32-NEXT:    move $a2, $zero
+; LA32-NEXT:    move $a3, $fp
+; LA32-NEXT:    move $a4, $zero
+; LA32-NEXT:    move $a5, $zero
+; LA32-NEXT:    move $a6, $zero
+; LA32-NEXT:    move $a7, $zero
+; LA32-NEXT:    jirl $ra, $zero, 0
+; LA32-NEXT:    ld.w $fp, $sp, 104 # 4-byte Folded Reload
+; LA32-NEXT:    ld.w $ra, $sp, 108 # 4-byte Folded Reload
+; LA32-NEXT:    addi.w $sp, $sp, 112
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: test:
+; LA64:       # %bb.0:
+; LA64-NEXT:    movgr2fr.d $fa0, $zero
+; LA64-NEXT:    move $a0, $zero
+; LA64-NEXT:    move $a1, $zero
+; LA64-NEXT:    move $a2, $zero
+; LA64-NEXT:    move $a3, $zero
+; LA64-NEXT:    move $a4, $zero
+; LA64-NEXT:    move $a5, $zero
+; LA64-NEXT:    move $a6, $zero
+; LA64-NEXT:    jr $a0
+  tail call void null(ptr null, double 0.000000e+00, ptr byval(%Box) null, { i64, ptr } zeroinitializer, i32 0, i64 0, i1 false)
+  ret void
+}



More information about the llvm-branch-commits mailing list