Index: llvm/lib/Target/AArch64/AArch64ISelLowering.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -17467,19 +17467,31 @@ SelectionDAG &DAG) { SDLoc DL(N); + EVT VT = N->getValueType(0); SDValue Pred = N->getOperand(1); SDValue VecToReduce = N->getOperand(2); + EVT DataVT = VecToReduce.getValueType(); + + // Promote the result and operands for legalization to handle later. + if (DataVT.getVectorElementType().getSimpleVT().SimpleTy == MVT::i1) { + SDValue IID = N->getOperand(0); + EVT NewDataVT = getPromotedVTForPredicate(DataVT); + auto Extend = DAG.getNode(ISD::SIGN_EXTEND, DL, NewDataVT, VecToReduce); + auto NewOp = + DAG.getNode(N->getOpcode(), DL, NewDataVT.getVectorElementType(), IID, + Pred, Extend); + return DAG.getNode(ISD::TRUNCATE, DL, VT, NewOp); + } // NOTE: The integer reduction's result type is not always linked to the // operand's element type so we construct it from the intrinsic's result type. - EVT ReduceVT = getPackedSVEVectorVT(N->getValueType(0)); + EVT ReduceVT = getPackedSVEVectorVT(VT); SDValue Reduce = DAG.getNode(Opc, DL, ReduceVT, Pred, VecToReduce); // SVE reductions set the whole vector register with the first element // containing the reduction result, which we'll now extract. SDValue Zero = DAG.getConstant(0, DL, MVT::i64); - return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, N->getValueType(0), Reduce, - Zero); + return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, Reduce, Zero); } static SDValue combineSVEReductionFP(SDNode *N, unsigned Opc, Index: llvm/test/CodeGen/AArch64/sve-int-reduce-pred.ll =================================================================== --- llvm/test/CodeGen/AArch64/sve-int-reduce-pred.ll +++ llvm/test/CodeGen/AArch64/sve-int-reduce-pred.ll @@ -399,6 +399,31 @@ ret i64 %out } +define void @PR59108() { +; CHECK-LABEL: PR59108: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: mov z0.s, #0 // =0x0 +; CHECK-NEXT: pfalse p0.b +; CHECK-NEXT: orv s0, p0, z0.s +; CHECK-NEXT: fmov w8, s0 +; CHECK-NEXT: tbnz w8, #0, .LBB36_2 +; CHECK-NEXT: // %bb.1: // %vector.ph +; CHECK-NEXT: mov x8, xzr +; CHECK-NEXT: str wzr, [x8] +; CHECK-NEXT: .LBB36_2: // %exit +; CHECK-NEXT: ret +entry: + %or = call i1 @llvm.aarch64.sve.orv.nxv4i1( zeroinitializer, zeroinitializer) + br i1 %or, label %exit, label %vector.ph + +vector.ph: ; preds = %entry + store volatile i32 0, ptr null, align 4 + br label %exit + +exit: ; preds = %vector.ph, %entry + ret void +} + declare i64 @llvm.aarch64.sve.saddv.nxv16i8(, ) declare i64 @llvm.aarch64.sve.saddv.nxv8i16(, ) declare i64 @llvm.aarch64.sve.saddv.nxv4i32(, ) @@ -423,6 +448,7 @@ declare i16 @llvm.aarch64.sve.uminv.nxv8i16(, ) declare i32 @llvm.aarch64.sve.uminv.nxv4i32(, ) declare i64 @llvm.aarch64.sve.uminv.nxv2i64(, ) +declare i1 @llvm.aarch64.sve.orv.nxv4i1(, ) declare i8 @llvm.aarch64.sve.orv.nxv16i8(, ) declare i16 @llvm.aarch64.sve.orv.nxv8i16(, ) declare i32 @llvm.aarch64.sve.orv.nxv4i32 (, )