[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