[llvm] [LoongArch] Materialize vector zero-test results via `MOVCF2GR` (PR #230804)

via llvm-commits llvm-commits at lists.llvm.org
Sat Oct 10 08:57:35 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-loongarch

Author: Rong "Mantle" Bao (CSharperMantle)

<details>
<summary>Changes</summary>

This generalizes the changes in the previous commit so that all zero-test results can be consumed directly through `$FCC` when possible, and materialized via `MOVCF2GR`, rather than branchy blocks, when really needed. Test expectations are updated accordingly.

I created [a microbench](https://gist.github.com/CSharperMantle/cc31f0320f15e1fc3985dafa567c5f75) with LLM assistance, which yielded the following results on my Loongson 3B6000 12C24T (units are in cycle, N=31). On all cases, the new sequence performs better in cycles than the current ("Old") one.

| Scenario                     | Old geomean | Old +/- % |  Old SD | New geomean | New +/- % | New SD | New/Old |  delta |   Welch p |
| ---------------------------- | ----------: | --------: | ------: | ----------: | --------: | -----: | ------: | -----: | --------: |
| linear / predicted-taken     |   3,255,142 | +/- 0.06% |   1,864 |   1,000,225 | +/- 0.00% |     49 |  0.3073 | -69.3% |  2.24e-94 |
| linear / predicted-not-taken |   3,380,939 | +/- 0.12% |   4,072 |   1,000,225 | +/- 0.00% |     49 |  0.2958 | -70.4% |  8.27e-85 |
| linear / unpredictable       |  10,256,382 | +/- 1.16% | 118,984 |   2,000,444 | +/- 0.02% |    402 |  0.1950 | -80.5% |  5.06e-57 |
| loop / predicted-taken       |   1,032,264 | +/- 0.00% |      42 |     519,737 | +/- 0.01% |     42 |  0.5035 | -49.7% | 3.85e-229 |
| loop / predicted-not-taken   |   1,032,286 | +/- 0.01% |      60 |     519,737 | +/- 0.01% |     42 |  0.5035 | -49.7% | 2.73e-202 |
| loop / unpredictable         |   1,390,452 | +/- 0.89% |  12,355 |   1,031,514 | +/- 0.13% |  1,328 |  0.7419 | -25.8% |  1.77e-46 |

Depends-on: #<!-- -->230801



---

Patch is 55.12 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/230804.diff


12 Files Affected:

- (modified) llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp (+5-147) 
- (modified) llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td (+13-22) 
- (modified) llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td (+27-33) 
- (added) llvm/test/CodeGen/LoongArch/lasx/intrinsic-bz-bnz.ll (+403) 
- (modified) llvm/test/CodeGen/LoongArch/lasx/intrinsic-set.ll (+2-12) 
- (modified) llvm/test/CodeGen/LoongArch/lasx/intrinsic-setallnez.ll (+4-24) 
- (modified) llvm/test/CodeGen/LoongArch/lasx/intrinsic-setanyeqz.ll (+4-24) 
- (added) llvm/test/CodeGen/LoongArch/lsx/intrinsic-bz-bnz.ll (+693) 
- (modified) llvm/test/CodeGen/LoongArch/lsx/intrinsic-set.ll (+2-12) 
- (modified) llvm/test/CodeGen/LoongArch/lsx/intrinsic-setallnez.ll (+4-24) 
- (modified) llvm/test/CodeGen/LoongArch/lsx/intrinsic-setanyeqz.ll (+4-24) 
- (modified) llvm/test/CodeGen/LoongArch/sextw-removal.ll (+2-15) 


``````````diff
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index 0639fb19e1454..6dc4e9bb5be68 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -8999,131 +8999,6 @@ static MachineBasicBlock *insertDivByZeroTrap(MachineInstr &MI,
   return SinkMBB;
 }
 
-static MachineBasicBlock *
-emitVecCondBranchPseudo(MachineInstr &MI, MachineBasicBlock *BB,
-                        const LoongArchSubtarget &Subtarget) {
-  unsigned CondOpc;
-  switch (MI.getOpcode()) {
-  default:
-    llvm_unreachable("Unexpected opcode");
-  case LoongArch::PseudoVBZ:
-    CondOpc = LoongArch::VSETEQZ_V;
-    break;
-  case LoongArch::PseudoVBZ_B:
-    CondOpc = LoongArch::VSETANYEQZ_B;
-    break;
-  case LoongArch::PseudoVBZ_H:
-    CondOpc = LoongArch::VSETANYEQZ_H;
-    break;
-  case LoongArch::PseudoVBZ_W:
-    CondOpc = LoongArch::VSETANYEQZ_W;
-    break;
-  case LoongArch::PseudoVBZ_D:
-    CondOpc = LoongArch::VSETANYEQZ_D;
-    break;
-  case LoongArch::PseudoVBNZ:
-    CondOpc = LoongArch::VSETNEZ_V;
-    break;
-  case LoongArch::PseudoVBNZ_B:
-    CondOpc = LoongArch::VSETALLNEZ_B;
-    break;
-  case LoongArch::PseudoVBNZ_H:
-    CondOpc = LoongArch::VSETALLNEZ_H;
-    break;
-  case LoongArch::PseudoVBNZ_W:
-    CondOpc = LoongArch::VSETALLNEZ_W;
-    break;
-  case LoongArch::PseudoVBNZ_D:
-    CondOpc = LoongArch::VSETALLNEZ_D;
-    break;
-  case LoongArch::PseudoXVBZ:
-    CondOpc = LoongArch::XVSETEQZ_V;
-    break;
-  case LoongArch::PseudoXVBZ_B:
-    CondOpc = LoongArch::XVSETANYEQZ_B;
-    break;
-  case LoongArch::PseudoXVBZ_H:
-    CondOpc = LoongArch::XVSETANYEQZ_H;
-    break;
-  case LoongArch::PseudoXVBZ_W:
-    CondOpc = LoongArch::XVSETANYEQZ_W;
-    break;
-  case LoongArch::PseudoXVBZ_D:
-    CondOpc = LoongArch::XVSETANYEQZ_D;
-    break;
-  case LoongArch::PseudoXVBNZ:
-    CondOpc = LoongArch::XVSETNEZ_V;
-    break;
-  case LoongArch::PseudoXVBNZ_B:
-    CondOpc = LoongArch::XVSETALLNEZ_B;
-    break;
-  case LoongArch::PseudoXVBNZ_H:
-    CondOpc = LoongArch::XVSETALLNEZ_H;
-    break;
-  case LoongArch::PseudoXVBNZ_W:
-    CondOpc = LoongArch::XVSETALLNEZ_W;
-    break;
-  case LoongArch::PseudoXVBNZ_D:
-    CondOpc = LoongArch::XVSETALLNEZ_D;
-    break;
-  }
-
-  const TargetInstrInfo *TII = Subtarget.getInstrInfo();
-  const BasicBlock *LLVM_BB = BB->getBasicBlock();
-  DebugLoc DL = MI.getDebugLoc();
-  MachineRegisterInfo &MRI = BB->getParent()->getRegInfo();
-  MachineFunction::iterator It = ++BB->getIterator();
-
-  MachineFunction *F = BB->getParent();
-  MachineBasicBlock *FalseBB = F->CreateMachineBasicBlock(LLVM_BB);
-  MachineBasicBlock *TrueBB = F->CreateMachineBasicBlock(LLVM_BB);
-  MachineBasicBlock *SinkBB = F->CreateMachineBasicBlock(LLVM_BB);
-
-  F->insert(It, FalseBB);
-  F->insert(It, TrueBB);
-  F->insert(It, SinkBB);
-
-  // Transfer the remainder of MBB and its successor edges to Sink.
-  SinkBB->splice(SinkBB->end(), BB, std::next(MI.getIterator()), BB->end());
-  SinkBB->transferSuccessorsAndUpdatePHIs(BB);
-
-  // Insert the real instruction to BB.
-  Register FCC = MRI.createVirtualRegister(&LoongArch::CFRRegClass);
-  BuildMI(BB, DL, TII->get(CondOpc), FCC).addReg(MI.getOperand(1).getReg());
-
-  // Insert branch.
-  BuildMI(BB, DL, TII->get(LoongArch::BCNEZ)).addReg(FCC).addMBB(TrueBB);
-  BB->addSuccessor(FalseBB);
-  BB->addSuccessor(TrueBB);
-
-  // FalseBB.
-  Register RD1 = MRI.createVirtualRegister(&LoongArch::GPRRegClass);
-  BuildMI(FalseBB, DL, TII->get(LoongArch::ADDI_W), RD1)
-      .addReg(LoongArch::R0)
-      .addImm(0);
-  BuildMI(FalseBB, DL, TII->get(LoongArch::PseudoBR)).addMBB(SinkBB);
-  FalseBB->addSuccessor(SinkBB);
-
-  // TrueBB.
-  Register RD2 = MRI.createVirtualRegister(&LoongArch::GPRRegClass);
-  BuildMI(TrueBB, DL, TII->get(LoongArch::ADDI_W), RD2)
-      .addReg(LoongArch::R0)
-      .addImm(1);
-  TrueBB->addSuccessor(SinkBB);
-
-  // SinkBB: merge the results.
-  BuildMI(*SinkBB, SinkBB->begin(), DL, TII->get(LoongArch::PHI),
-          MI.getOperand(0).getReg())
-      .addReg(RD1)
-      .addMBB(FalseBB)
-      .addReg(RD2)
-      .addMBB(TrueBB);
-
-  // The pseudo instruction is gone now.
-  MI.eraseFromParent();
-  return SinkBB;
-}
-
 static MachineBasicBlock *
 emitPseudoXVINSGR2VR(MachineInstr &MI, MachineBasicBlock *BB,
                      const LoongArchSubtarget &Subtarget) {
@@ -9585,27 +9460,6 @@ MachineBasicBlock *LoongArchTargetLowering::EmitInstrWithCustomInserter(
     return emitBuildPairF64Pseudo(MI, BB, Subtarget);
   case LoongArch::SplitPairF64Pseudo:
     return emitSplitPairF64Pseudo(MI, BB, Subtarget);
-  case LoongArch::PseudoVBZ:
-  case LoongArch::PseudoVBZ_B:
-  case LoongArch::PseudoVBZ_H:
-  case LoongArch::PseudoVBZ_W:
-  case LoongArch::PseudoVBZ_D:
-  case LoongArch::PseudoVBNZ:
-  case LoongArch::PseudoVBNZ_B:
-  case LoongArch::PseudoVBNZ_H:
-  case LoongArch::PseudoVBNZ_W:
-  case LoongArch::PseudoVBNZ_D:
-  case LoongArch::PseudoXVBZ:
-  case LoongArch::PseudoXVBZ_B:
-  case LoongArch::PseudoXVBZ_H:
-  case LoongArch::PseudoXVBZ_W:
-  case LoongArch::PseudoXVBZ_D:
-  case LoongArch::PseudoXVBNZ:
-  case LoongArch::PseudoXVBNZ_B:
-  case LoongArch::PseudoXVBNZ_H:
-  case LoongArch::PseudoXVBNZ_W:
-  case LoongArch::PseudoXVBNZ_D:
-    return emitVecCondBranchPseudo(MI, BB, Subtarget);
   case LoongArch::PseudoXVINSGR2VR_B:
   case LoongArch::PseudoXVINSGR2VR_H:
     return emitPseudoXVINSGR2VR(MI, BB, Subtarget);
@@ -11907,7 +11761,11 @@ void LoongArchTargetLowering::computeKnownBitsForTargetNode(
   default:
     break;
   case LoongArchISD::VANYNONZERO:
-  case LoongArchISD::VALLZERO: {
+  case LoongArchISD::VALLZERO:
+  case LoongArchISD::VALL_ZERO:
+  case LoongArchISD::VANY_ZERO:
+  case LoongArchISD::VALL_NONZERO:
+  case LoongArchISD::VANY_NONZERO: {
     // MOVCF2GR zero-extend the i1 cond to GPR.
     Known.Zero.setBitsFrom(1);
     break;
diff --git a/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td
index fcd134770332d..6b3db86facf2e 100644
--- a/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td
@@ -1086,18 +1086,6 @@ def PseudoXVREPLI_D : Pseudo<(outs LASX256:$xd), (ins simm10:$imm), [],
                              "xvrepli.d", "$xd, $imm">;
 }
 
-def PseudoXVBNZ_B : VecCond<loongarch_vall_nonzero, v32i8, LASX256>;
-def PseudoXVBNZ_H : VecCond<loongarch_vall_nonzero, v16i16, LASX256>;
-def PseudoXVBNZ_W : VecCond<loongarch_vall_nonzero, v8i32, LASX256>;
-def PseudoXVBNZ_D : VecCond<loongarch_vall_nonzero, v4i64, LASX256>;
-def PseudoXVBNZ : VecCond<loongarch_vany_nonzero, v32i8, LASX256>;
-
-def PseudoXVBZ_B : VecCond<loongarch_vall_zero, v32i8, LASX256>;
-def PseudoXVBZ_H : VecCond<loongarch_vall_zero, v16i16, LASX256>;
-def PseudoXVBZ_W : VecCond<loongarch_vall_zero, v8i32, LASX256>;
-def PseudoXVBZ_D : VecCond<loongarch_vall_zero, v4i64, LASX256>;
-def PseudoXVBZ : VecCond<loongarch_vany_zero, v32i8, LASX256>;
-
 let usesCustomInserter = 1, Constraints = "$xd = $dst" in {
 def PseudoXVINSGR2VR_B
   : Pseudo<(outs LASX256:$dst), (ins LASX256:$xd, GPR:$rj, uimm5:$imm)>;
@@ -2792,16 +2780,19 @@ def : Pat<(int_loongarch_lasx_xvstelm_d v4i64:$xd, GPR:$rj, timm:$imm, timm:$idx
 
 // Whole-vector zero tests, see the LSX counterparts.
 foreach vt = [v32i8, v16i16, v8i32, v4i64] in {
-def : Pat<(GRLenVT (loongarch_vanynonzero (vt LASX256:$xj))),
-          (MOVCF2GR (XVSETNEZ_V LASX256:$xj))>;
-def : Pat<(GRLenVT (loongarch_vallzero (vt LASX256:$xj))),
-          (MOVCF2GR (XVSETEQZ_V LASX256:$xj))>;
-def : Pat<(loongarch_brcc (GRLenVT (loongarch_vanynonzero (vt LASX256:$xj))), 0,
-                          SETNE, bb:$imm21),
-          (BCNEZ (XVSETNEZ_V LASX256:$xj), bb:$imm21)>;
-def : Pat<(loongarch_brcc (GRLenVT (loongarch_vallzero (vt LASX256:$xj))), 0,
-                          SETNE, bb:$imm21),
-          (BCNEZ (XVSETEQZ_V LASX256:$xj), bb:$imm21)>;
+defm : PatVecCond<loongarch_vanynonzero, XVSETNEZ_V, vt, LASX256>;
+defm : PatVecCond<loongarch_vallzero, XVSETEQZ_V, vt, LASX256>;
 }
 
+defm : PatVecCond<loongarch_vall_zero, XVSETANYEQZ_B, v32i8, LASX256>;
+defm : PatVecCond<loongarch_vall_zero, XVSETANYEQZ_H, v16i16, LASX256>;
+defm : PatVecCond<loongarch_vall_zero, XVSETANYEQZ_W, v8i32, LASX256>;
+defm : PatVecCond<loongarch_vall_zero, XVSETANYEQZ_D, v4i64, LASX256>;
+defm : PatVecCond<loongarch_vall_nonzero, XVSETALLNEZ_B, v32i8, LASX256>;
+defm : PatVecCond<loongarch_vall_nonzero, XVSETALLNEZ_H, v16i16, LASX256>;
+defm : PatVecCond<loongarch_vall_nonzero, XVSETALLNEZ_W, v8i32, LASX256>;
+defm : PatVecCond<loongarch_vall_nonzero, XVSETALLNEZ_D, v4i64, LASX256>;
+defm : PatVecCond<loongarch_vany_zero, XVSETEQZ_V, v32i8, LASX256>;
+defm : PatVecCond<loongarch_vany_nonzero, XVSETNEZ_V, v32i8, LASX256>;
+
 } // Predicates = [HasExtLASX]
diff --git a/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td
index e1489f9e36d69..e9c188509e8d9 100644
--- a/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td
@@ -145,16 +145,6 @@ def immZExt3 : ImmLeaf<GRLenVT, [{return isUInt<3>(Imm);}]>;
 def immZExt4 : ImmLeaf<GRLenVT, [{return isUInt<4>(Imm);}]>;
 def immZExt8 : ImmLeaf<GRLenVT, [{return isUInt<8>(Imm);}]>;
 
-class VecCond<SDPatternOperator OpNode, ValueType TyNode,
-              RegisterClass RC = LSX128>
-    : Pseudo<(outs GPR:$rd), (ins RC:$vj),
-             [(set GPR:$rd, (OpNode (TyNode RC:$vj)))]> {
-  let hasSideEffects = 0;
-  let mayLoad = 0;
-  let mayStore = 0;
-  let usesCustomInserter = 1;
-}
-
 def vsplat_imm_eq_1 : PatFrags<(ops), [(build_vector)], [{
   APInt Imm;
   EVT EltTy = N->getValueType(0).getVectorElementType();
@@ -1333,18 +1323,6 @@ def PseudoVREPLI_D : Pseudo<(outs LSX128:$vd), (ins simm10:$imm), [],
                             "vrepli.d", "$vd, $imm">;
 }
 
-def PseudoVBNZ_B : VecCond<loongarch_vall_nonzero, v16i8>;
-def PseudoVBNZ_H : VecCond<loongarch_vall_nonzero, v8i16>;
-def PseudoVBNZ_W : VecCond<loongarch_vall_nonzero, v4i32>;
-def PseudoVBNZ_D : VecCond<loongarch_vall_nonzero, v2i64>;
-def PseudoVBNZ : VecCond<loongarch_vany_nonzero, v16i8>;
-
-def PseudoVBZ_B : VecCond<loongarch_vall_zero, v16i8>;
-def PseudoVBZ_H : VecCond<loongarch_vall_zero, v8i16>;
-def PseudoVBZ_W : VecCond<loongarch_vall_zero, v4i32>;
-def PseudoVBZ_D : VecCond<loongarch_vall_zero, v2i64>;
-def PseudoVBZ : VecCond<loongarch_vany_zero, v16i8>;
-
 let usesCustomInserter = 1 in {
 def PseudoCTPOP_B : Pseudo<(outs GPR:$rd), (ins GPR:$rj),
                            [(set GPR:$rd, (ctpop (and GPR:$rj, 255)))]>;
@@ -2468,21 +2446,37 @@ def : Pat<(loongarch_vmskgez (v16i8 LSX128:$vj)), (PseudoVMSKGEZ_B LSX128:$vj)>;
 def : Pat<(loongarch_vmskeqz (v16i8 LSX128:$vj)), (PseudoVMSKEQZ_B LSX128:$vj)>;
 def : Pat<(loongarch_vmsknez (v16i8 LSX128:$vj)), (PseudoVMSKNEZ_B LSX128:$vj)>;
 
-// Whole-vector zero tests. The result lives in a condition flag register, so a
+// Vector tests against zero. The result lives in a condition flag register, so a
 // branch consumes it directly and only a materialization needs MOVCF2GR.
+multiclass PatVecCond<SDPatternOperator OpNode, LAInst VSet, ValueType VT,
+                      RegisterClass RC> {
+  def : Pat<(GRLenVT (OpNode (VT RC:$vj))),
+            (MOVCF2GR (VSet RC:$vj))>;
+  def : Pat<(loongarch_brcc (GRLenVT (OpNode (VT RC:$vj))), 0,
+                            SETNE, bb:$imm21),
+            (BCNEZ (VSet RC:$vj), bb:$imm21)>;
+  def : Pat<(loongarch_brcc (GRLenVT (OpNode (VT RC:$vj))), 0,
+                            SETEQ, bb:$imm21),
+            (BCEQZ (VSet RC:$vj), bb:$imm21)>;
+}
+
+// Whole-vector zero tests.
 foreach vt = [v16i8, v8i16, v4i32, v2i64] in {
-def : Pat<(GRLenVT (loongarch_vanynonzero (vt LSX128:$vj))),
-          (MOVCF2GR (VSETNEZ_V LSX128:$vj))>;
-def : Pat<(GRLenVT (loongarch_vallzero (vt LSX128:$vj))),
-          (MOVCF2GR (VSETEQZ_V LSX128:$vj))>;
-def : Pat<(loongarch_brcc (GRLenVT (loongarch_vanynonzero (vt LSX128:$vj))), 0,
-                          SETNE, bb:$imm21),
-          (BCNEZ (VSETNEZ_V LSX128:$vj), bb:$imm21)>;
-def : Pat<(loongarch_brcc (GRLenVT (loongarch_vallzero (vt LSX128:$vj))), 0,
-                          SETNE, bb:$imm21),
-          (BCNEZ (VSETEQZ_V LSX128:$vj), bb:$imm21)>;
+defm : PatVecCond<loongarch_vanynonzero, VSETNEZ_V, vt, LSX128>;
+defm : PatVecCond<loongarch_vallzero, VSETEQZ_V, vt, LSX128>;
 }
 
+defm : PatVecCond<loongarch_vall_zero, VSETANYEQZ_B, v16i8, LSX128>;
+defm : PatVecCond<loongarch_vall_zero, VSETANYEQZ_H, v8i16, LSX128>;
+defm : PatVecCond<loongarch_vall_zero, VSETANYEQZ_W, v4i32, LSX128>;
+defm : PatVecCond<loongarch_vall_zero, VSETANYEQZ_D, v2i64, LSX128>;
+defm : PatVecCond<loongarch_vall_nonzero, VSETALLNEZ_B, v16i8, LSX128>;
+defm : PatVecCond<loongarch_vall_nonzero, VSETALLNEZ_H, v8i16, LSX128>;
+defm : PatVecCond<loongarch_vall_nonzero, VSETALLNEZ_W, v4i32, LSX128>;
+defm : PatVecCond<loongarch_vall_nonzero, VSETALLNEZ_D, v2i64, LSX128>;
+defm : PatVecCond<loongarch_vany_zero, VSETEQZ_V, v16i8, LSX128>;
+defm : PatVecCond<loongarch_vany_nonzero, VSETNEZ_V, v16i8, LSX128>;
+
 } // Predicates = [HasExtLSX]
 
 /// Intrinsic pattern
diff --git a/llvm/test/CodeGen/LoongArch/lasx/intrinsic-bz-bnz.ll b/llvm/test/CodeGen/LoongArch/lasx/intrinsic-bz-bnz.ll
new file mode 100644
index 0000000000000..7760ec0247f9e
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/lasx/intrinsic-bz-bnz.ll
@@ -0,0 +1,403 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc --mtriple=loongarch64 --mattr=+lasx --verify-machineinstrs < %s | FileCheck %s
+
+declare i32 @llvm.loongarch.lasx.xbz.b(<32 x i8>)
+declare i32 @llvm.loongarch.lasx.xbz.h(<16 x i16>)
+declare i32 @llvm.loongarch.lasx.xbz.w(<8 x i32>)
+declare i32 @llvm.loongarch.lasx.xbz.d(<4 x i64>)
+declare i32 @llvm.loongarch.lasx.xbz.v(<32 x i8>)
+declare i32 @llvm.loongarch.lasx.xbnz.b(<32 x i8>)
+declare i32 @llvm.loongarch.lasx.xbnz.h(<16 x i16>)
+declare i32 @llvm.loongarch.lasx.xbnz.w(<8 x i32>)
+declare i32 @llvm.loongarch.lasx.xbnz.d(<4 x i64>)
+declare i32 @llvm.loongarch.lasx.xbnz.v(<32 x i8>)
+
+define void @xbz_b_ne(<32 x i8> %v, ptr %p) {
+; CHECK-LABEL: xbz_b_ne:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xvsetanyeqz.b $fcc0, $xr0
+; CHECK-NEXT:    bceqz $fcc0, .LBB0_2
+; CHECK-NEXT:  # %bb.1: # %t
+; CHECK-NEXT:    ld.w $zero, $a0, 0
+; CHECK-NEXT:  .LBB0_2: # %e
+; CHECK-NEXT:    ret
+  %r = call i32 @llvm.loongarch.lasx.xbz.b(<32 x i8> %v)
+  %c = icmp ne i32 %r, 0
+  br i1 %c, label %t, label %e
+t:
+  %l = load volatile i32, ptr %p
+  ret void
+e:
+  ret void
+}
+
+define void @xbz_b_eq(<32 x i8> %v, ptr %p) {
+; CHECK-LABEL: xbz_b_eq:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xvsetanyeqz.b $fcc0, $xr0
+; CHECK-NEXT:    bceqz $fcc0, .LBB1_2
+; CHECK-NEXT:  # %bb.1: # %e
+; CHECK-NEXT:    ret
+; CHECK-NEXT:  .LBB1_2: # %t
+; CHECK-NEXT:    ld.w $zero, $a0, 0
+; CHECK-NEXT:    ret
+  %r = call i32 @llvm.loongarch.lasx.xbz.b(<32 x i8> %v)
+  %c = icmp eq i32 %r, 0
+  br i1 %c, label %t, label %e
+t:
+  %l = load volatile i32, ptr %p
+  ret void
+e:
+  ret void
+}
+
+define void @xbz_h_ne(<16 x i16> %v, ptr %p) {
+; CHECK-LABEL: xbz_h_ne:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xvsetanyeqz.h $fcc0, $xr0
+; CHECK-NEXT:    bceqz $fcc0, .LBB2_2
+; CHECK-NEXT:  # %bb.1: # %t
+; CHECK-NEXT:    ld.w $zero, $a0, 0
+; CHECK-NEXT:  .LBB2_2: # %e
+; CHECK-NEXT:    ret
+  %r = call i32 @llvm.loongarch.lasx.xbz.h(<16 x i16> %v)
+  %c = icmp ne i32 %r, 0
+  br i1 %c, label %t, label %e
+t:
+  %l = load volatile i32, ptr %p
+  ret void
+e:
+  ret void
+}
+
+define void @xbz_h_eq(<16 x i16> %v, ptr %p) {
+; CHECK-LABEL: xbz_h_eq:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xvsetanyeqz.h $fcc0, $xr0
+; CHECK-NEXT:    bceqz $fcc0, .LBB3_2
+; CHECK-NEXT:  # %bb.1: # %e
+; CHECK-NEXT:    ret
+; CHECK-NEXT:  .LBB3_2: # %t
+; CHECK-NEXT:    ld.w $zero, $a0, 0
+; CHECK-NEXT:    ret
+  %r = call i32 @llvm.loongarch.lasx.xbz.h(<16 x i16> %v)
+  %c = icmp eq i32 %r, 0
+  br i1 %c, label %t, label %e
+t:
+  %l = load volatile i32, ptr %p
+  ret void
+e:
+  ret void
+}
+
+define void @xbz_w_ne(<8 x i32> %v, ptr %p) {
+; CHECK-LABEL: xbz_w_ne:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xvsetanyeqz.w $fcc0, $xr0
+; CHECK-NEXT:    bceqz $fcc0, .LBB4_2
+; CHECK-NEXT:  # %bb.1: # %t
+; CHECK-NEXT:    ld.w $zero, $a0, 0
+; CHECK-NEXT:  .LBB4_2: # %e
+; CHECK-NEXT:    ret
+  %r = call i32 @llvm.loongarch.lasx.xbz.w(<8 x i32> %v)
+  %c = icmp ne i32 %r, 0
+  br i1 %c, label %t, label %e
+t:
+  %l = load volatile i32, ptr %p
+  ret void
+e:
+  ret void
+}
+
+define void @xbz_w_eq(<8 x i32> %v, ptr %p) {
+; CHECK-LABEL: xbz_w_eq:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xvsetanyeqz.w $fcc0, $xr0
+; CHECK-NEXT:    bceqz $fcc0, .LBB5_2
+; CHECK-NEXT:  # %bb.1: # %e
+; CHECK-NEXT:    ret
+; CHECK-NEXT:  .LBB5_2: # %t
+; CHECK-NEXT:    ld.w $zero, $a0, 0
+; CHECK-NEXT:    ret
+  %r = call i32 @llvm.loongarch.lasx.xbz.w(<8 x i32> %v)
+  %c = icmp eq i32 %r, 0
+  br i1 %c, label %t, label %e
+t:
+  %l = load volatile i32, ptr %p
+  ret void
+e:
+  ret void
+}
+
+define void @xbz_d_ne(<4 x i64> %v, ptr %p) {
+; CHECK-LABEL: xbz_d_ne:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xvsetanyeqz.d $fcc0, $xr0
+; CHECK-NEXT:    bceqz $fcc0, .LBB6_2
+; CHECK-NEXT:  # %bb.1: # %t
+; CHECK-NEXT:    ld.w $zero, $a0, 0
+; CHECK-NEXT:  .LBB6_2: # %e
+; CHECK-NEXT:    ret
+  %r = call i32 @llvm.loongarch.lasx.xbz.d(<4 x i64> %v)
+  %c = icmp ne i32 %r, 0
+  br i1 %c, label %t, label %e
+t:
+  %l = load volatile i32, ptr %p
+  ret void
+e:
+  ret void
+}
+
+define void @xbz_d_eq(<4 x i64> %v, ptr %p) {
+; CHECK-LABEL: xbz_d_eq:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xvsetanyeqz.d $fcc0, $xr0
+; CHECK-NEXT:    bceqz $fcc0, .LBB7_2
+; CHECK-NEXT:  # %bb.1: # %e
+; CHECK-NEXT:    ret
+; CHECK-NEXT:  .LBB7_2: # %t
+; CHECK-NEXT:    ld.w $zero, $a0, 0
+; CHECK-NEXT:    ret
+  %r = call i32 @llvm.loongarch.lasx.xbz.d(<4 x i64> %v)
+  %c = icmp eq i32 %r, 0
+  br i1 %c, label %t, label %e
+t:
+  %l = load volatile i32, ptr %p
+  ret void
+e:
+  ret void
+}
+
+define void @xbz_v_ne(<32 x i8> %v, ptr %p) {
+; CHECK-LABEL: xbz_v_ne:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xvseteqz.v $fcc0, $xr0
+; CHECK-NEXT:    bceqz $fcc0, .LBB8_2
+; CHECK-NEXT:  # %bb.1: # %t
+; CHECK-NEXT:    ld.w $zero, $a0, 0
+; CHECK-NEXT:  .LBB8_2: # %e
+; CHECK-NEXT:    ret
+  %r = call i32 @llvm.loongarch.lasx.xbz.v(<32 x i8> %v)
+  %c = icmp ne i32 %r, 0
+  br i1 %c, label %t, label %e
+t:
+  %l = load volatile i32, ptr %p
+  ret void
+e:
+  ret void
+}
+
+define void @xbz_v_eq(<32 x i8> %v, ptr %p) {
+; CHECK-LABEL: xbz_v_eq:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xvseteqz.v $fcc0, $xr0
+; CHECK-NEXT:    bceqz $fcc0, .LBB9_2
+; CHECK-NEXT:  # %bb.1: # %e
+; CHECK-NEXT:    ret
+; CHECK-NEXT:  .LBB9_2: # %t
+; CHECK-NEXT:    ld.w $zero, $a0, 0
+; CHECK-NEXT:    ret
+  %r = call i32 @llvm.loongarch.lasx.xbz.v(<32 x i8> %v)
+  %c = icmp eq i32 %r, 0
+  br i1 %c, label %t, label %e
+t:
+  %l = load volatile i32, ptr %p
+  ret void
+e:
+  ret void
+}
+
+define void @xbnz_b_ne(<32 x i8> %v, ptr %p) {
+; CHECK-LABEL: xbnz_b_ne:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xvsetallnez.b $fcc0, $xr0
+; CHECK-NEXT:    bceqz $fcc0, .LBB10_2
+; CHECK-NEXT:  # %bb.1: # %t
+; CHECK-NEXT:    ld.w $zero, $a0, 0
+; CHECK-NEXT:  .LBB10_2: # %e
+; CHECK-NEXT:    ret
+  %r = call i32 @llvm.loongarch.lasx.xbnz.b(<32 x i8> %v)
+  %c = icmp ne i32 %r, 0
+  br i1 %c, label %t, label %e
+t:
+  %l = load volatile i32, ptr %p
+  ret void
+e:
+  ret void
+}
+
+define void @xbnz_b_eq(<32 x i8> %v, ptr %p) {
+; CHECK-LABEL: xbnz_b_eq:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xvsetallnez.b $fcc0, $xr0
+; CHECK-NEXT:    bceqz $fcc0, .LBB11_2
+; CHECK-NEXT:  # %bb.1: # %e
+; CHECK-NEXT:    ret
+; CHECK-NEXT:  .LBB11_2: # %t
+; CHECK-NEXT:    ld.w $zero, $a0, 0
+; CHECK-NEXT:    ret
+  %r = call i32 @llvm.loongarch.lasx.xbnz.b(<32 x i8> %v)
+  %c = icmp eq i32 %r, 0
+  br i1 %c, label %t, label %e
+t:
+  %l = load volatile i32, ptr %p
+  ret void
+e:
+  ret void
+}
+
+define void @xbnz_h_ne(<16 x i16> %v, ptr %p) {
+; CHECK-LABEL: xbnz_h_ne:
+; CHECK:       # %bb.0:
+; CHECK-NEXT: ...
[truncated]

``````````

</details>


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


More information about the llvm-commits mailing list