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 @@ -501,6 +501,10 @@ Value *Vec = II.getArgOperand(1); bool IsAfter = II.getIntrinsicID() == Intrinsic::aarch64_sve_lasta; + // lastX(splat(X)) --> X + if (auto *SplatVal = getSplatValue(Vec)) + return IC.replaceInstUsesWith(II, SplatVal); + auto *C = dyn_cast(Pg); if (IsAfter && C && C->isNullValue()) { // The intrinsic is extracting lane 0 so use an extract instead. diff --git a/llvm/test/Transforms/InstCombine/AArch64/sve-intrinsic-opts-lasta-lastb.ll b/llvm/test/Transforms/InstCombine/AArch64/sve-intrinsic-opts-lasta-lastb.ll --- a/llvm/test/Transforms/InstCombine/AArch64/sve-intrinsic-opts-lasta-lastb.ll +++ b/llvm/test/Transforms/InstCombine/AArch64/sve-intrinsic-opts-lasta-lastb.ll @@ -144,6 +144,25 @@ ret i8 %e } +; Return the splatted value irrespective of the predicate. +define i8 @lasta_splat( %pg, i8 %a) #0 { +; OPT-LABEL: @lasta_splat( +; OPT-NEXT: ret i8 %a + %splat_insert = insertelement poison, i8 %a, i32 0 + %splat = shufflevector %splat_insert, poison, zeroinitializer + %last = tail call i8 @llvm.aarch64.sve.lasta.nxv16i8( %pg, %splat) + ret i8 %last +} + +define i8 @lastb_splat( %pg, i8 %a) #0 { +; OPT-LABEL: @lastb_splat( +; OPT-NEXT: ret i8 %a + %splat_insert = insertelement poison, i8 %a, i32 0 + %splat = shufflevector %splat_insert, poison, zeroinitializer + %last = tail call i8 @llvm.aarch64.sve.lastb.nxv16i8( %pg, %splat) + ret i8 %last +} + declare @llvm.aarch64.sve.ptrue.nxv16i1(i32) declare i8 @llvm.aarch64.sve.lasta.nxv16i8(, ) declare i8 @llvm.aarch64.sve.lastb.nxv16i8(, )