diff --git a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp --- a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp @@ -1022,6 +1022,32 @@ return None; } +static Optional instCombineSVESplatSDIV(InstCombiner &IC, + IntrinsicInst &II) { + IRBuilder<> Builder(II.getContext()); + Builder.SetInsertPoint(&II); + + auto SplatVec = II.getOperand(2); + if (!isSplatValue(SplatVec)) + return None; + + Value *SplattedValue = getSplatValue(SplatVec); + ConstantInt *SplattedConstantInt = dyn_cast(SplattedValue); + if (!SplattedConstantInt) + return None; + + APInt SplattedAPInt = SplattedConstantInt->getValue(); + + if (!SplattedAPInt.isPowerOf2()) + return None; + + auto ASRD = Builder.CreateIntrinsic( + Intrinsic::aarch64_sve_asrd, {II.getType()}, + {II.getOperand(0), II.getOperand(1), + ConstantInt::get(SplattedValue->getType(), SplattedAPInt.logBase2())}); + return IC.replaceInstUsesWith(II, ASRD); +} + Optional AArch64TTIImpl::instCombineIntrinsic(InstCombiner &IC, IntrinsicInst &II) const { @@ -1082,6 +1108,8 @@ return instCombineSVELD1(IC, II, DL); case Intrinsic::aarch64_sve_st1: return instCombineSVEST1(IC, II, DL); + case Intrinsic::aarch64_sve_sdiv: + return instCombineSVESplatSDIV(IC, II); } return None; diff --git a/llvm/test/Transforms/InstCombine/AArch64/sve-intrinsic-sdiv.ll b/llvm/test/Transforms/InstCombine/AArch64/sve-intrinsic-sdiv.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/AArch64/sve-intrinsic-sdiv.ll @@ -0,0 +1,44 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -S -instcombine < %s | FileCheck %s + +target triple = "aarch64-unknown-linux-gnu" + +define @sdiv_i32( %a, %pg) #0 { +; CHECK-LABEL: @sdiv_i32( +; CHECK-NEXT: [[TMP1:%.*]] = call @llvm.aarch64.sve.asrd.nxv4i32( [[PG:%.*]], [[A:%.*]], i32 23) +; CHECK-NEXT: ret [[TMP1]] +; + %out = call @llvm.aarch64.sve.sdiv.nxv4i32( %pg, %a, shufflevector ( insertelement ( poison, i32 8388608, i32 0), poison, zeroinitializer)) + ret %out +} + +define @sdiv_i32_not_base2( %a, %pg) #0 { +; CHECK-LABEL: @sdiv_i32_not_base2( +; CHECK-NEXT: [[OUT:%.*]] = call @llvm.aarch64.sve.sdiv.nxv4i32( [[PG:%.*]], [[A:%.*]], shufflevector ( insertelement ( poison, i32 8388607, i32 0), poison, zeroinitializer)) +; CHECK-NEXT: ret [[OUT]] +; + %out = call @llvm.aarch64.sve.sdiv.nxv4i32( %pg, %a, shufflevector ( insertelement ( poison, i32 8388607, i32 0), poison, zeroinitializer)) + ret %out +} + +define @sdiv_i32_not_zero( %a, %pg) #0 { +; CHECK-LABEL: @sdiv_i32_not_zero( +; CHECK-NEXT: [[OUT:%.*]] = call @llvm.aarch64.sve.sdiv.nxv4i32( [[PG:%.*]], [[A:%.*]], zeroinitializer) +; CHECK-NEXT: ret [[OUT]] +; + %out = call @llvm.aarch64.sve.sdiv.nxv4i32( %pg, %a, shufflevector ( insertelement ( poison, i32 0, i32 0), poison, zeroinitializer)) + ret %out +} + +define @sdiv_i32_not_neg( %a, %pg) #0 { +; CHECK-LABEL: @sdiv_i32_not_neg( +; CHECK-NEXT: [[OUT:%.*]] = call @llvm.aarch64.sve.sdiv.nxv4i32( [[PG:%.*]], [[A:%.*]], shufflevector ( insertelement ( poison, i32 -8388608, i32 0), poison, zeroinitializer)) +; CHECK-NEXT: ret [[OUT]] +; + %out = call @llvm.aarch64.sve.sdiv.nxv4i32( %pg, %a, shufflevector ( insertelement ( poison, i32 -8388608, i32 0), poison, zeroinitializer)) + ret %out +} + +declare @llvm.aarch64.sve.sdiv.nxv4i32(, , ) + +attributes #0 = { "target-features"="+sve" }