diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -4796,6 +4796,15 @@ case ISD::VSCALE: assert(VT == Operand.getValueType() && "Unexpected VT!"); break; + case ISD::CTPOP: + if (Operand.getValueType().getScalarType() == MVT::i1) + return Operand; + break; + case ISD::CTLZ: + case ISD::CTTZ: + if (Operand.getValueType().getScalarType() == MVT::i1) + return getNOT(DL, Operand, Operand.getValueType()); + break; case ISD::VECREDUCE_SMIN: case ISD::VECREDUCE_UMAX: if (Operand.getValueType().getScalarType() == MVT::i1) diff --git a/llvm/test/CodeGen/AArch64/sve-bit-counting-pred.ll b/llvm/test/CodeGen/AArch64/sve-bit-counting-pred.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/sve-bit-counting-pred.ll @@ -0,0 +1,141 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=aarch64-linux-gnu -mattr=+sve < %s 2>%t | FileCheck %s +; RUN: FileCheck --check-prefix=WARN --allow-empty %s <%t + +; If this check fails please read test/CodeGen/AArch64/README for instructions on how to resolve it. +; WARN-NOT: warning + +; +; CTPOP +; + +define @ctpop_nxv16i1( %a) { +; CHECK-LABEL: ctpop_nxv16i1: +; CHECK: // %bb.0: +; CHECK-NEXT: ret + %res = call @llvm.ctpop.nxv16i1( %a) + ret %res +} + +define @ctpop_nxv8i1( %a) { +; CHECK-LABEL: ctpop_nxv8i1: +; CHECK: // %bb.0: +; CHECK-NEXT: ret + %res = call @llvm.ctpop.nxv8i1( %a) + ret %res +} + +define @ctpop_nxv4i1( %a) { +; CHECK-LABEL: ctpop_nxv4i1: +; CHECK: // %bb.0: +; CHECK-NEXT: ret + %res = call @llvm.ctpop.nxv4i1( %a) + ret %res +} + +define @ctpop_nxv2i1( %a) { +; CHECK-LABEL: ctpop_nxv2i1: +; CHECK: // %bb.0: +; CHECK-NEXT: ret + %res = call @llvm.ctpop.nxv2i1( %a) + ret %res +} + +; CTLZ + +define @ctlz_nxv16i1( %a) { +; CHECK-LABEL: ctlz_nxv16i1: +; CHECK: // %bb.0: +; CHECK-NEXT: ptrue p1.b +; CHECK-NEXT: not p0.b, p1/z, p0.b +; CHECK-NEXT: ret + %res = call @llvm.ctlz.nxv16i1( %a) + ret %res +} + +define @ctlz_nxv8i1( %a) { +; CHECK-LABEL: ctlz_nxv8i1: +; CHECK: // %bb.0: +; CHECK-NEXT: ptrue p1.h +; CHECK-NEXT: not p0.b, p1/z, p0.b +; CHECK-NEXT: ret + %res = call @llvm.ctlz.nxv8i1( %a) + ret %res +} + +define @ctlz_nxv4i1( %a) { +; CHECK-LABEL: ctlz_nxv4i1: +; CHECK: // %bb.0: +; CHECK-NEXT: ptrue p1.s +; CHECK-NEXT: not p0.b, p1/z, p0.b +; CHECK-NEXT: ret + %res = call @llvm.ctlz.nxv4i1( %a) + ret %res +} + +define @ctlz_nxv2i1( %a) { +; CHECK-LABEL: ctlz_nxv2i1: +; CHECK: // %bb.0: +; CHECK-NEXT: ptrue p1.d +; CHECK-NEXT: not p0.b, p1/z, p0.b +; CHECK-NEXT: ret + %res = call @llvm.ctlz.nxv2i1( %a) + ret %res +} + +; CTTZ + +define @cttz_nxv16i1( %a) { +; CHECK-LABEL: cttz_nxv16i1: +; CHECK: // %bb.0: +; CHECK-NEXT: ptrue p1.b +; CHECK-NEXT: not p0.b, p1/z, p0.b +; CHECK-NEXT: ret + %res = call @llvm.cttz.nxv16i1( %a) + ret %res +} + +define @cttz_nxv8i1( %a) { +; CHECK-LABEL: cttz_nxv8i1: +; CHECK: // %bb.0: +; CHECK-NEXT: ptrue p1.h +; CHECK-NEXT: not p0.b, p1/z, p0.b +; CHECK-NEXT: ret + %res = call @llvm.cttz.nxv8i1( %a) + ret %res +} + +define @cttz_nxv4i1( %a) { +; CHECK-LABEL: cttz_nxv4i1: +; CHECK: // %bb.0: +; CHECK-NEXT: ptrue p1.s +; CHECK-NEXT: not p0.b, p1/z, p0.b +; CHECK-NEXT: ret + %res = call @llvm.cttz.nxv4i1( %a) + ret %res +} + +define @cttz_nxv2i1( %a) { +; CHECK-LABEL: cttz_nxv2i1: +; CHECK: // %bb.0: +; CHECK-NEXT: ptrue p1.d +; CHECK-NEXT: not p0.b, p1/z, p0.b +; CHECK-NEXT: ret + %res = call @llvm.cttz.nxv2i1( %a) + ret %res +} + +declare @llvm.ctpop.nxv16i1() +declare @llvm.ctpop.nxv8i1() +declare @llvm.ctpop.nxv4i1() +declare @llvm.ctpop.nxv2i1() + +declare @llvm.ctlz.nxv16i1() +declare @llvm.ctlz.nxv8i1() +declare @llvm.ctlz.nxv4i1() +declare @llvm.ctlz.nxv2i1() + +declare @llvm.cttz.nxv16i1() +declare @llvm.cttz.nxv8i1() +declare @llvm.cttz.nxv4i1() +declare @llvm.cttz.nxv2i1()