diff --git a/llvm/include/llvm/IR/Constant.h b/llvm/include/llvm/IR/Constant.h index 0be1fc172ebd4..e8ce453559ed7 100644 --- a/llvm/include/llvm/IR/Constant.h +++ b/llvm/include/llvm/IR/Constant.h @@ -79,6 +79,9 @@ class Constant : public User { /// Return true if the value is the smallest signed value. LLVM_ABI bool isMinSignedValue() const; + /// Return true if the value is the largest signed value. + LLVM_ABI bool isMaxSignedValue() const; + /// Return true if this is a finite and non-zero floating-point scalar /// constant or a fixed width vector constant with all finite and non-zero /// elements. diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 2a0a6a2d302b1..852259e6bdda0 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -41,6 +41,7 @@ #include "llvm/IR/Dominators.h" #include "llvm/IR/InstrTypes.h" #include "llvm/IR/Instructions.h" +#include "llvm/IR/IntrinsicsAArch64.h" #include "llvm/IR/Operator.h" #include "llvm/IR/PatternMatch.h" #include "llvm/IR/Statepoint.h" @@ -6676,6 +6677,62 @@ static MinMaxOptResult OptimizeConstMinMax(const Constant *RHSConst, return MinMaxOptResult::CannotOptimize; } +static Value *simplifySVEIntReduction(Intrinsic::ID IID, Type *ReturnType, + Value *Op0, Value *Op1) { + Constant *C0 = dyn_cast(Op0); + Constant *C1 = dyn_cast(Op1); + unsigned Width = ReturnType->getPrimitiveSizeInBits(); + + // All false predicate or reduction of neutral values ==> neutral result. + switch (IID) { + case Intrinsic::aarch64_sve_eorv: + case Intrinsic::aarch64_sve_orv: + case Intrinsic::aarch64_sve_saddv: + case Intrinsic::aarch64_sve_uaddv: + case Intrinsic::aarch64_sve_umaxv: + if ((C0 && C0->isNullValue()) || (C1 && C1->isNullValue())) + return ConstantInt::get(ReturnType, 0); + break; + case Intrinsic::aarch64_sve_andv: + case Intrinsic::aarch64_sve_uminv: + if ((C0 && C0->isNullValue()) || (C1 && C1->isAllOnesValue())) + return ConstantInt::get(ReturnType, APInt::getMaxValue(Width)); + break; + case Intrinsic::aarch64_sve_smaxv: + if ((C0 && C0->isNullValue()) || (C1 && C1->isMinSignedValue())) + return ConstantInt::get(ReturnType, APInt::getSignedMinValue(Width)); + break; + case Intrinsic::aarch64_sve_sminv: + if ((C0 && C0->isNullValue()) || (C1 && C1->isMaxSignedValue())) + return ConstantInt::get(ReturnType, APInt::getSignedMaxValue(Width)); + break; + } + + switch (IID) { + case Intrinsic::aarch64_sve_andv: + case Intrinsic::aarch64_sve_orv: + case Intrinsic::aarch64_sve_smaxv: + case Intrinsic::aarch64_sve_sminv: + case Intrinsic::aarch64_sve_umaxv: + case Intrinsic::aarch64_sve_uminv: + // sve_reduce_##(all, splat(X)) ==> X + if (C0 && C0->isAllOnesValue()) { + if (Value *SplatVal = getSplatValue(Op1)) { + assert(SplatVal->getType() == ReturnType && "Unexpected result type!"); + return SplatVal; + } + } + break; + case Intrinsic::aarch64_sve_eorv: + // sve_reduce_xor(all, splat(X)) ==> 0 + if (C0 && C0->isAllOnesValue()) + return ConstantInt::get(ReturnType, 0); + break; + } + + return nullptr; +} + Value *llvm::simplifyBinaryIntrinsic(Intrinsic::ID IID, Type *ReturnType, Value *Op0, Value *Op1, const SimplifyQuery &Q, @@ -7033,6 +7090,17 @@ Value *llvm::simplifyBinaryIntrinsic(Intrinsic::ID IID, Type *ReturnType, break; } + + case Intrinsic::aarch64_sve_andv: + case Intrinsic::aarch64_sve_eorv: + case Intrinsic::aarch64_sve_orv: + case Intrinsic::aarch64_sve_saddv: + case Intrinsic::aarch64_sve_smaxv: + case Intrinsic::aarch64_sve_sminv: + case Intrinsic::aarch64_sve_uaddv: + case Intrinsic::aarch64_sve_umaxv: + case Intrinsic::aarch64_sve_uminv: + return simplifySVEIntReduction(IID, ReturnType, Op0, Op1); default: break; } diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp index cbce8bd736102..a3aa5e9571657 100644 --- a/llvm/lib/IR/Constants.cpp +++ b/llvm/lib/IR/Constants.cpp @@ -183,6 +183,23 @@ bool Constant::isMinSignedValue() const { return false; } +bool Constant::isMaxSignedValue() const { + // Check for INT_MAX integers + if (const ConstantInt *CI = dyn_cast(this)) + return CI->isMaxValue(/*isSigned=*/true); + + // Check for FP which are bitcasted from INT_MAX integers + if (const ConstantFP *CFP = dyn_cast(this)) + return CFP->getValueAPF().bitcastToAPInt().isMaxSignedValue(); + + // Check for splats of INT_MAX values. + if (getType()->isVectorTy()) + if (const auto *SplatVal = getSplatValue()) + return SplatVal->isMaxSignedValue(); + + return false; +} + bool Constant::isNotMinSignedValue() const { // Check for INT_MIN integers if (const ConstantInt *CI = dyn_cast(this)) diff --git a/llvm/test/Transforms/InstSimplify/AArch64/aarch64-sve-reductions.ll b/llvm/test/Transforms/InstSimplify/AArch64/aarch64-sve-reductions.ll new file mode 100644 index 0000000000000..a54d6044d04b1 --- /dev/null +++ b/llvm/test/Transforms/InstSimplify/AArch64/aarch64-sve-reductions.ll @@ -0,0 +1,912 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 +; RUN: opt -S -passes=instsimplify < %s | FileCheck %s + +target triple = "aarch64-unknown-linux-gnu" + +; +; ANDV +; + +define i8 @andv_i8_no_active( %a) #0 { +; CHECK-LABEL: define i8 @andv_i8_no_active( +; CHECK-SAME: [[A:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: ret i8 -1 +; + %out = call i8 @llvm.aarch64.sve.andv.nxv16i8( zeroinitializer, %a) + ret i8 %out +} + +define i8 @andv_i8_splat_neutral_val( %pg) #0 { +; CHECK-LABEL: define i8 @andv_i8_splat_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i8 -1 +; + %out = call i8 @llvm.aarch64.sve.andv.nxv16i8( %pg, splat(i8 -1)) + ret i8 %out +} + +define i8 @andv_i8_splat_non_neutral_val( %pg) #0 { +; CHECK-LABEL: define i8 @andv_i8_splat_non_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[OUT:%.*]] = call i8 @llvm.aarch64.sve.andv.nxv16i8( [[PG]], zeroinitializer) +; CHECK-NEXT: ret i8 [[OUT]] +; + %out = call i8 @llvm.aarch64.sve.andv.nxv16i8( %pg, zeroinitializer) + ret i8 %out +} + +define i8 @andv_i8_all_active_splat(i8 %a) #0 { +; CHECK-LABEL: define i8 @andv_i8_all_active_splat( +; CHECK-SAME: i8 [[A:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i8 [[A]] +; + %a.insert = insertelement poison, i8 %a, i8 0 + %a.splat = shufflevector %a.insert, poison, zeroinitializer + %out = call i8 @llvm.aarch64.sve.andv.nxv16i8( splat (i1 true), %a.splat) + ret i8 %out +} + +define i16 @andv_i16_splat_neutral_val( %pg) #0 { +; CHECK-LABEL: define i16 @andv_i16_splat_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i16 -1 +; + %out = call i16 @llvm.aarch64.sve.andv.nxv8i16( %pg, splat(i16 -1)) + ret i16 %out +} + +define i16 @andv_i16_splat_non_neutral_val( %pg) #0 { +; CHECK-LABEL: define i16 @andv_i16_splat_non_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[OUT:%.*]] = call i16 @llvm.aarch64.sve.andv.nxv8i16( [[PG]], zeroinitializer) +; CHECK-NEXT: ret i16 [[OUT]] +; + %out = call i16 @llvm.aarch64.sve.andv.nxv8i16( %pg, zeroinitializer) + ret i16 %out +} + +define i32 @andv_i32_splat_neutral_val( %pg) #0 { +; CHECK-LABEL: define i32 @andv_i32_splat_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i32 -1 +; + %out = call i32 @llvm.aarch64.sve.andv.nxv4i32( %pg, splat(i32 -1)) + ret i32 %out +} + +define i32 @andv_i32_splat_non_neutral_val( %pg) #0 { +; CHECK-LABEL: define i32 @andv_i32_splat_non_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[OUT:%.*]] = call i32 @llvm.aarch64.sve.andv.nxv4i32( [[PG]], zeroinitializer) +; CHECK-NEXT: ret i32 [[OUT]] +; + %out = call i32 @llvm.aarch64.sve.andv.nxv4i32( %pg, zeroinitializer) + ret i32 %out +} + +define i64 @andv_i64_splat_neutral_val( %pg) #0 { +; CHECK-LABEL: define i64 @andv_i64_splat_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i64 -1 +; + %out = call i64 @llvm.aarch64.sve.andv.nxv2i64( %pg, splat(i64 -1)) + ret i64 %out +} + +define i64 @andv_i64_splat_non_neutral_val( %pg) #0 { +; CHECK-LABEL: define i64 @andv_i64_splat_non_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[OUT:%.*]] = call i64 @llvm.aarch64.sve.andv.nxv2i64( [[PG]], zeroinitializer) +; CHECK-NEXT: ret i64 [[OUT]] +; + %out = call i64 @llvm.aarch64.sve.andv.nxv2i64( %pg, zeroinitializer) + ret i64 %out +} + +; +; EORV +; + +define i8 @eorv_i8_no_active( %a) #0 { +; CHECK-LABEL: define i8 @eorv_i8_no_active( +; CHECK-SAME: [[A:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i8 0 +; + %out = call i8 @llvm.aarch64.sve.eorv.nxv16i8( zeroinitializer, %a) + ret i8 %out +} + +define i8 @eorv_i8_splat_neutral_val( %pg) #0 { +; CHECK-LABEL: define i8 @eorv_i8_splat_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i8 0 +; + %out = call i8 @llvm.aarch64.sve.eorv.nxv16i8( %pg, zeroinitializer) + ret i8 %out +} + +define i8 @eorv_i8_splat_non_neutral_val( %pg) #0 { +; CHECK-LABEL: define i8 @eorv_i8_splat_non_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[OUT:%.*]] = call i8 @llvm.aarch64.sve.eorv.nxv16i8( [[PG]], splat (i8 1)) +; CHECK-NEXT: ret i8 [[OUT]] +; + %out = call i8 @llvm.aarch64.sve.eorv.nxv16i8( %pg, splat(i8 1)) + ret i8 %out +} + +define i8 @eorv_i8_all_active_splat(i8 %a) #0 { +; CHECK-LABEL: define i8 @eorv_i8_all_active_splat( +; CHECK-SAME: i8 [[A:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i8 0 +; + %a.insert = insertelement poison, i8 %a, i8 0 + %a.splat = shufflevector %a.insert, poison, zeroinitializer + %out = call i8 @llvm.aarch64.sve.eorv.nxv16i8( splat (i1 true), %a.splat) + ret i8 %out +} + +define i16 @eorv_i16_splat_neutral_val( %pg) #0 { +; CHECK-LABEL: define i16 @eorv_i16_splat_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i16 0 +; + %out = call i16 @llvm.aarch64.sve.eorv.nxv8i16( %pg, zeroinitializer) + ret i16 %out +} + +define i16 @eorv_i16_splat_non_neutral_val( %pg) #0 { +; CHECK-LABEL: define i16 @eorv_i16_splat_non_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[OUT:%.*]] = call i16 @llvm.aarch64.sve.eorv.nxv8i16( [[PG]], splat (i16 1)) +; CHECK-NEXT: ret i16 [[OUT]] +; + %out = call i16 @llvm.aarch64.sve.eorv.nxv8i16( %pg, splat(i16 1)) + ret i16 %out +} + +define i32 @eorv_i32_splat_neutral_val( %pg) #0 { +; CHECK-LABEL: define i32 @eorv_i32_splat_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i32 0 +; + %out = call i32 @llvm.aarch64.sve.eorv.nxv4i32( %pg, zeroinitializer) + ret i32 %out +} + +define i32 @eorv_i32_splat_non_neutral_val( %pg) #0 { +; CHECK-LABEL: define i32 @eorv_i32_splat_non_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[OUT:%.*]] = call i32 @llvm.aarch64.sve.eorv.nxv4i32( [[PG]], splat (i32 1)) +; CHECK-NEXT: ret i32 [[OUT]] +; + %out = call i32 @llvm.aarch64.sve.eorv.nxv4i32( %pg, splat(i32 1)) + ret i32 %out +} + +define i64 @eorv_i64_splat_neutral_val( %pg) #0 { +; CHECK-LABEL: define i64 @eorv_i64_splat_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i64 0 +; + %out = call i64 @llvm.aarch64.sve.eorv.nxv2i64( %pg, zeroinitializer) + ret i64 %out +} + +define i64 @eorv_i64_splat_non_neutral_val( %pg) #0 { +; CHECK-LABEL: define i64 @eorv_i64_splat_non_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[OUT:%.*]] = call i64 @llvm.aarch64.sve.eorv.nxv2i64( [[PG]], splat (i64 1)) +; CHECK-NEXT: ret i64 [[OUT]] +; + %out = call i64 @llvm.aarch64.sve.eorv.nxv2i64( %pg, splat(i64 1)) + ret i64 %out +} + +; +; ORV +; + +define i8 @orv_i8_no_active( %a) #0 { +; CHECK-LABEL: define i8 @orv_i8_no_active( +; CHECK-SAME: [[A:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i8 0 +; + %out = call i8 @llvm.aarch64.sve.orv.nxv16i8( zeroinitializer, %a) + ret i8 %out +} + +define i8 @orv_i8_splat_neutral_val( %pg) #0 { +; CHECK-LABEL: define i8 @orv_i8_splat_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i8 0 +; + %out = call i8 @llvm.aarch64.sve.orv.nxv16i8( %pg, zeroinitializer) + ret i8 %out +} + +define i8 @orv_i8_splat_non_neutral_val( %pg) #0 { +; CHECK-LABEL: define i8 @orv_i8_splat_non_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[OUT:%.*]] = call i8 @llvm.aarch64.sve.orv.nxv16i8( [[PG]], splat (i8 1)) +; CHECK-NEXT: ret i8 [[OUT]] +; + %out = call i8 @llvm.aarch64.sve.orv.nxv16i8( %pg, splat(i8 1)) + ret i8 %out +} + +define i8 @orv_i8_all_active_splat(i8 %a) #0 { +; CHECK-LABEL: define i8 @orv_i8_all_active_splat( +; CHECK-SAME: i8 [[A:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i8 [[A]] +; + %a.insert = insertelement poison, i8 %a, i8 0 + %a.splat = shufflevector %a.insert, poison, zeroinitializer + %out = call i8 @llvm.aarch64.sve.orv.nxv16i8( splat (i1 true), %a.splat) + ret i8 %out +} + +define i16 @orv_i16_splat_neutral_val( %pg) #0 { +; CHECK-LABEL: define i16 @orv_i16_splat_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i16 0 +; + %out = call i16 @llvm.aarch64.sve.orv.nxv8i16( %pg, zeroinitializer) + ret i16 %out +} + +define i16 @orv_i16_splat_non_neutral_val( %pg) #0 { +; CHECK-LABEL: define i16 @orv_i16_splat_non_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[OUT:%.*]] = call i16 @llvm.aarch64.sve.orv.nxv8i16( [[PG]], splat (i16 1)) +; CHECK-NEXT: ret i16 [[OUT]] +; + %out = call i16 @llvm.aarch64.sve.orv.nxv8i16( %pg, splat(i16 1)) + ret i16 %out +} + +define i32 @orv_i32_splat_neutral_val( %pg) #0 { +; CHECK-LABEL: define i32 @orv_i32_splat_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i32 0 +; + %out = call i32 @llvm.aarch64.sve.orv.nxv4i32( %pg, zeroinitializer) + ret i32 %out +} + +define i32 @orv_i32_splat_non_neutral_val( %pg) #0 { +; CHECK-LABEL: define i32 @orv_i32_splat_non_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[OUT:%.*]] = call i32 @llvm.aarch64.sve.orv.nxv4i32( [[PG]], splat (i32 1)) +; CHECK-NEXT: ret i32 [[OUT]] +; + %out = call i32 @llvm.aarch64.sve.orv.nxv4i32( %pg, splat(i32 1)) + ret i32 %out +} + +define i64 @orv_i64_splat_neutral_val( %pg) #0 { +; CHECK-LABEL: define i64 @orv_i64_splat_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i64 0 +; + %out = call i64 @llvm.aarch64.sve.orv.nxv2i64( %pg, zeroinitializer) + ret i64 %out +} + +define i64 @orv_i64_splat_non_neutral_val( %pg) #0 { +; CHECK-LABEL: define i64 @orv_i64_splat_non_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[OUT:%.*]] = call i64 @llvm.aarch64.sve.orv.nxv2i64( [[PG]], splat (i64 1)) +; CHECK-NEXT: ret i64 [[OUT]] +; + %out = call i64 @llvm.aarch64.sve.orv.nxv2i64( %pg, splat(i64 1)) + ret i64 %out +} + +; +; SADDV +; + +define i64 @saddv_i8_no_active( %a) #0 { +; CHECK-LABEL: define i64 @saddv_i8_no_active( +; CHECK-SAME: [[A:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i64 0 +; + %out = call i64 @llvm.aarch64.sve.saddv.nxv16i8( zeroinitializer, %a) + ret i64 %out +} + +define i64 @saddv_i8_splat_neutral_val( %pg) #0 { +; CHECK-LABEL: define i64 @saddv_i8_splat_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i64 0 +; + %out = call i64 @llvm.aarch64.sve.saddv.nxv16i8( %pg, zeroinitializer) + ret i64 %out +} + +define i64 @saddv_i8_splat_non_neutral_val( %pg) #0 { +; CHECK-LABEL: define i64 @saddv_i8_splat_non_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[OUT:%.*]] = call i64 @llvm.aarch64.sve.saddv.nxv16i8( [[PG]], splat (i8 1)) +; CHECK-NEXT: ret i64 [[OUT]] +; + %out = call i64 @llvm.aarch64.sve.saddv.nxv16i8( %pg, splat(i8 1)) + ret i64 %out +} + +define i64 @saddv_i8_all_active_splat(i8 %a) #0 { +; CHECK-LABEL: define i64 @saddv_i8_all_active_splat( +; CHECK-SAME: i8 [[A:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[A_INSERT:%.*]] = insertelement poison, i8 [[A]], i8 0 +; CHECK-NEXT: [[A_SPLAT:%.*]] = shufflevector [[A_INSERT]], poison, zeroinitializer +; CHECK-NEXT: [[OUT:%.*]] = call i64 @llvm.aarch64.sve.saddv.nxv16i8( splat (i1 true), [[A_SPLAT]]) +; CHECK-NEXT: ret i64 [[OUT]] +; + %a.insert = insertelement poison, i8 %a, i8 0 + %a.splat = shufflevector %a.insert, poison, zeroinitializer + %out = call i64 @llvm.aarch64.sve.saddv.nxv16i8( splat (i1 true), %a.splat) + ret i64 %out +} + +define i64 @saddv_i16_splat_neutral_val( %pg) #0 { +; CHECK-LABEL: define i64 @saddv_i16_splat_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i64 0 +; + %out = call i64 @llvm.aarch64.sve.saddv.nxv8i16( %pg, zeroinitializer) + ret i64 %out +} + +define i64 @saddv_i16_splat_non_neutral_val( %pg) #0 { +; CHECK-LABEL: define i64 @saddv_i16_splat_non_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[OUT:%.*]] = call i64 @llvm.aarch64.sve.saddv.nxv8i16( [[PG]], splat (i16 1)) +; CHECK-NEXT: ret i64 [[OUT]] +; + %out = call i64 @llvm.aarch64.sve.saddv.nxv8i16( %pg, splat(i16 1)) + ret i64 %out +} + +define i64 @saddv_i32_splat_neutral_val( %pg) #0 { +; CHECK-LABEL: define i64 @saddv_i32_splat_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i64 0 +; + %out = call i64 @llvm.aarch64.sve.saddv.nxv4i32( %pg, zeroinitializer) + ret i64 %out +} + +define i64 @saddv_i32_splat_non_neutral_val( %pg) #0 { +; CHECK-LABEL: define i64 @saddv_i32_splat_non_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[OUT:%.*]] = call i64 @llvm.aarch64.sve.saddv.nxv4i32( [[PG]], splat (i32 1)) +; CHECK-NEXT: ret i64 [[OUT]] +; + %out = call i64 @llvm.aarch64.sve.saddv.nxv4i32( %pg, splat(i32 1)) + ret i64 %out +} + +define i64 @saddv_i64_splat_neutral_val( %pg) #0 { +; CHECK-LABEL: define i64 @saddv_i64_splat_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i64 0 +; + %out = call i64 @llvm.aarch64.sve.saddv.nxv2i64( %pg, zeroinitializer) + ret i64 %out +} + +define i64 @saddv_i64_splat_non_neutral_val( %pg) #0 { +; CHECK-LABEL: define i64 @saddv_i64_splat_non_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[OUT:%.*]] = call i64 @llvm.aarch64.sve.saddv.nxv2i64( [[PG]], splat (i64 1)) +; CHECK-NEXT: ret i64 [[OUT]] +; + %out = call i64 @llvm.aarch64.sve.saddv.nxv2i64( %pg, splat(i64 1)) + ret i64 %out +} + +; +; SMAXV +; + +define i8 @smaxv_i8_no_active( %a) #0 { +; CHECK-LABEL: define i8 @smaxv_i8_no_active( +; CHECK-SAME: [[A:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i8 -128 +; + %out = call i8 @llvm.aarch64.sve.smaxv.nxv16i8( zeroinitializer, %a) + ret i8 %out +} + +define i8 @smaxv_i8_splat_neutral_val( %pg) #0 { +; CHECK-LABEL: define i8 @smaxv_i8_splat_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i8 -128 +; + %out = call i8 @llvm.aarch64.sve.smaxv.nxv16i8( %pg, splat(i8 -128)) + ret i8 %out +} + +define i8 @smaxv_i8_splat_non_neutral_val( %pg) #0 { +; CHECK-LABEL: define i8 @smaxv_i8_splat_non_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[OUT:%.*]] = call i8 @llvm.aarch64.sve.smaxv.nxv16i8( [[PG]], zeroinitializer) +; CHECK-NEXT: ret i8 [[OUT]] +; + %out = call i8 @llvm.aarch64.sve.smaxv.nxv16i8( %pg, zeroinitializer) + ret i8 %out +} + +define i8 @smaxv_i8_all_active_splat(i8 %a) #0 { +; CHECK-LABEL: define i8 @smaxv_i8_all_active_splat( +; CHECK-SAME: i8 [[A:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i8 [[A]] +; + %a.insert = insertelement poison, i8 %a, i8 0 + %a.splat = shufflevector %a.insert, poison, zeroinitializer + %out = call i8 @llvm.aarch64.sve.smaxv.nxv16i8( splat (i1 true), %a.splat) + ret i8 %out +} + +define i16 @smaxv_i16_splat_neutral_val( %pg) #0 { +; CHECK-LABEL: define i16 @smaxv_i16_splat_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i16 -32768 +; + %out = call i16 @llvm.aarch64.sve.smaxv.nxv8i16( %pg, splat(i16 -32768)) + ret i16 %out +} + +define i16 @smaxv_i16_splat_non_neutral_val( %pg) #0 { +; CHECK-LABEL: define i16 @smaxv_i16_splat_non_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[OUT:%.*]] = call i16 @llvm.aarch64.sve.smaxv.nxv8i16( [[PG]], zeroinitializer) +; CHECK-NEXT: ret i16 [[OUT]] +; + %out = call i16 @llvm.aarch64.sve.smaxv.nxv8i16( %pg, zeroinitializer) + ret i16 %out +} + +define i32 @smaxv_i32_splat_neutral_val( %pg) #0 { +; CHECK-LABEL: define i32 @smaxv_i32_splat_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i32 -2147483648 +; + %out = call i32 @llvm.aarch64.sve.smaxv.nxv4i32( %pg, splat(i32 -2147483648)) + ret i32 %out +} + +define i32 @smaxv_i32_splat_non_neutral_val( %pg) #0 { +; CHECK-LABEL: define i32 @smaxv_i32_splat_non_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[OUT:%.*]] = call i32 @llvm.aarch64.sve.smaxv.nxv4i32( [[PG]], zeroinitializer) +; CHECK-NEXT: ret i32 [[OUT]] +; + %out = call i32 @llvm.aarch64.sve.smaxv.nxv4i32( %pg, zeroinitializer) + ret i32 %out +} + +define i64 @smaxv_i64_splat_neutral_val( %pg) #0 { +; CHECK-LABEL: define i64 @smaxv_i64_splat_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i64 -9223372036854775808 +; + %out = call i64 @llvm.aarch64.sve.smaxv.nxv2i64( %pg, splat(i64 -9223372036854775808)) + ret i64 %out +} + +define i64 @smaxv_i64_splat_non_neutral_val( %pg) #0 { +; CHECK-LABEL: define i64 @smaxv_i64_splat_non_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[OUT:%.*]] = call i64 @llvm.aarch64.sve.smaxv.nxv2i64( [[PG]], zeroinitializer) +; CHECK-NEXT: ret i64 [[OUT]] +; + %out = call i64 @llvm.aarch64.sve.smaxv.nxv2i64( %pg, zeroinitializer) + ret i64 %out +} + +; +; SMINV +; + +define i8 @sminv_i8_no_active( %a) #0 { +; CHECK-LABEL: define i8 @sminv_i8_no_active( +; CHECK-SAME: [[A:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i8 127 +; + %out = call i8 @llvm.aarch64.sve.sminv.nxv16i8( zeroinitializer, %a) + ret i8 %out +} + +define i8 @sminv_i8_splat_neutral_val( %pg) #0 { +; CHECK-LABEL: define i8 @sminv_i8_splat_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i8 127 +; + %out = call i8 @llvm.aarch64.sve.sminv.nxv16i8( %pg, splat(i8 127)) + ret i8 %out +} + +define i8 @sminv_i8_splat_non_neutral_val( %pg) #0 { +; CHECK-LABEL: define i8 @sminv_i8_splat_non_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[OUT:%.*]] = call i8 @llvm.aarch64.sve.sminv.nxv16i8( [[PG]], zeroinitializer) +; CHECK-NEXT: ret i8 [[OUT]] +; + %out = call i8 @llvm.aarch64.sve.sminv.nxv16i8( %pg, zeroinitializer) + ret i8 %out +} + +define i8 @sminv_i8_all_active_splat(i8 %a) #0 { +; CHECK-LABEL: define i8 @sminv_i8_all_active_splat( +; CHECK-SAME: i8 [[A:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i8 [[A]] +; + %a.insert = insertelement poison, i8 %a, i8 0 + %a.splat = shufflevector %a.insert, poison, zeroinitializer + %out = call i8 @llvm.aarch64.sve.sminv.nxv16i8( splat (i1 true), %a.splat) + ret i8 %out +} + +define i16 @sminv_i16_splat_neutral_val( %pg) #0 { +; CHECK-LABEL: define i16 @sminv_i16_splat_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i16 32767 +; + %out = call i16 @llvm.aarch64.sve.sminv.nxv8i16( %pg, splat(i16 32767)) + ret i16 %out +} + +define i16 @sminv_i16_splat_non_neutral_val( %pg) #0 { +; CHECK-LABEL: define i16 @sminv_i16_splat_non_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[OUT:%.*]] = call i16 @llvm.aarch64.sve.sminv.nxv8i16( [[PG]], zeroinitializer) +; CHECK-NEXT: ret i16 [[OUT]] +; + %out = call i16 @llvm.aarch64.sve.sminv.nxv8i16( %pg, zeroinitializer) + ret i16 %out +} + +define i32 @sminv_i32_splat_neutral_val( %pg) #0 { +; CHECK-LABEL: define i32 @sminv_i32_splat_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i32 2147483647 +; + %out = call i32 @llvm.aarch64.sve.sminv.nxv4i32( %pg, splat(i32 2147483647)) + ret i32 %out +} + +define i32 @sminv_i32_splat_non_neutral_val( %pg) #0 { +; CHECK-LABEL: define i32 @sminv_i32_splat_non_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[OUT:%.*]] = call i32 @llvm.aarch64.sve.sminv.nxv4i32( [[PG]], zeroinitializer) +; CHECK-NEXT: ret i32 [[OUT]] +; + %out = call i32 @llvm.aarch64.sve.sminv.nxv4i32( %pg, zeroinitializer) + ret i32 %out +} + +define i64 @sminv_i64_splat_neutral_val( %pg) #0 { +; CHECK-LABEL: define i64 @sminv_i64_splat_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i64 9223372036854775807 +; + %out = call i64 @llvm.aarch64.sve.sminv.nxv2i64( %pg, splat(i64 9223372036854775807)) + ret i64 %out +} + +define i64 @sminv_i64_splat_non_neutral_val( %pg) #0 { +; CHECK-LABEL: define i64 @sminv_i64_splat_non_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[OUT:%.*]] = call i64 @llvm.aarch64.sve.sminv.nxv2i64( [[PG]], zeroinitializer) +; CHECK-NEXT: ret i64 [[OUT]] +; + %out = call i64 @llvm.aarch64.sve.sminv.nxv2i64( %pg, zeroinitializer) + ret i64 %out +} + +; +; UADDV +; + +define i64 @uaddv_i8_no_active( %a) #0 { +; CHECK-LABEL: define i64 @uaddv_i8_no_active( +; CHECK-SAME: [[A:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i64 0 +; + %out = call i64 @llvm.aarch64.sve.uaddv.nxv16i8( zeroinitializer, %a) + ret i64 %out +} + +define i64 @uaddv_i8_splat_neutral_val( %pg) #0 { +; CHECK-LABEL: define i64 @uaddv_i8_splat_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i64 0 +; + %out = call i64 @llvm.aarch64.sve.uaddv.nxv16i8( %pg, zeroinitializer) + ret i64 %out +} + +define i64 @uaddv_i8_splat_non_neutral_val( %pg) #0 { +; CHECK-LABEL: define i64 @uaddv_i8_splat_non_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[OUT:%.*]] = call i64 @llvm.aarch64.sve.uaddv.nxv16i8( [[PG]], splat (i8 1)) +; CHECK-NEXT: ret i64 [[OUT]] +; + %out = call i64 @llvm.aarch64.sve.uaddv.nxv16i8( %pg, splat(i8 1)) + ret i64 %out +} + +define i64 @uaddv_i8_all_active_splat(i8 %a) #0 { +; CHECK-LABEL: define i64 @uaddv_i8_all_active_splat( +; CHECK-SAME: i8 [[A:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[A_INSERT:%.*]] = insertelement poison, i8 [[A]], i8 0 +; CHECK-NEXT: [[A_SPLAT:%.*]] = shufflevector [[A_INSERT]], poison, zeroinitializer +; CHECK-NEXT: [[OUT:%.*]] = call i64 @llvm.aarch64.sve.uaddv.nxv16i8( splat (i1 true), [[A_SPLAT]]) +; CHECK-NEXT: ret i64 [[OUT]] +; + %a.insert = insertelement poison, i8 %a, i8 0 + %a.splat = shufflevector %a.insert, poison, zeroinitializer + %out = call i64 @llvm.aarch64.sve.uaddv.nxv16i8( splat (i1 true), %a.splat) + ret i64 %out +} + +define i64 @uaddv_i16_splat_neutral_val( %pg) #0 { +; CHECK-LABEL: define i64 @uaddv_i16_splat_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i64 0 +; + %out = call i64 @llvm.aarch64.sve.uaddv.nxv8i16( %pg, zeroinitializer) + ret i64 %out +} + +define i64 @uaddv_i16_splat_non_neutral_val( %pg) #0 { +; CHECK-LABEL: define i64 @uaddv_i16_splat_non_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[OUT:%.*]] = call i64 @llvm.aarch64.sve.uaddv.nxv8i16( [[PG]], splat (i16 1)) +; CHECK-NEXT: ret i64 [[OUT]] +; + %out = call i64 @llvm.aarch64.sve.uaddv.nxv8i16( %pg, splat(i16 1)) + ret i64 %out +} + +define i64 @uaddv_i32_splat_neutral_val( %pg) #0 { +; CHECK-LABEL: define i64 @uaddv_i32_splat_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i64 0 +; + %out = call i64 @llvm.aarch64.sve.uaddv.nxv4i32( %pg, zeroinitializer) + ret i64 %out +} + +define i64 @uaddv_i32_splat_non_neutral_val( %pg) #0 { +; CHECK-LABEL: define i64 @uaddv_i32_splat_non_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[OUT:%.*]] = call i64 @llvm.aarch64.sve.uaddv.nxv4i32( [[PG]], splat (i32 1)) +; CHECK-NEXT: ret i64 [[OUT]] +; + %out = call i64 @llvm.aarch64.sve.uaddv.nxv4i32( %pg, splat(i32 1)) + ret i64 %out +} + +define i64 @uaddv_i64_splat_neutral_val( %pg) #0 { +; CHECK-LABEL: define i64 @uaddv_i64_splat_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i64 0 +; + %out = call i64 @llvm.aarch64.sve.uaddv.nxv2i64( %pg, zeroinitializer) + ret i64 %out +} + +define i64 @uaddv_i64_splat_non_neutral_val( %pg) #0 { +; CHECK-LABEL: define i64 @uaddv_i64_splat_non_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[OUT:%.*]] = call i64 @llvm.aarch64.sve.uaddv.nxv2i64( [[PG]], splat (i64 1)) +; CHECK-NEXT: ret i64 [[OUT]] +; + %out = call i64 @llvm.aarch64.sve.uaddv.nxv2i64( %pg, splat(i64 1)) + ret i64 %out +} + +; +; UMAXV +; + +define i8 @umaxv_i8_no_active( %a) #0 { +; CHECK-LABEL: define i8 @umaxv_i8_no_active( +; CHECK-SAME: [[A:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i8 0 +; + %out = call i8 @llvm.aarch64.sve.umaxv.nxv16i8( zeroinitializer, %a) + ret i8 %out +} + +define i8 @umaxv_i8_splat_neutral_val( %pg) #0 { +; CHECK-LABEL: define i8 @umaxv_i8_splat_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i8 0 +; + %out = call i8 @llvm.aarch64.sve.umaxv.nxv16i8( %pg, zeroinitializer) + ret i8 %out +} + +define i8 @umaxv_i8_splat_non_neutral_val( %pg) #0 { +; CHECK-LABEL: define i8 @umaxv_i8_splat_non_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[OUT:%.*]] = call i8 @llvm.aarch64.sve.umaxv.nxv16i8( [[PG]], splat (i8 1)) +; CHECK-NEXT: ret i8 [[OUT]] +; + %out = call i8 @llvm.aarch64.sve.umaxv.nxv16i8( %pg, splat(i8 1)) + ret i8 %out +} + +define i8 @umaxv_i8_all_active_splat(i8 %a) #0 { +; CHECK-LABEL: define i8 @umaxv_i8_all_active_splat( +; CHECK-SAME: i8 [[A:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i8 [[A]] +; + %a.insert = insertelement poison, i8 %a, i8 0 + %a.splat = shufflevector %a.insert, poison, zeroinitializer + %out = call i8 @llvm.aarch64.sve.umaxv.nxv16i8( splat (i1 true), %a.splat) + ret i8 %out +} + +define i16 @umaxv_i16_splat_neutral_val( %pg) #0 { +; CHECK-LABEL: define i16 @umaxv_i16_splat_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i16 0 +; + %out = call i16 @llvm.aarch64.sve.umaxv.nxv8i16( %pg, zeroinitializer) + ret i16 %out +} + +define i16 @umaxv_i16_splat_non_neutral_val( %pg) #0 { +; CHECK-LABEL: define i16 @umaxv_i16_splat_non_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[OUT:%.*]] = call i16 @llvm.aarch64.sve.umaxv.nxv8i16( [[PG]], splat (i16 1)) +; CHECK-NEXT: ret i16 [[OUT]] +; + %out = call i16 @llvm.aarch64.sve.umaxv.nxv8i16( %pg, splat(i16 1)) + ret i16 %out +} + +define i32 @umaxv_i32_splat_neutral_val( %pg) #0 { +; CHECK-LABEL: define i32 @umaxv_i32_splat_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i32 0 +; + %out = call i32 @llvm.aarch64.sve.umaxv.nxv4i32( %pg, zeroinitializer) + ret i32 %out +} + +define i32 @umaxv_i32_splat_non_neutral_val( %pg) #0 { +; CHECK-LABEL: define i32 @umaxv_i32_splat_non_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[OUT:%.*]] = call i32 @llvm.aarch64.sve.umaxv.nxv4i32( [[PG]], splat (i32 1)) +; CHECK-NEXT: ret i32 [[OUT]] +; + %out = call i32 @llvm.aarch64.sve.umaxv.nxv4i32( %pg, splat(i32 1)) + ret i32 %out +} + +define i64 @umaxv_i64_splat_neutral_val( %pg) #0 { +; CHECK-LABEL: define i64 @umaxv_i64_splat_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i64 0 +; + %out = call i64 @llvm.aarch64.sve.umaxv.nxv2i64( %pg, zeroinitializer) + ret i64 %out +} + +define i64 @umaxv_i64_splat_non_neutral_val( %pg) #0 { +; CHECK-LABEL: define i64 @umaxv_i64_splat_non_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[OUT:%.*]] = call i64 @llvm.aarch64.sve.umaxv.nxv2i64( [[PG]], splat (i64 1)) +; CHECK-NEXT: ret i64 [[OUT]] +; + %out = call i64 @llvm.aarch64.sve.umaxv.nxv2i64( %pg, splat(i64 1)) + ret i64 %out +} + +; +; UMINV +; + +define i8 @uminv_i8_no_active( %a) #0 { +; CHECK-LABEL: define i8 @uminv_i8_no_active( +; CHECK-SAME: [[A:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i8 -1 +; + %out = call i8 @llvm.aarch64.sve.uminv.nxv16i8( zeroinitializer, %a) + ret i8 %out +} + +define i8 @uminv_i8_splat_neutral_val( %pg) #0 { +; CHECK-LABEL: define i8 @uminv_i8_splat_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i8 -1 +; + %out = call i8 @llvm.aarch64.sve.uminv.nxv16i8( %pg, splat(i8 -1)) + ret i8 %out +} + +define i8 @uminv_i8_splat_non_neutral_val( %pg) #0 { +; CHECK-LABEL: define i8 @uminv_i8_splat_non_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[OUT:%.*]] = call i8 @llvm.aarch64.sve.uminv.nxv16i8( [[PG]], zeroinitializer) +; CHECK-NEXT: ret i8 [[OUT]] +; + %out = call i8 @llvm.aarch64.sve.uminv.nxv16i8( %pg, zeroinitializer) + ret i8 %out +} + +define i8 @uminv_i8_all_active_splat(i8 %a) #0 { +; CHECK-LABEL: define i8 @uminv_i8_all_active_splat( +; CHECK-SAME: i8 [[A:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i8 [[A]] +; + %a.insert = insertelement poison, i8 %a, i8 0 + %a.splat = shufflevector %a.insert, poison, zeroinitializer + %out = call i8 @llvm.aarch64.sve.uminv.nxv16i8( splat (i1 true), %a.splat) + ret i8 %out +} + +define i16 @uminv_i16_splat_neutral_val( %pg) #0 { +; CHECK-LABEL: define i16 @uminv_i16_splat_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i16 -1 +; + %out = call i16 @llvm.aarch64.sve.uminv.nxv8i16( %pg, splat(i16 -1)) + ret i16 %out +} + +define i16 @uminv_i16_splat_non_neutral_val( %pg) #0 { +; CHECK-LABEL: define i16 @uminv_i16_splat_non_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[OUT:%.*]] = call i16 @llvm.aarch64.sve.uminv.nxv8i16( [[PG]], zeroinitializer) +; CHECK-NEXT: ret i16 [[OUT]] +; + %out = call i16 @llvm.aarch64.sve.uminv.nxv8i16( %pg, zeroinitializer) + ret i16 %out +} + +define i32 @uminv_i32_splat_neutral_val( %pg) #0 { +; CHECK-LABEL: define i32 @uminv_i32_splat_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i32 -1 +; + %out = call i32 @llvm.aarch64.sve.uminv.nxv4i32( %pg, splat(i32 -1)) + ret i32 %out +} + +define i32 @uminv_i32_splat_non_neutral_val( %pg) #0 { +; CHECK-LABEL: define i32 @uminv_i32_splat_non_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[OUT:%.*]] = call i32 @llvm.aarch64.sve.uminv.nxv4i32( [[PG]], zeroinitializer) +; CHECK-NEXT: ret i32 [[OUT]] +; + %out = call i32 @llvm.aarch64.sve.uminv.nxv4i32( %pg, zeroinitializer) + ret i32 %out +} + +define i64 @uminv_i64_splat_neutral_val( %pg) #0 { +; CHECK-LABEL: define i64 @uminv_i64_splat_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i64 -1 +; + %out = call i64 @llvm.aarch64.sve.uminv.nxv2i64( %pg, splat(i64 -1)) + ret i64 %out +} + +define i64 @uminv_i64_splat_non_neutral_val( %pg) #0 { +; CHECK-LABEL: define i64 @uminv_i64_splat_non_neutral_val( +; CHECK-SAME: [[PG:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[OUT:%.*]] = call i64 @llvm.aarch64.sve.uminv.nxv2i64( [[PG]], zeroinitializer) +; CHECK-NEXT: ret i64 [[OUT]] +; + %out = call i64 @llvm.aarch64.sve.uminv.nxv2i64( %pg, zeroinitializer) + ret i64 %out +} + +attributes #0 = { "target-features"="+sve" } diff --git a/llvm/test/Transforms/InstSimplify/AArch64/lit.local.cfg b/llvm/test/Transforms/InstSimplify/AArch64/lit.local.cfg new file mode 100644 index 0000000000000..10d4a0e953ed4 --- /dev/null +++ b/llvm/test/Transforms/InstSimplify/AArch64/lit.local.cfg @@ -0,0 +1,2 @@ +if not "AArch64" in config.root.targets: + config.unsupported = True