[llvm] [LoongArch] Add custom lowering for CTTZ_ELTS and CTTZ_ELTS_ZERO_POISON (PR #226042)

via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 24 00:12:25 PDT 2026


https://github.com/lrzlin created https://github.com/llvm/llvm-project/pull/226042

Use `[X]VMSKLTZ` and `CTZ` for custom lowering `ISD::CTTZ_ELTS` and `ISD::CTTZ_ELTS_ZERO_POISON`, when the number of lanes is larger than or equal to `GRLen`, switch back to the generic way; these two intrinsics could possibly be used in early-exit loop vectorization.

>From 8bfce73b1ccd1186f606ac237eab9ebd22056851 Mon Sep 17 00:00:00 2001
From: Lin Runze <linrunze at loongson.cn>
Date: Thu, 24 Sep 2026 14:51:04 +0800
Subject: [PATCH 1/2] [LoongArch][NFC] Add tests for CTTZ_ELTS and
 CTTZ_ELTS_ZERO_POISON

---
 llvm/test/CodeGen/LoongArch/lasx/cttz-elts.ll | 275 ++++++++++++++++++
 llvm/test/CodeGen/LoongArch/lsx/cttz-elts.ll  | 239 +++++++++++++++
 2 files changed, 514 insertions(+)
 create mode 100644 llvm/test/CodeGen/LoongArch/lasx/cttz-elts.ll
 create mode 100644 llvm/test/CodeGen/LoongArch/lsx/cttz-elts.ll

diff --git a/llvm/test/CodeGen/LoongArch/lasx/cttz-elts.ll b/llvm/test/CodeGen/LoongArch/lasx/cttz-elts.ll
new file mode 100644
index 00000000000000..8d251c3138b42a
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/lasx/cttz-elts.ll
@@ -0,0 +1,275 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc --mtriple=loongarch32 --mattr=+32s,+lasx --verify-machineinstrs < %s | FileCheck %s --check-prefixes=CHECK,LA32
+; RUN: llc --mtriple=loongarch64 --mattr=+lasx --verify-machineinstrs < %s | FileCheck %s --check-prefixes=CHECK,LA64
+
+declare i64 @llvm.experimental.cttz.elts.i64.v4i1(<4 x i1>, i1)
+declare i64 @llvm.experimental.cttz.elts.i64.v8i1(<8 x i1>, i1)
+declare i64 @llvm.experimental.cttz.elts.i64.v16i1(<16 x i1>, i1)
+declare i64 @llvm.experimental.cttz.elts.i64.v32i1(<32 x i1>, i1)
+
+define void @first_set_lane_v4i64(ptr %src, ptr %dst) {
+; LA32-LABEL: first_set_lane_v4i64:
+; LA32:       # %bb.0:
+; LA32-NEXT:    xvld $xr0, $a0, 0
+; LA32-NEXT:    xvld $xr1, $a1, 0
+; LA32-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI0_0)
+; LA32-NEXT:    vld $vr2, $a0, %pc_lo12(.LCPI0_0)
+; LA32-NEXT:    xvseq.d $xr0, $xr0, $xr1
+; LA32-NEXT:    xvpickev.w $xr0, $xr0, $xr0
+; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT:    vand.v $vr0, $vr0, $vr2
+; LA32-NEXT:    vbsrl.v $vr1, $vr0, 8
+; LA32-NEXT:    vmax.wu $vr0, $vr1, $vr0
+; LA32-NEXT:    vbsrl.v $vr1, $vr0, 4
+; LA32-NEXT:    vmax.wu $vr0, $vr1, $vr0
+; LA32-NEXT:    vpickve2gr.w $a0, $vr0, 0
+; LA32-NEXT:    ori $a2, $zero, 4
+; LA32-NEXT:    sub.w $a0, $a2, $a0
+; LA32-NEXT:    st.w $zero, $a1, 4
+; LA32-NEXT:    st.w $a0, $a1, 0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: first_set_lane_v4i64:
+; LA64:       # %bb.0:
+; LA64-NEXT:    xvld $xr0, $a0, 0
+; LA64-NEXT:    xvld $xr1, $a1, 0
+; LA64-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI0_0)
+; LA64-NEXT:    vld $vr2, $a0, %pc_lo12(.LCPI0_0)
+; LA64-NEXT:    xvseq.d $xr0, $xr0, $xr1
+; LA64-NEXT:    xvpickev.w $xr0, $xr0, $xr0
+; LA64-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA64-NEXT:    vand.v $vr0, $vr0, $vr2
+; LA64-NEXT:    vbsrl.v $vr1, $vr0, 8
+; LA64-NEXT:    vmax.wu $vr0, $vr1, $vr0
+; LA64-NEXT:    vbsrl.v $vr1, $vr0, 4
+; LA64-NEXT:    vmax.wu $vr0, $vr1, $vr0
+; LA64-NEXT:    vpickve2gr.wu $a0, $vr0, 0
+; LA64-NEXT:    ori $a2, $zero, 4
+; LA64-NEXT:    sub.d $a0, $a2, $a0
+; LA64-NEXT:    st.d $a0, $a1, 0
+; LA64-NEXT:    ret
+  %a = load <4 x i64>, ptr %src
+  %b = load <4 x i64>, ptr %dst
+  %cmp = icmp eq <4 x i64> %a, %b
+  %r = call i64 @llvm.experimental.cttz.elts.i64.v4i1(<4 x i1> %cmp, i1 false)
+  store i64 %r, ptr %dst
+  ret void
+}
+
+define void @first_set_lane_v4i64_poison(ptr %src, ptr %dst) {
+; LA32-LABEL: first_set_lane_v4i64_poison:
+; LA32:       # %bb.0:
+; LA32-NEXT:    xvld $xr0, $a0, 0
+; LA32-NEXT:    xvld $xr1, $a1, 0
+; LA32-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI1_0)
+; LA32-NEXT:    vld $vr2, $a0, %pc_lo12(.LCPI1_0)
+; LA32-NEXT:    xvseq.d $xr0, $xr0, $xr1
+; LA32-NEXT:    xvpickev.w $xr0, $xr0, $xr0
+; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT:    vand.v $vr0, $vr0, $vr2
+; LA32-NEXT:    vbsrl.v $vr1, $vr0, 8
+; LA32-NEXT:    vmax.wu $vr0, $vr1, $vr0
+; LA32-NEXT:    vbsrl.v $vr1, $vr0, 4
+; LA32-NEXT:    vmax.wu $vr0, $vr1, $vr0
+; LA32-NEXT:    vpickve2gr.w $a0, $vr0, 0
+; LA32-NEXT:    ori $a2, $zero, 4
+; LA32-NEXT:    sub.w $a0, $a2, $a0
+; LA32-NEXT:    st.w $zero, $a1, 4
+; LA32-NEXT:    st.w $a0, $a1, 0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: first_set_lane_v4i64_poison:
+; LA64:       # %bb.0:
+; LA64-NEXT:    xvld $xr0, $a0, 0
+; LA64-NEXT:    xvld $xr1, $a1, 0
+; LA64-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI1_0)
+; LA64-NEXT:    vld $vr2, $a0, %pc_lo12(.LCPI1_0)
+; LA64-NEXT:    xvseq.d $xr0, $xr0, $xr1
+; LA64-NEXT:    xvpickev.w $xr0, $xr0, $xr0
+; LA64-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA64-NEXT:    vand.v $vr0, $vr0, $vr2
+; LA64-NEXT:    vbsrl.v $vr1, $vr0, 8
+; LA64-NEXT:    vmax.wu $vr0, $vr1, $vr0
+; LA64-NEXT:    vbsrl.v $vr1, $vr0, 4
+; LA64-NEXT:    vmax.wu $vr0, $vr1, $vr0
+; LA64-NEXT:    vpickve2gr.wu $a0, $vr0, 0
+; LA64-NEXT:    ori $a2, $zero, 4
+; LA64-NEXT:    sub.d $a0, $a2, $a0
+; LA64-NEXT:    st.d $a0, $a1, 0
+; LA64-NEXT:    ret
+  %a = load <4 x i64>, ptr %src
+  %b = load <4 x i64>, ptr %dst
+  %cmp = icmp eq <4 x i64> %a, %b
+  %r = call i64 @llvm.experimental.cttz.elts.i64.v4i1(<4 x i1> %cmp, i1 true)
+  store i64 %r, ptr %dst
+  ret void
+}
+
+define void @first_set_lane_v8i32(ptr %src, ptr %dst) {
+; LA32-LABEL: first_set_lane_v8i32:
+; LA32:       # %bb.0:
+; LA32-NEXT:    xvld $xr0, $a0, 0
+; LA32-NEXT:    xvld $xr1, $a1, 0
+; LA32-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI2_0)
+; LA32-NEXT:    vld $vr2, $a0, %pc_lo12(.LCPI2_0)
+; LA32-NEXT:    xvseq.w $xr0, $xr0, $xr1
+; LA32-NEXT:    xvpickev.h $xr0, $xr0, $xr0
+; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT:    vand.v $vr0, $vr0, $vr2
+; LA32-NEXT:    vbsrl.v $vr1, $vr0, 8
+; LA32-NEXT:    vmax.hu $vr0, $vr1, $vr0
+; LA32-NEXT:    vbsrl.v $vr1, $vr0, 4
+; LA32-NEXT:    vmax.hu $vr0, $vr1, $vr0
+; LA32-NEXT:    vbsrl.v $vr1, $vr0, 2
+; LA32-NEXT:    vmax.hu $vr0, $vr1, $vr0
+; LA32-NEXT:    vpickve2gr.hu $a0, $vr0, 0
+; LA32-NEXT:    ori $a2, $zero, 8
+; LA32-NEXT:    sub.w $a0, $a2, $a0
+; LA32-NEXT:    st.w $zero, $a1, 4
+; LA32-NEXT:    st.w $a0, $a1, 0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: first_set_lane_v8i32:
+; LA64:       # %bb.0:
+; LA64-NEXT:    xvld $xr0, $a0, 0
+; LA64-NEXT:    xvld $xr1, $a1, 0
+; LA64-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI2_0)
+; LA64-NEXT:    vld $vr2, $a0, %pc_lo12(.LCPI2_0)
+; LA64-NEXT:    xvseq.w $xr0, $xr0, $xr1
+; LA64-NEXT:    xvpickev.h $xr0, $xr0, $xr0
+; LA64-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA64-NEXT:    vand.v $vr0, $vr0, $vr2
+; LA64-NEXT:    vbsrl.v $vr1, $vr0, 8
+; LA64-NEXT:    vmax.hu $vr0, $vr1, $vr0
+; LA64-NEXT:    vbsrl.v $vr1, $vr0, 4
+; LA64-NEXT:    vmax.hu $vr0, $vr1, $vr0
+; LA64-NEXT:    vbsrl.v $vr1, $vr0, 2
+; LA64-NEXT:    vmax.hu $vr0, $vr1, $vr0
+; LA64-NEXT:    vpickve2gr.hu $a0, $vr0, 0
+; LA64-NEXT:    ori $a2, $zero, 8
+; LA64-NEXT:    sub.d $a0, $a2, $a0
+; LA64-NEXT:    st.d $a0, $a1, 0
+; LA64-NEXT:    ret
+  %a = load <8 x i32>, ptr %src
+  %b = load <8 x i32>, ptr %dst
+  %cmp = icmp eq <8 x i32> %a, %b
+  %r = call i64 @llvm.experimental.cttz.elts.i64.v8i1(<8 x i1> %cmp, i1 false)
+  store i64 %r, ptr %dst
+  ret void
+}
+
+define void @first_set_lane_v16i16(ptr %src, ptr %dst) {
+; LA32-LABEL: first_set_lane_v16i16:
+; LA32:       # %bb.0:
+; LA32-NEXT:    xvld $xr0, $a0, 0
+; LA32-NEXT:    xvld $xr1, $a1, 0
+; LA32-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI3_0)
+; LA32-NEXT:    vld $vr2, $a0, %pc_lo12(.LCPI3_0)
+; LA32-NEXT:    xvseq.h $xr0, $xr0, $xr1
+; LA32-NEXT:    xvpickev.b $xr0, $xr0, $xr0
+; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT:    vand.v $vr0, $vr0, $vr2
+; LA32-NEXT:    vbsrl.v $vr1, $vr0, 8
+; LA32-NEXT:    vmax.bu $vr0, $vr1, $vr0
+; LA32-NEXT:    vbsrl.v $vr1, $vr0, 4
+; LA32-NEXT:    vmax.bu $vr0, $vr1, $vr0
+; LA32-NEXT:    vbsrl.v $vr1, $vr0, 2
+; LA32-NEXT:    vmax.bu $vr0, $vr1, $vr0
+; LA32-NEXT:    vbsrl.v $vr1, $vr0, 1
+; LA32-NEXT:    vmax.bu $vr0, $vr1, $vr0
+; LA32-NEXT:    vpickve2gr.bu $a0, $vr0, 0
+; LA32-NEXT:    ori $a2, $zero, 16
+; LA32-NEXT:    sub.w $a0, $a2, $a0
+; LA32-NEXT:    st.w $zero, $a1, 4
+; LA32-NEXT:    st.w $a0, $a1, 0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: first_set_lane_v16i16:
+; LA64:       # %bb.0:
+; LA64-NEXT:    xvld $xr0, $a0, 0
+; LA64-NEXT:    xvld $xr1, $a1, 0
+; LA64-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI3_0)
+; LA64-NEXT:    vld $vr2, $a0, %pc_lo12(.LCPI3_0)
+; LA64-NEXT:    xvseq.h $xr0, $xr0, $xr1
+; LA64-NEXT:    xvpickev.b $xr0, $xr0, $xr0
+; LA64-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA64-NEXT:    vand.v $vr0, $vr0, $vr2
+; LA64-NEXT:    vbsrl.v $vr1, $vr0, 8
+; LA64-NEXT:    vmax.bu $vr0, $vr1, $vr0
+; LA64-NEXT:    vbsrl.v $vr1, $vr0, 4
+; LA64-NEXT:    vmax.bu $vr0, $vr1, $vr0
+; LA64-NEXT:    vbsrl.v $vr1, $vr0, 2
+; LA64-NEXT:    vmax.bu $vr0, $vr1, $vr0
+; LA64-NEXT:    vbsrl.v $vr1, $vr0, 1
+; LA64-NEXT:    vmax.bu $vr0, $vr1, $vr0
+; LA64-NEXT:    vpickve2gr.bu $a0, $vr0, 0
+; LA64-NEXT:    ori $a2, $zero, 16
+; LA64-NEXT:    sub.d $a0, $a2, $a0
+; LA64-NEXT:    st.d $a0, $a1, 0
+; LA64-NEXT:    ret
+  %a = load <16 x i16>, ptr %src
+  %b = load <16 x i16>, ptr %dst
+  %cmp = icmp eq <16 x i16> %a, %b
+  %r = call i64 @llvm.experimental.cttz.elts.i64.v16i1(<16 x i1> %cmp, i1 false)
+  store i64 %r, ptr %dst
+  ret void
+}
+
+define void @first_set_lane_v32i8(ptr %src, ptr %dst) {
+; LA32-LABEL: first_set_lane_v32i8:
+; LA32:       # %bb.0:
+; LA32-NEXT:    xvld $xr0, $a0, 0
+; LA32-NEXT:    xvld $xr1, $a1, 0
+; LA32-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI4_0)
+; LA32-NEXT:    xvld $xr2, $a0, %pc_lo12(.LCPI4_0)
+; LA32-NEXT:    xvseq.b $xr0, $xr0, $xr1
+; LA32-NEXT:    xvand.v $xr0, $xr0, $xr2
+; LA32-NEXT:    xvpermi.q $xr1, $xr0, 1
+; LA32-NEXT:    vmax.bu $vr0, $vr0, $vr1
+; LA32-NEXT:    vbsrl.v $vr1, $vr0, 8
+; LA32-NEXT:    vmax.bu $vr0, $vr1, $vr0
+; LA32-NEXT:    vbsrl.v $vr1, $vr0, 4
+; LA32-NEXT:    vmax.bu $vr0, $vr1, $vr0
+; LA32-NEXT:    vbsrl.v $vr1, $vr0, 2
+; LA32-NEXT:    vmax.bu $vr0, $vr1, $vr0
+; LA32-NEXT:    vbsrl.v $vr1, $vr0, 1
+; LA32-NEXT:    vmax.bu $vr0, $vr1, $vr0
+; LA32-NEXT:    vpickve2gr.bu $a0, $vr0, 0
+; LA32-NEXT:    ori $a2, $zero, 32
+; LA32-NEXT:    sub.w $a0, $a2, $a0
+; LA32-NEXT:    st.w $zero, $a1, 4
+; LA32-NEXT:    st.w $a0, $a1, 0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: first_set_lane_v32i8:
+; LA64:       # %bb.0:
+; LA64-NEXT:    xvld $xr0, $a0, 0
+; LA64-NEXT:    xvld $xr1, $a1, 0
+; LA64-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI4_0)
+; LA64-NEXT:    xvld $xr2, $a0, %pc_lo12(.LCPI4_0)
+; LA64-NEXT:    xvseq.b $xr0, $xr0, $xr1
+; LA64-NEXT:    xvand.v $xr0, $xr0, $xr2
+; LA64-NEXT:    xvpermi.q $xr1, $xr0, 1
+; LA64-NEXT:    vmax.bu $vr0, $vr0, $vr1
+; LA64-NEXT:    vbsrl.v $vr1, $vr0, 8
+; LA64-NEXT:    vmax.bu $vr0, $vr1, $vr0
+; LA64-NEXT:    vbsrl.v $vr1, $vr0, 4
+; LA64-NEXT:    vmax.bu $vr0, $vr1, $vr0
+; LA64-NEXT:    vbsrl.v $vr1, $vr0, 2
+; LA64-NEXT:    vmax.bu $vr0, $vr1, $vr0
+; LA64-NEXT:    vbsrl.v $vr1, $vr0, 1
+; LA64-NEXT:    vmax.bu $vr0, $vr1, $vr0
+; LA64-NEXT:    vpickve2gr.bu $a0, $vr0, 0
+; LA64-NEXT:    ori $a2, $zero, 32
+; LA64-NEXT:    sub.d $a0, $a2, $a0
+; LA64-NEXT:    st.d $a0, $a1, 0
+; LA64-NEXT:    ret
+  %a = load <32 x i8>, ptr %src
+  %b = load <32 x i8>, ptr %dst
+  %cmp = icmp eq <32 x i8> %a, %b
+  %r = call i64 @llvm.experimental.cttz.elts.i64.v32i1(<32 x i1> %cmp, i1 false)
+  store i64 %r, ptr %dst
+  ret void
+}
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; CHECK: {{.*}}
diff --git a/llvm/test/CodeGen/LoongArch/lsx/cttz-elts.ll b/llvm/test/CodeGen/LoongArch/lsx/cttz-elts.ll
new file mode 100644
index 00000000000000..182a5e4def318d
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/lsx/cttz-elts.ll
@@ -0,0 +1,239 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc --mtriple=loongarch32 --mattr=+32s,+lsx --verify-machineinstrs < %s | FileCheck %s --check-prefixes=CHECK,LA32
+; RUN: llc --mtriple=loongarch64 --mattr=+lsx --verify-machineinstrs < %s | FileCheck %s --check-prefixes=CHECK,LA64
+
+declare i64 @llvm.experimental.cttz.elts.i64.v2i1(<2 x i1>, i1)
+declare i64 @llvm.experimental.cttz.elts.i64.v4i1(<4 x i1>, i1)
+declare i64 @llvm.experimental.cttz.elts.i64.v8i1(<8 x i1>, i1)
+declare i64 @llvm.experimental.cttz.elts.i64.v16i1(<16 x i1>, i1)
+
+define void @first_set_lane_v2i64(ptr %src, ptr %dst) {
+; LA32-LABEL: first_set_lane_v2i64:
+; LA32:       # %bb.0:
+; LA32-NEXT:    vld $vr0, $a0, 0
+; LA32-NEXT:    vld $vr1, $a1, 0
+; LA32-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI0_0)
+; LA32-NEXT:    vld $vr2, $a0, %pc_lo12(.LCPI0_0)
+; LA32-NEXT:    vseq.d $vr0, $vr0, $vr1
+; LA32-NEXT:    vand.v $vr0, $vr0, $vr2
+; LA32-NEXT:    vbsrl.v $vr1, $vr0, 8
+; LA32-NEXT:    vmax.du $vr0, $vr1, $vr0
+; LA32-NEXT:    vpickve2gr.w $a0, $vr0, 0
+; LA32-NEXT:    ori $a2, $zero, 2
+; LA32-NEXT:    sub.w $a0, $a2, $a0
+; LA32-NEXT:    st.w $zero, $a1, 4
+; LA32-NEXT:    st.w $a0, $a1, 0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: first_set_lane_v2i64:
+; LA64:       # %bb.0:
+; LA64-NEXT:    vld $vr0, $a0, 0
+; LA64-NEXT:    vld $vr1, $a1, 0
+; LA64-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI0_0)
+; LA64-NEXT:    vld $vr2, $a0, %pc_lo12(.LCPI0_0)
+; LA64-NEXT:    vseq.d $vr0, $vr0, $vr1
+; LA64-NEXT:    vand.v $vr0, $vr0, $vr2
+; LA64-NEXT:    vbsrl.v $vr1, $vr0, 8
+; LA64-NEXT:    vmax.du $vr0, $vr1, $vr0
+; LA64-NEXT:    vpickve2gr.d $a0, $vr0, 0
+; LA64-NEXT:    ori $a2, $zero, 2
+; LA64-NEXT:    sub.d $a0, $a2, $a0
+; LA64-NEXT:    st.d $a0, $a1, 0
+; LA64-NEXT:    ret
+  %a = load <2 x i64>, ptr %src
+  %b = load <2 x i64>, ptr %dst
+  %cmp = icmp eq <2 x i64> %a, %b
+  %r = call i64 @llvm.experimental.cttz.elts.i64.v2i1(<2 x i1> %cmp, i1 false)
+  store i64 %r, ptr %dst
+  ret void
+}
+
+define void @first_set_lane_v2i64_poison(ptr %src, ptr %dst) {
+; LA32-LABEL: first_set_lane_v2i64_poison:
+; LA32:       # %bb.0:
+; LA32-NEXT:    vld $vr0, $a0, 0
+; LA32-NEXT:    vld $vr1, $a1, 0
+; LA32-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI1_0)
+; LA32-NEXT:    vld $vr2, $a0, %pc_lo12(.LCPI1_0)
+; LA32-NEXT:    vseq.d $vr0, $vr0, $vr1
+; LA32-NEXT:    vand.v $vr0, $vr0, $vr2
+; LA32-NEXT:    vbsrl.v $vr1, $vr0, 8
+; LA32-NEXT:    vmax.du $vr0, $vr1, $vr0
+; LA32-NEXT:    vpickve2gr.w $a0, $vr0, 0
+; LA32-NEXT:    ori $a2, $zero, 2
+; LA32-NEXT:    sub.w $a0, $a2, $a0
+; LA32-NEXT:    st.w $zero, $a1, 4
+; LA32-NEXT:    st.w $a0, $a1, 0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: first_set_lane_v2i64_poison:
+; LA64:       # %bb.0:
+; LA64-NEXT:    vld $vr0, $a0, 0
+; LA64-NEXT:    vld $vr1, $a1, 0
+; LA64-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI1_0)
+; LA64-NEXT:    vld $vr2, $a0, %pc_lo12(.LCPI1_0)
+; LA64-NEXT:    vseq.d $vr0, $vr0, $vr1
+; LA64-NEXT:    vand.v $vr0, $vr0, $vr2
+; LA64-NEXT:    vbsrl.v $vr1, $vr0, 8
+; LA64-NEXT:    vmax.du $vr0, $vr1, $vr0
+; LA64-NEXT:    vpickve2gr.d $a0, $vr0, 0
+; LA64-NEXT:    ori $a2, $zero, 2
+; LA64-NEXT:    sub.d $a0, $a2, $a0
+; LA64-NEXT:    st.d $a0, $a1, 0
+; LA64-NEXT:    ret
+  %a = load <2 x i64>, ptr %src
+  %b = load <2 x i64>, ptr %dst
+  %cmp = icmp eq <2 x i64> %a, %b
+  %r = call i64 @llvm.experimental.cttz.elts.i64.v2i1(<2 x i1> %cmp, i1 true)
+  store i64 %r, ptr %dst
+  ret void
+}
+
+define void @first_set_lane_v4i32(ptr %src, ptr %dst) {
+; LA32-LABEL: first_set_lane_v4i32:
+; LA32:       # %bb.0:
+; LA32-NEXT:    vld $vr0, $a0, 0
+; LA32-NEXT:    vld $vr1, $a1, 0
+; LA32-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI2_0)
+; LA32-NEXT:    vld $vr2, $a0, %pc_lo12(.LCPI2_0)
+; LA32-NEXT:    vseq.w $vr0, $vr0, $vr1
+; LA32-NEXT:    vand.v $vr0, $vr0, $vr2
+; LA32-NEXT:    vbsrl.v $vr1, $vr0, 8
+; LA32-NEXT:    vmax.wu $vr0, $vr1, $vr0
+; LA32-NEXT:    vbsrl.v $vr1, $vr0, 4
+; LA32-NEXT:    vmax.wu $vr0, $vr1, $vr0
+; LA32-NEXT:    vpickve2gr.w $a0, $vr0, 0
+; LA32-NEXT:    ori $a2, $zero, 4
+; LA32-NEXT:    sub.w $a0, $a2, $a0
+; LA32-NEXT:    st.w $zero, $a1, 4
+; LA32-NEXT:    st.w $a0, $a1, 0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: first_set_lane_v4i32:
+; LA64:       # %bb.0:
+; LA64-NEXT:    vld $vr0, $a0, 0
+; LA64-NEXT:    vld $vr1, $a1, 0
+; LA64-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI2_0)
+; LA64-NEXT:    vld $vr2, $a0, %pc_lo12(.LCPI2_0)
+; LA64-NEXT:    vseq.w $vr0, $vr0, $vr1
+; LA64-NEXT:    vand.v $vr0, $vr0, $vr2
+; LA64-NEXT:    vbsrl.v $vr1, $vr0, 8
+; LA64-NEXT:    vmax.wu $vr0, $vr1, $vr0
+; LA64-NEXT:    vbsrl.v $vr1, $vr0, 4
+; LA64-NEXT:    vmax.wu $vr0, $vr1, $vr0
+; LA64-NEXT:    vpickve2gr.wu $a0, $vr0, 0
+; LA64-NEXT:    ori $a2, $zero, 4
+; LA64-NEXT:    sub.d $a0, $a2, $a0
+; LA64-NEXT:    st.d $a0, $a1, 0
+; LA64-NEXT:    ret
+  %a = load <4 x i32>, ptr %src
+  %b = load <4 x i32>, ptr %dst
+  %cmp = icmp eq <4 x i32> %a, %b
+  %r = call i64 @llvm.experimental.cttz.elts.i64.v4i1(<4 x i1> %cmp, i1 false)
+  store i64 %r, ptr %dst
+  ret void
+}
+
+define void @first_set_lane_v8i16(ptr %src, ptr %dst) {
+; LA32-LABEL: first_set_lane_v8i16:
+; LA32:       # %bb.0:
+; LA32-NEXT:    vld $vr0, $a0, 0
+; LA32-NEXT:    vld $vr1, $a1, 0
+; LA32-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI3_0)
+; LA32-NEXT:    vld $vr2, $a0, %pc_lo12(.LCPI3_0)
+; LA32-NEXT:    vseq.h $vr0, $vr0, $vr1
+; LA32-NEXT:    vand.v $vr0, $vr0, $vr2
+; LA32-NEXT:    vbsrl.v $vr1, $vr0, 8
+; LA32-NEXT:    vmax.hu $vr0, $vr1, $vr0
+; LA32-NEXT:    vbsrl.v $vr1, $vr0, 4
+; LA32-NEXT:    vmax.hu $vr0, $vr1, $vr0
+; LA32-NEXT:    vbsrl.v $vr1, $vr0, 2
+; LA32-NEXT:    vmax.hu $vr0, $vr1, $vr0
+; LA32-NEXT:    vpickve2gr.hu $a0, $vr0, 0
+; LA32-NEXT:    ori $a2, $zero, 8
+; LA32-NEXT:    sub.w $a0, $a2, $a0
+; LA32-NEXT:    st.w $zero, $a1, 4
+; LA32-NEXT:    st.w $a0, $a1, 0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: first_set_lane_v8i16:
+; LA64:       # %bb.0:
+; LA64-NEXT:    vld $vr0, $a0, 0
+; LA64-NEXT:    vld $vr1, $a1, 0
+; LA64-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI3_0)
+; LA64-NEXT:    vld $vr2, $a0, %pc_lo12(.LCPI3_0)
+; LA64-NEXT:    vseq.h $vr0, $vr0, $vr1
+; LA64-NEXT:    vand.v $vr0, $vr0, $vr2
+; LA64-NEXT:    vbsrl.v $vr1, $vr0, 8
+; LA64-NEXT:    vmax.hu $vr0, $vr1, $vr0
+; LA64-NEXT:    vbsrl.v $vr1, $vr0, 4
+; LA64-NEXT:    vmax.hu $vr0, $vr1, $vr0
+; LA64-NEXT:    vbsrl.v $vr1, $vr0, 2
+; LA64-NEXT:    vmax.hu $vr0, $vr1, $vr0
+; LA64-NEXT:    vpickve2gr.hu $a0, $vr0, 0
+; LA64-NEXT:    ori $a2, $zero, 8
+; LA64-NEXT:    sub.d $a0, $a2, $a0
+; LA64-NEXT:    st.d $a0, $a1, 0
+; LA64-NEXT:    ret
+  %a = load <8 x i16>, ptr %src
+  %b = load <8 x i16>, ptr %dst
+  %cmp = icmp eq <8 x i16> %a, %b
+  %r = call i64 @llvm.experimental.cttz.elts.i64.v8i1(<8 x i1> %cmp, i1 false)
+  store i64 %r, ptr %dst
+  ret void
+}
+
+define void @first_set_lane_v16i8(ptr %src, ptr %dst) {
+; LA32-LABEL: first_set_lane_v16i8:
+; LA32:       # %bb.0:
+; LA32-NEXT:    vld $vr0, $a0, 0
+; LA32-NEXT:    vld $vr1, $a1, 0
+; LA32-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI4_0)
+; LA32-NEXT:    vld $vr2, $a0, %pc_lo12(.LCPI4_0)
+; LA32-NEXT:    vseq.b $vr0, $vr0, $vr1
+; LA32-NEXT:    vand.v $vr0, $vr0, $vr2
+; LA32-NEXT:    vbsrl.v $vr1, $vr0, 8
+; LA32-NEXT:    vmax.bu $vr0, $vr1, $vr0
+; LA32-NEXT:    vbsrl.v $vr1, $vr0, 4
+; LA32-NEXT:    vmax.bu $vr0, $vr1, $vr0
+; LA32-NEXT:    vbsrl.v $vr1, $vr0, 2
+; LA32-NEXT:    vmax.bu $vr0, $vr1, $vr0
+; LA32-NEXT:    vbsrl.v $vr1, $vr0, 1
+; LA32-NEXT:    vmax.bu $vr0, $vr1, $vr0
+; LA32-NEXT:    vpickve2gr.bu $a0, $vr0, 0
+; LA32-NEXT:    ori $a2, $zero, 16
+; LA32-NEXT:    sub.w $a0, $a2, $a0
+; LA32-NEXT:    st.w $zero, $a1, 4
+; LA32-NEXT:    st.w $a0, $a1, 0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: first_set_lane_v16i8:
+; LA64:       # %bb.0:
+; LA64-NEXT:    vld $vr0, $a0, 0
+; LA64-NEXT:    vld $vr1, $a1, 0
+; LA64-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI4_0)
+; LA64-NEXT:    vld $vr2, $a0, %pc_lo12(.LCPI4_0)
+; LA64-NEXT:    vseq.b $vr0, $vr0, $vr1
+; LA64-NEXT:    vand.v $vr0, $vr0, $vr2
+; LA64-NEXT:    vbsrl.v $vr1, $vr0, 8
+; LA64-NEXT:    vmax.bu $vr0, $vr1, $vr0
+; LA64-NEXT:    vbsrl.v $vr1, $vr0, 4
+; LA64-NEXT:    vmax.bu $vr0, $vr1, $vr0
+; LA64-NEXT:    vbsrl.v $vr1, $vr0, 2
+; LA64-NEXT:    vmax.bu $vr0, $vr1, $vr0
+; LA64-NEXT:    vbsrl.v $vr1, $vr0, 1
+; LA64-NEXT:    vmax.bu $vr0, $vr1, $vr0
+; LA64-NEXT:    vpickve2gr.bu $a0, $vr0, 0
+; LA64-NEXT:    ori $a2, $zero, 16
+; LA64-NEXT:    sub.d $a0, $a2, $a0
+; LA64-NEXT:    st.d $a0, $a1, 0
+; LA64-NEXT:    ret
+  %a = load <16 x i8>, ptr %src
+  %b = load <16 x i8>, ptr %dst
+  %cmp = icmp eq <16 x i8> %a, %b
+  %r = call i64 @llvm.experimental.cttz.elts.i64.v16i1(<16 x i1> %cmp, i1 false)
+  store i64 %r, ptr %dst
+  ret void
+}
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; CHECK: {{.*}}

>From bf5eb6c12524af3f688215fafdbc3440ede68e02 Mon Sep 17 00:00:00 2001
From: Lin Runze <linrunze at loongson.cn>
Date: Thu, 24 Sep 2026 14:54:01 +0800
Subject: [PATCH 2/2] [LoongArch] Add custom lowering for CTTZ_ELTS and
 CTTZ_ELTS_ZERO_POISON

---
 .../LoongArch/LoongArchISelLowering.cpp       |  41 +++++
 .../Target/LoongArch/LoongArchISelLowering.h  |   1 +
 llvm/test/CodeGen/LoongArch/lasx/cttz-elts.ll | 144 +++++-------------
 llvm/test/CodeGen/LoongArch/lsx/cttz-elts.ll  | 140 +++++------------
 4 files changed, 118 insertions(+), 208 deletions(-)

diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index 07f6a438bbb1bc..249fe798a60558 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -328,6 +328,8 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
       setOperationAction(ISD::VSELECT, VT, Legal);
       setOperationAction(ISD::VECTOR_SHUFFLE, VT, Custom);
       setOperationAction(ISD::EXTRACT_SUBVECTOR, VT, Legal);
+      setOperationAction({ISD::CTTZ_ELTS, ISD::CTTZ_ELTS_ZERO_POISON}, VT,
+                         Custom);
     }
     for (MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64}) {
       setOperationAction({ISD::ADD, ISD::SUB}, VT, Legal);
@@ -430,6 +432,8 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
       setOperationAction(ISD::SETCC, VT, Custom);
       setOperationAction(ISD::VSELECT, VT, Legal);
       setOperationAction(ISD::VECTOR_SHUFFLE, VT, Custom);
+      setOperationAction({ISD::CTTZ_ELTS, ISD::CTTZ_ELTS_ZERO_POISON}, VT,
+                         Custom);
     }
     for (MVT VT : {MVT::v4i64, MVT::v8i32, MVT::v16i16, MVT::v32i8}) {
       setOperationAction({ISD::ADD, ISD::SUB}, VT, Legal);
@@ -670,6 +674,9 @@ SDValue LoongArchTargetLowering::LowerOperation(SDValue Op,
   case ISD::ROTL:
   case ISD::ROTR:
     return lowerRotate(Op, DAG);
+  case ISD::CTTZ_ELTS:
+  case ISD::CTTZ_ELTS_ZERO_POISON:
+    return lowerCTTZ_ELTS(Op, DAG);
   case ISD::VECREDUCE_AND:
   case ISD::VECREDUCE_OR:
   case ISD::VECREDUCE_XOR:
@@ -10986,6 +10993,40 @@ bool LoongArchTargetLowering::shouldInsertFencesForAtomic(
   return false;
 }
 
+SDValue LoongArchTargetLowering::lowerCTTZ_ELTS(SDValue Op,
+                                                SelectionDAG &DAG) const {
+  SDLoc DL(Op);
+  MVT GRLenVT = Subtarget.getGRLenVT();
+  SDValue Src = Op.getOperand(0);
+  EVT SrcVT = Src.getValueType();
+  unsigned NumElts = SrcVT.getVectorNumElements();
+  unsigned SrcBits = SrcVT.getSizeInBits();
+
+  // Only masks occupying exactly one LSX or LASX register are handled; anything
+  // else is left to the generic expansion.
+  if (SrcBits != 128 && SrcBits != 256)
+    return SDValue();
+
+  // [X]VMSKLTZ collect each lane's sign bit into lowest bits of a VPR, copy
+  // them into GPR and count trailing zeros.
+  SDValue Bits = DAG.getNode(SrcBits == 256 ? LoongArchISD::XVMSKLTZ
+                                            : LoongArchISD::VMSKLTZ,
+                             DL, GRLenVT, Src);
+
+  // CTTZ_ELTS must produce the vector length when no lane is set.
+  if (Op.getOpcode() == ISD::CTTZ_ELTS) {
+    // When GRLen is 32, it's possible that NumElts is 32 too.
+    if (NumElts >= GRLenVT.getSizeInBits())
+      return SDValue();
+    Bits = DAG.getNode(ISD::OR, DL, GRLenVT, Bits,
+                       DAG.getConstant(1ULL << NumElts, DL, GRLenVT));
+  }
+
+  return DAG.getZExtOrTrunc(
+      DAG.getNode(ISD::CTTZ_ZERO_POISON, DL, GRLenVT, Bits), DL,
+      Op.getValueType());
+}
+
 EVT LoongArchTargetLowering::getSetCCResultType(const DataLayout &DL,
                                                 LLVMContext &Context,
                                                 EVT VT) const {
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
index 7c3ae7d6aac14a..8371efff305e43 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
@@ -255,6 +255,7 @@ class LoongArchTargetLowering : public TargetLowering {
   SDValue lowerFP16_TO_FP(SDValue Op, SelectionDAG &DAG) const;
   SDValue lowerFP_TO_BF16(SDValue Op, SelectionDAG &DAG) const;
   SDValue lowerBF16_TO_FP(SDValue Op, SelectionDAG &DAG) const;
+  SDValue lowerCTTZ_ELTS(SDValue Op, SelectionDAG &DAG) const;
   SDValue lowerVECREDUCE_ADD(SDValue Op, SelectionDAG &DAG) const;
   SDValue lowerVECREDUCE(SDValue Op, SelectionDAG &DAG) const;
   SDValue lowerConstantFP(SDValue Op, SelectionDAG &DAG) const;
diff --git a/llvm/test/CodeGen/LoongArch/lasx/cttz-elts.ll b/llvm/test/CodeGen/LoongArch/lasx/cttz-elts.ll
index 8d251c3138b42a..988786df71c089 100644
--- a/llvm/test/CodeGen/LoongArch/lasx/cttz-elts.ll
+++ b/llvm/test/CodeGen/LoongArch/lasx/cttz-elts.ll
@@ -12,19 +12,13 @@ define void @first_set_lane_v4i64(ptr %src, ptr %dst) {
 ; LA32:       # %bb.0:
 ; LA32-NEXT:    xvld $xr0, $a0, 0
 ; LA32-NEXT:    xvld $xr1, $a1, 0
-; LA32-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI0_0)
-; LA32-NEXT:    vld $vr2, $a0, %pc_lo12(.LCPI0_0)
 ; LA32-NEXT:    xvseq.d $xr0, $xr0, $xr1
 ; LA32-NEXT:    xvpickev.w $xr0, $xr0, $xr0
 ; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
-; LA32-NEXT:    vand.v $vr0, $vr0, $vr2
-; LA32-NEXT:    vbsrl.v $vr1, $vr0, 8
-; LA32-NEXT:    vmax.wu $vr0, $vr1, $vr0
-; LA32-NEXT:    vbsrl.v $vr1, $vr0, 4
-; LA32-NEXT:    vmax.wu $vr0, $vr1, $vr0
-; LA32-NEXT:    vpickve2gr.w $a0, $vr0, 0
-; LA32-NEXT:    ori $a2, $zero, 4
-; LA32-NEXT:    sub.w $a0, $a2, $a0
+; LA32-NEXT:    vmskltz.w $vr0, $vr0
+; LA32-NEXT:    vpickve2gr.hu $a0, $vr0, 0
+; LA32-NEXT:    ori $a0, $a0, 16
+; LA32-NEXT:    ctz.w $a0, $a0
 ; LA32-NEXT:    st.w $zero, $a1, 4
 ; LA32-NEXT:    st.w $a0, $a1, 0
 ; LA32-NEXT:    ret
@@ -33,19 +27,13 @@ define void @first_set_lane_v4i64(ptr %src, ptr %dst) {
 ; LA64:       # %bb.0:
 ; LA64-NEXT:    xvld $xr0, $a0, 0
 ; LA64-NEXT:    xvld $xr1, $a1, 0
-; LA64-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI0_0)
-; LA64-NEXT:    vld $vr2, $a0, %pc_lo12(.LCPI0_0)
 ; LA64-NEXT:    xvseq.d $xr0, $xr0, $xr1
 ; LA64-NEXT:    xvpickev.w $xr0, $xr0, $xr0
 ; LA64-NEXT:    xvpermi.d $xr0, $xr0, 216
-; LA64-NEXT:    vand.v $vr0, $vr0, $vr2
-; LA64-NEXT:    vbsrl.v $vr1, $vr0, 8
-; LA64-NEXT:    vmax.wu $vr0, $vr1, $vr0
-; LA64-NEXT:    vbsrl.v $vr1, $vr0, 4
-; LA64-NEXT:    vmax.wu $vr0, $vr1, $vr0
-; LA64-NEXT:    vpickve2gr.wu $a0, $vr0, 0
-; LA64-NEXT:    ori $a2, $zero, 4
-; LA64-NEXT:    sub.d $a0, $a2, $a0
+; LA64-NEXT:    vmskltz.w $vr0, $vr0
+; LA64-NEXT:    vpickve2gr.hu $a0, $vr0, 0
+; LA64-NEXT:    ori $a0, $a0, 16
+; LA64-NEXT:    ctz.d $a0, $a0
 ; LA64-NEXT:    st.d $a0, $a1, 0
 ; LA64-NEXT:    ret
   %a = load <4 x i64>, ptr %src
@@ -61,19 +49,12 @@ define void @first_set_lane_v4i64_poison(ptr %src, ptr %dst) {
 ; LA32:       # %bb.0:
 ; LA32-NEXT:    xvld $xr0, $a0, 0
 ; LA32-NEXT:    xvld $xr1, $a1, 0
-; LA32-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI1_0)
-; LA32-NEXT:    vld $vr2, $a0, %pc_lo12(.LCPI1_0)
 ; LA32-NEXT:    xvseq.d $xr0, $xr0, $xr1
 ; LA32-NEXT:    xvpickev.w $xr0, $xr0, $xr0
 ; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
-; LA32-NEXT:    vand.v $vr0, $vr0, $vr2
-; LA32-NEXT:    vbsrl.v $vr1, $vr0, 8
-; LA32-NEXT:    vmax.wu $vr0, $vr1, $vr0
-; LA32-NEXT:    vbsrl.v $vr1, $vr0, 4
-; LA32-NEXT:    vmax.wu $vr0, $vr1, $vr0
-; LA32-NEXT:    vpickve2gr.w $a0, $vr0, 0
-; LA32-NEXT:    ori $a2, $zero, 4
-; LA32-NEXT:    sub.w $a0, $a2, $a0
+; LA32-NEXT:    vmskltz.w $vr0, $vr0
+; LA32-NEXT:    vpickve2gr.hu $a0, $vr0, 0
+; LA32-NEXT:    ctz.w $a0, $a0
 ; LA32-NEXT:    st.w $zero, $a1, 4
 ; LA32-NEXT:    st.w $a0, $a1, 0
 ; LA32-NEXT:    ret
@@ -82,19 +63,12 @@ define void @first_set_lane_v4i64_poison(ptr %src, ptr %dst) {
 ; LA64:       # %bb.0:
 ; LA64-NEXT:    xvld $xr0, $a0, 0
 ; LA64-NEXT:    xvld $xr1, $a1, 0
-; LA64-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI1_0)
-; LA64-NEXT:    vld $vr2, $a0, %pc_lo12(.LCPI1_0)
 ; LA64-NEXT:    xvseq.d $xr0, $xr0, $xr1
 ; LA64-NEXT:    xvpickev.w $xr0, $xr0, $xr0
 ; LA64-NEXT:    xvpermi.d $xr0, $xr0, 216
-; LA64-NEXT:    vand.v $vr0, $vr0, $vr2
-; LA64-NEXT:    vbsrl.v $vr1, $vr0, 8
-; LA64-NEXT:    vmax.wu $vr0, $vr1, $vr0
-; LA64-NEXT:    vbsrl.v $vr1, $vr0, 4
-; LA64-NEXT:    vmax.wu $vr0, $vr1, $vr0
-; LA64-NEXT:    vpickve2gr.wu $a0, $vr0, 0
-; LA64-NEXT:    ori $a2, $zero, 4
-; LA64-NEXT:    sub.d $a0, $a2, $a0
+; LA64-NEXT:    vmskltz.w $vr0, $vr0
+; LA64-NEXT:    vpickve2gr.hu $a0, $vr0, 0
+; LA64-NEXT:    ctz.d $a0, $a0
 ; LA64-NEXT:    st.d $a0, $a1, 0
 ; LA64-NEXT:    ret
   %a = load <4 x i64>, ptr %src
@@ -110,21 +84,13 @@ define void @first_set_lane_v8i32(ptr %src, ptr %dst) {
 ; LA32:       # %bb.0:
 ; LA32-NEXT:    xvld $xr0, $a0, 0
 ; LA32-NEXT:    xvld $xr1, $a1, 0
-; LA32-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI2_0)
-; LA32-NEXT:    vld $vr2, $a0, %pc_lo12(.LCPI2_0)
 ; LA32-NEXT:    xvseq.w $xr0, $xr0, $xr1
 ; LA32-NEXT:    xvpickev.h $xr0, $xr0, $xr0
 ; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
-; LA32-NEXT:    vand.v $vr0, $vr0, $vr2
-; LA32-NEXT:    vbsrl.v $vr1, $vr0, 8
-; LA32-NEXT:    vmax.hu $vr0, $vr1, $vr0
-; LA32-NEXT:    vbsrl.v $vr1, $vr0, 4
-; LA32-NEXT:    vmax.hu $vr0, $vr1, $vr0
-; LA32-NEXT:    vbsrl.v $vr1, $vr0, 2
-; LA32-NEXT:    vmax.hu $vr0, $vr1, $vr0
+; LA32-NEXT:    vmskltz.h $vr0, $vr0
 ; LA32-NEXT:    vpickve2gr.hu $a0, $vr0, 0
-; LA32-NEXT:    ori $a2, $zero, 8
-; LA32-NEXT:    sub.w $a0, $a2, $a0
+; LA32-NEXT:    ori $a0, $a0, 256
+; LA32-NEXT:    ctz.w $a0, $a0
 ; LA32-NEXT:    st.w $zero, $a1, 4
 ; LA32-NEXT:    st.w $a0, $a1, 0
 ; LA32-NEXT:    ret
@@ -133,21 +99,13 @@ define void @first_set_lane_v8i32(ptr %src, ptr %dst) {
 ; LA64:       # %bb.0:
 ; LA64-NEXT:    xvld $xr0, $a0, 0
 ; LA64-NEXT:    xvld $xr1, $a1, 0
-; LA64-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI2_0)
-; LA64-NEXT:    vld $vr2, $a0, %pc_lo12(.LCPI2_0)
 ; LA64-NEXT:    xvseq.w $xr0, $xr0, $xr1
 ; LA64-NEXT:    xvpickev.h $xr0, $xr0, $xr0
 ; LA64-NEXT:    xvpermi.d $xr0, $xr0, 216
-; LA64-NEXT:    vand.v $vr0, $vr0, $vr2
-; LA64-NEXT:    vbsrl.v $vr1, $vr0, 8
-; LA64-NEXT:    vmax.hu $vr0, $vr1, $vr0
-; LA64-NEXT:    vbsrl.v $vr1, $vr0, 4
-; LA64-NEXT:    vmax.hu $vr0, $vr1, $vr0
-; LA64-NEXT:    vbsrl.v $vr1, $vr0, 2
-; LA64-NEXT:    vmax.hu $vr0, $vr1, $vr0
+; LA64-NEXT:    vmskltz.h $vr0, $vr0
 ; LA64-NEXT:    vpickve2gr.hu $a0, $vr0, 0
-; LA64-NEXT:    ori $a2, $zero, 8
-; LA64-NEXT:    sub.d $a0, $a2, $a0
+; LA64-NEXT:    ori $a0, $a0, 256
+; LA64-NEXT:    ctz.d $a0, $a0
 ; LA64-NEXT:    st.d $a0, $a1, 0
 ; LA64-NEXT:    ret
   %a = load <8 x i32>, ptr %src
@@ -163,23 +121,14 @@ define void @first_set_lane_v16i16(ptr %src, ptr %dst) {
 ; LA32:       # %bb.0:
 ; LA32-NEXT:    xvld $xr0, $a0, 0
 ; LA32-NEXT:    xvld $xr1, $a1, 0
-; LA32-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI3_0)
-; LA32-NEXT:    vld $vr2, $a0, %pc_lo12(.LCPI3_0)
 ; LA32-NEXT:    xvseq.h $xr0, $xr0, $xr1
 ; LA32-NEXT:    xvpickev.b $xr0, $xr0, $xr0
 ; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
-; LA32-NEXT:    vand.v $vr0, $vr0, $vr2
-; LA32-NEXT:    vbsrl.v $vr1, $vr0, 8
-; LA32-NEXT:    vmax.bu $vr0, $vr1, $vr0
-; LA32-NEXT:    vbsrl.v $vr1, $vr0, 4
-; LA32-NEXT:    vmax.bu $vr0, $vr1, $vr0
-; LA32-NEXT:    vbsrl.v $vr1, $vr0, 2
-; LA32-NEXT:    vmax.bu $vr0, $vr1, $vr0
-; LA32-NEXT:    vbsrl.v $vr1, $vr0, 1
-; LA32-NEXT:    vmax.bu $vr0, $vr1, $vr0
-; LA32-NEXT:    vpickve2gr.bu $a0, $vr0, 0
-; LA32-NEXT:    ori $a2, $zero, 16
-; LA32-NEXT:    sub.w $a0, $a2, $a0
+; LA32-NEXT:    vmskltz.b $vr0, $vr0
+; LA32-NEXT:    vpickve2gr.hu $a0, $vr0, 0
+; LA32-NEXT:    lu12i.w $a2, 16
+; LA32-NEXT:    or $a0, $a0, $a2
+; LA32-NEXT:    ctz.w $a0, $a0
 ; LA32-NEXT:    st.w $zero, $a1, 4
 ; LA32-NEXT:    st.w $a0, $a1, 0
 ; LA32-NEXT:    ret
@@ -188,23 +137,14 @@ define void @first_set_lane_v16i16(ptr %src, ptr %dst) {
 ; LA64:       # %bb.0:
 ; LA64-NEXT:    xvld $xr0, $a0, 0
 ; LA64-NEXT:    xvld $xr1, $a1, 0
-; LA64-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI3_0)
-; LA64-NEXT:    vld $vr2, $a0, %pc_lo12(.LCPI3_0)
 ; LA64-NEXT:    xvseq.h $xr0, $xr0, $xr1
 ; LA64-NEXT:    xvpickev.b $xr0, $xr0, $xr0
 ; LA64-NEXT:    xvpermi.d $xr0, $xr0, 216
-; LA64-NEXT:    vand.v $vr0, $vr0, $vr2
-; LA64-NEXT:    vbsrl.v $vr1, $vr0, 8
-; LA64-NEXT:    vmax.bu $vr0, $vr1, $vr0
-; LA64-NEXT:    vbsrl.v $vr1, $vr0, 4
-; LA64-NEXT:    vmax.bu $vr0, $vr1, $vr0
-; LA64-NEXT:    vbsrl.v $vr1, $vr0, 2
-; LA64-NEXT:    vmax.bu $vr0, $vr1, $vr0
-; LA64-NEXT:    vbsrl.v $vr1, $vr0, 1
-; LA64-NEXT:    vmax.bu $vr0, $vr1, $vr0
-; LA64-NEXT:    vpickve2gr.bu $a0, $vr0, 0
-; LA64-NEXT:    ori $a2, $zero, 16
-; LA64-NEXT:    sub.d $a0, $a2, $a0
+; LA64-NEXT:    vmskltz.b $vr0, $vr0
+; LA64-NEXT:    vpickve2gr.hu $a0, $vr0, 0
+; LA64-NEXT:    lu12i.w $a2, 16
+; LA64-NEXT:    or $a0, $a0, $a2
+; LA64-NEXT:    ctz.d $a0, $a0
 ; LA64-NEXT:    st.d $a0, $a1, 0
 ; LA64-NEXT:    ret
   %a = load <16 x i16>, ptr %src
@@ -245,23 +185,15 @@ define void @first_set_lane_v32i8(ptr %src, ptr %dst) {
 ; LA64:       # %bb.0:
 ; LA64-NEXT:    xvld $xr0, $a0, 0
 ; LA64-NEXT:    xvld $xr1, $a1, 0
-; LA64-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI4_0)
-; LA64-NEXT:    xvld $xr2, $a0, %pc_lo12(.LCPI4_0)
 ; LA64-NEXT:    xvseq.b $xr0, $xr0, $xr1
-; LA64-NEXT:    xvand.v $xr0, $xr0, $xr2
-; LA64-NEXT:    xvpermi.q $xr1, $xr0, 1
-; LA64-NEXT:    vmax.bu $vr0, $vr0, $vr1
-; LA64-NEXT:    vbsrl.v $vr1, $vr0, 8
-; LA64-NEXT:    vmax.bu $vr0, $vr1, $vr0
-; LA64-NEXT:    vbsrl.v $vr1, $vr0, 4
-; LA64-NEXT:    vmax.bu $vr0, $vr1, $vr0
-; LA64-NEXT:    vbsrl.v $vr1, $vr0, 2
-; LA64-NEXT:    vmax.bu $vr0, $vr1, $vr0
-; LA64-NEXT:    vbsrl.v $vr1, $vr0, 1
-; LA64-NEXT:    vmax.bu $vr0, $vr1, $vr0
-; LA64-NEXT:    vpickve2gr.bu $a0, $vr0, 0
-; LA64-NEXT:    ori $a2, $zero, 32
-; LA64-NEXT:    sub.d $a0, $a2, $a0
+; LA64-NEXT:    xvmskltz.b $xr0, $xr0
+; LA64-NEXT:    xvpickve2gr.wu $a0, $xr0, 0
+; LA64-NEXT:    xvpickve2gr.wu $a2, $xr0, 4
+; LA64-NEXT:    bstrins.d $a0, $a2, 31, 16
+; LA64-NEXT:    ori $a2, $zero, 0
+; LA64-NEXT:    lu32i.d $a2, 1
+; LA64-NEXT:    or $a0, $a0, $a2
+; LA64-NEXT:    ctz.d $a0, $a0
 ; LA64-NEXT:    st.d $a0, $a1, 0
 ; LA64-NEXT:    ret
   %a = load <32 x i8>, ptr %src
diff --git a/llvm/test/CodeGen/LoongArch/lsx/cttz-elts.ll b/llvm/test/CodeGen/LoongArch/lsx/cttz-elts.ll
index 182a5e4def318d..b7a5e151e57657 100644
--- a/llvm/test/CodeGen/LoongArch/lsx/cttz-elts.ll
+++ b/llvm/test/CodeGen/LoongArch/lsx/cttz-elts.ll
@@ -12,15 +12,11 @@ define void @first_set_lane_v2i64(ptr %src, ptr %dst) {
 ; LA32:       # %bb.0:
 ; LA32-NEXT:    vld $vr0, $a0, 0
 ; LA32-NEXT:    vld $vr1, $a1, 0
-; LA32-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI0_0)
-; LA32-NEXT:    vld $vr2, $a0, %pc_lo12(.LCPI0_0)
 ; LA32-NEXT:    vseq.d $vr0, $vr0, $vr1
-; LA32-NEXT:    vand.v $vr0, $vr0, $vr2
-; LA32-NEXT:    vbsrl.v $vr1, $vr0, 8
-; LA32-NEXT:    vmax.du $vr0, $vr1, $vr0
-; LA32-NEXT:    vpickve2gr.w $a0, $vr0, 0
-; LA32-NEXT:    ori $a2, $zero, 2
-; LA32-NEXT:    sub.w $a0, $a2, $a0
+; LA32-NEXT:    vmskltz.d $vr0, $vr0
+; LA32-NEXT:    vpickve2gr.hu $a0, $vr0, 0
+; LA32-NEXT:    ori $a0, $a0, 4
+; LA32-NEXT:    ctz.w $a0, $a0
 ; LA32-NEXT:    st.w $zero, $a1, 4
 ; LA32-NEXT:    st.w $a0, $a1, 0
 ; LA32-NEXT:    ret
@@ -29,15 +25,11 @@ define void @first_set_lane_v2i64(ptr %src, ptr %dst) {
 ; LA64:       # %bb.0:
 ; LA64-NEXT:    vld $vr0, $a0, 0
 ; LA64-NEXT:    vld $vr1, $a1, 0
-; LA64-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI0_0)
-; LA64-NEXT:    vld $vr2, $a0, %pc_lo12(.LCPI0_0)
 ; LA64-NEXT:    vseq.d $vr0, $vr0, $vr1
-; LA64-NEXT:    vand.v $vr0, $vr0, $vr2
-; LA64-NEXT:    vbsrl.v $vr1, $vr0, 8
-; LA64-NEXT:    vmax.du $vr0, $vr1, $vr0
-; LA64-NEXT:    vpickve2gr.d $a0, $vr0, 0
-; LA64-NEXT:    ori $a2, $zero, 2
-; LA64-NEXT:    sub.d $a0, $a2, $a0
+; LA64-NEXT:    vmskltz.d $vr0, $vr0
+; LA64-NEXT:    vpickve2gr.hu $a0, $vr0, 0
+; LA64-NEXT:    ori $a0, $a0, 4
+; LA64-NEXT:    ctz.d $a0, $a0
 ; LA64-NEXT:    st.d $a0, $a1, 0
 ; LA64-NEXT:    ret
   %a = load <2 x i64>, ptr %src
@@ -53,15 +45,10 @@ define void @first_set_lane_v2i64_poison(ptr %src, ptr %dst) {
 ; LA32:       # %bb.0:
 ; LA32-NEXT:    vld $vr0, $a0, 0
 ; LA32-NEXT:    vld $vr1, $a1, 0
-; LA32-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI1_0)
-; LA32-NEXT:    vld $vr2, $a0, %pc_lo12(.LCPI1_0)
 ; LA32-NEXT:    vseq.d $vr0, $vr0, $vr1
-; LA32-NEXT:    vand.v $vr0, $vr0, $vr2
-; LA32-NEXT:    vbsrl.v $vr1, $vr0, 8
-; LA32-NEXT:    vmax.du $vr0, $vr1, $vr0
-; LA32-NEXT:    vpickve2gr.w $a0, $vr0, 0
-; LA32-NEXT:    ori $a2, $zero, 2
-; LA32-NEXT:    sub.w $a0, $a2, $a0
+; LA32-NEXT:    vmskltz.d $vr0, $vr0
+; LA32-NEXT:    vpickve2gr.hu $a0, $vr0, 0
+; LA32-NEXT:    ctz.w $a0, $a0
 ; LA32-NEXT:    st.w $zero, $a1, 4
 ; LA32-NEXT:    st.w $a0, $a1, 0
 ; LA32-NEXT:    ret
@@ -70,15 +57,10 @@ define void @first_set_lane_v2i64_poison(ptr %src, ptr %dst) {
 ; LA64:       # %bb.0:
 ; LA64-NEXT:    vld $vr0, $a0, 0
 ; LA64-NEXT:    vld $vr1, $a1, 0
-; LA64-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI1_0)
-; LA64-NEXT:    vld $vr2, $a0, %pc_lo12(.LCPI1_0)
 ; LA64-NEXT:    vseq.d $vr0, $vr0, $vr1
-; LA64-NEXT:    vand.v $vr0, $vr0, $vr2
-; LA64-NEXT:    vbsrl.v $vr1, $vr0, 8
-; LA64-NEXT:    vmax.du $vr0, $vr1, $vr0
-; LA64-NEXT:    vpickve2gr.d $a0, $vr0, 0
-; LA64-NEXT:    ori $a2, $zero, 2
-; LA64-NEXT:    sub.d $a0, $a2, $a0
+; LA64-NEXT:    vmskltz.d $vr0, $vr0
+; LA64-NEXT:    vpickve2gr.hu $a0, $vr0, 0
+; LA64-NEXT:    ctz.d $a0, $a0
 ; LA64-NEXT:    st.d $a0, $a1, 0
 ; LA64-NEXT:    ret
   %a = load <2 x i64>, ptr %src
@@ -94,17 +76,11 @@ define void @first_set_lane_v4i32(ptr %src, ptr %dst) {
 ; LA32:       # %bb.0:
 ; LA32-NEXT:    vld $vr0, $a0, 0
 ; LA32-NEXT:    vld $vr1, $a1, 0
-; LA32-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI2_0)
-; LA32-NEXT:    vld $vr2, $a0, %pc_lo12(.LCPI2_0)
 ; LA32-NEXT:    vseq.w $vr0, $vr0, $vr1
-; LA32-NEXT:    vand.v $vr0, $vr0, $vr2
-; LA32-NEXT:    vbsrl.v $vr1, $vr0, 8
-; LA32-NEXT:    vmax.wu $vr0, $vr1, $vr0
-; LA32-NEXT:    vbsrl.v $vr1, $vr0, 4
-; LA32-NEXT:    vmax.wu $vr0, $vr1, $vr0
-; LA32-NEXT:    vpickve2gr.w $a0, $vr0, 0
-; LA32-NEXT:    ori $a2, $zero, 4
-; LA32-NEXT:    sub.w $a0, $a2, $a0
+; LA32-NEXT:    vmskltz.w $vr0, $vr0
+; LA32-NEXT:    vpickve2gr.hu $a0, $vr0, 0
+; LA32-NEXT:    ori $a0, $a0, 16
+; LA32-NEXT:    ctz.w $a0, $a0
 ; LA32-NEXT:    st.w $zero, $a1, 4
 ; LA32-NEXT:    st.w $a0, $a1, 0
 ; LA32-NEXT:    ret
@@ -113,17 +89,11 @@ define void @first_set_lane_v4i32(ptr %src, ptr %dst) {
 ; LA64:       # %bb.0:
 ; LA64-NEXT:    vld $vr0, $a0, 0
 ; LA64-NEXT:    vld $vr1, $a1, 0
-; LA64-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI2_0)
-; LA64-NEXT:    vld $vr2, $a0, %pc_lo12(.LCPI2_0)
 ; LA64-NEXT:    vseq.w $vr0, $vr0, $vr1
-; LA64-NEXT:    vand.v $vr0, $vr0, $vr2
-; LA64-NEXT:    vbsrl.v $vr1, $vr0, 8
-; LA64-NEXT:    vmax.wu $vr0, $vr1, $vr0
-; LA64-NEXT:    vbsrl.v $vr1, $vr0, 4
-; LA64-NEXT:    vmax.wu $vr0, $vr1, $vr0
-; LA64-NEXT:    vpickve2gr.wu $a0, $vr0, 0
-; LA64-NEXT:    ori $a2, $zero, 4
-; LA64-NEXT:    sub.d $a0, $a2, $a0
+; LA64-NEXT:    vmskltz.w $vr0, $vr0
+; LA64-NEXT:    vpickve2gr.hu $a0, $vr0, 0
+; LA64-NEXT:    ori $a0, $a0, 16
+; LA64-NEXT:    ctz.d $a0, $a0
 ; LA64-NEXT:    st.d $a0, $a1, 0
 ; LA64-NEXT:    ret
   %a = load <4 x i32>, ptr %src
@@ -139,19 +109,11 @@ define void @first_set_lane_v8i16(ptr %src, ptr %dst) {
 ; LA32:       # %bb.0:
 ; LA32-NEXT:    vld $vr0, $a0, 0
 ; LA32-NEXT:    vld $vr1, $a1, 0
-; LA32-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI3_0)
-; LA32-NEXT:    vld $vr2, $a0, %pc_lo12(.LCPI3_0)
 ; LA32-NEXT:    vseq.h $vr0, $vr0, $vr1
-; LA32-NEXT:    vand.v $vr0, $vr0, $vr2
-; LA32-NEXT:    vbsrl.v $vr1, $vr0, 8
-; LA32-NEXT:    vmax.hu $vr0, $vr1, $vr0
-; LA32-NEXT:    vbsrl.v $vr1, $vr0, 4
-; LA32-NEXT:    vmax.hu $vr0, $vr1, $vr0
-; LA32-NEXT:    vbsrl.v $vr1, $vr0, 2
-; LA32-NEXT:    vmax.hu $vr0, $vr1, $vr0
+; LA32-NEXT:    vmskltz.h $vr0, $vr0
 ; LA32-NEXT:    vpickve2gr.hu $a0, $vr0, 0
-; LA32-NEXT:    ori $a2, $zero, 8
-; LA32-NEXT:    sub.w $a0, $a2, $a0
+; LA32-NEXT:    ori $a0, $a0, 256
+; LA32-NEXT:    ctz.w $a0, $a0
 ; LA32-NEXT:    st.w $zero, $a1, 4
 ; LA32-NEXT:    st.w $a0, $a1, 0
 ; LA32-NEXT:    ret
@@ -160,19 +122,11 @@ define void @first_set_lane_v8i16(ptr %src, ptr %dst) {
 ; LA64:       # %bb.0:
 ; LA64-NEXT:    vld $vr0, $a0, 0
 ; LA64-NEXT:    vld $vr1, $a1, 0
-; LA64-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI3_0)
-; LA64-NEXT:    vld $vr2, $a0, %pc_lo12(.LCPI3_0)
 ; LA64-NEXT:    vseq.h $vr0, $vr0, $vr1
-; LA64-NEXT:    vand.v $vr0, $vr0, $vr2
-; LA64-NEXT:    vbsrl.v $vr1, $vr0, 8
-; LA64-NEXT:    vmax.hu $vr0, $vr1, $vr0
-; LA64-NEXT:    vbsrl.v $vr1, $vr0, 4
-; LA64-NEXT:    vmax.hu $vr0, $vr1, $vr0
-; LA64-NEXT:    vbsrl.v $vr1, $vr0, 2
-; LA64-NEXT:    vmax.hu $vr0, $vr1, $vr0
+; LA64-NEXT:    vmskltz.h $vr0, $vr0
 ; LA64-NEXT:    vpickve2gr.hu $a0, $vr0, 0
-; LA64-NEXT:    ori $a2, $zero, 8
-; LA64-NEXT:    sub.d $a0, $a2, $a0
+; LA64-NEXT:    ori $a0, $a0, 256
+; LA64-NEXT:    ctz.d $a0, $a0
 ; LA64-NEXT:    st.d $a0, $a1, 0
 ; LA64-NEXT:    ret
   %a = load <8 x i16>, ptr %src
@@ -188,21 +142,12 @@ define void @first_set_lane_v16i8(ptr %src, ptr %dst) {
 ; LA32:       # %bb.0:
 ; LA32-NEXT:    vld $vr0, $a0, 0
 ; LA32-NEXT:    vld $vr1, $a1, 0
-; LA32-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI4_0)
-; LA32-NEXT:    vld $vr2, $a0, %pc_lo12(.LCPI4_0)
 ; LA32-NEXT:    vseq.b $vr0, $vr0, $vr1
-; LA32-NEXT:    vand.v $vr0, $vr0, $vr2
-; LA32-NEXT:    vbsrl.v $vr1, $vr0, 8
-; LA32-NEXT:    vmax.bu $vr0, $vr1, $vr0
-; LA32-NEXT:    vbsrl.v $vr1, $vr0, 4
-; LA32-NEXT:    vmax.bu $vr0, $vr1, $vr0
-; LA32-NEXT:    vbsrl.v $vr1, $vr0, 2
-; LA32-NEXT:    vmax.bu $vr0, $vr1, $vr0
-; LA32-NEXT:    vbsrl.v $vr1, $vr0, 1
-; LA32-NEXT:    vmax.bu $vr0, $vr1, $vr0
-; LA32-NEXT:    vpickve2gr.bu $a0, $vr0, 0
-; LA32-NEXT:    ori $a2, $zero, 16
-; LA32-NEXT:    sub.w $a0, $a2, $a0
+; LA32-NEXT:    vmskltz.b $vr0, $vr0
+; LA32-NEXT:    vpickve2gr.hu $a0, $vr0, 0
+; LA32-NEXT:    lu12i.w $a2, 16
+; LA32-NEXT:    or $a0, $a0, $a2
+; LA32-NEXT:    ctz.w $a0, $a0
 ; LA32-NEXT:    st.w $zero, $a1, 4
 ; LA32-NEXT:    st.w $a0, $a1, 0
 ; LA32-NEXT:    ret
@@ -211,21 +156,12 @@ define void @first_set_lane_v16i8(ptr %src, ptr %dst) {
 ; LA64:       # %bb.0:
 ; LA64-NEXT:    vld $vr0, $a0, 0
 ; LA64-NEXT:    vld $vr1, $a1, 0
-; LA64-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI4_0)
-; LA64-NEXT:    vld $vr2, $a0, %pc_lo12(.LCPI4_0)
 ; LA64-NEXT:    vseq.b $vr0, $vr0, $vr1
-; LA64-NEXT:    vand.v $vr0, $vr0, $vr2
-; LA64-NEXT:    vbsrl.v $vr1, $vr0, 8
-; LA64-NEXT:    vmax.bu $vr0, $vr1, $vr0
-; LA64-NEXT:    vbsrl.v $vr1, $vr0, 4
-; LA64-NEXT:    vmax.bu $vr0, $vr1, $vr0
-; LA64-NEXT:    vbsrl.v $vr1, $vr0, 2
-; LA64-NEXT:    vmax.bu $vr0, $vr1, $vr0
-; LA64-NEXT:    vbsrl.v $vr1, $vr0, 1
-; LA64-NEXT:    vmax.bu $vr0, $vr1, $vr0
-; LA64-NEXT:    vpickve2gr.bu $a0, $vr0, 0
-; LA64-NEXT:    ori $a2, $zero, 16
-; LA64-NEXT:    sub.d $a0, $a2, $a0
+; LA64-NEXT:    vmskltz.b $vr0, $vr0
+; LA64-NEXT:    vpickve2gr.hu $a0, $vr0, 0
+; LA64-NEXT:    lu12i.w $a2, 16
+; LA64-NEXT:    or $a0, $a0, $a2
+; LA64-NEXT:    ctz.d $a0, $a0
 ; LA64-NEXT:    st.d $a0, $a1, 0
 ; LA64-NEXT:    ret
   %a = load <16 x i8>, ptr %src



More information about the llvm-commits mailing list