Index: llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp +++ llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp @@ -766,6 +766,28 @@ return None; } +static Optional instCombineSVEUnpack(InstCombiner &IC, + IntrinsicInst &II) { + IRBuilder<> Builder(II.getContext()); + Builder.SetInsertPoint(&II); + Value *UnpackArg = II.getArgOperand(0); + auto *RetTy = cast(II.getType()); + bool IsSigned = II.getIntrinsicID() == Intrinsic::aarch64_sve_sunpkhi || + II.getIntrinsicID() == Intrinsic::aarch64_sve_sunpklo; + + // Hi = uunpkhi(splat(X)) --> Hi = splat(extend(X)) + // Lo = uunpklo(splat(X)) --> Lo = splat(extend(X)) + if (auto *ScalarArg = getSplatValue(UnpackArg)) { + ScalarArg = + Builder.CreateIntCast(ScalarArg, RetTy->getScalarType(), IsSigned); + Value *NewVal = + Builder.CreateVectorSplat(RetTy->getElementCount(), ScalarArg); + NewVal->takeName(&II); + return IC.replaceInstUsesWith(II, NewVal); + } + + return None; +} static Optional instCombineSVETBL(InstCombiner &IC, IntrinsicInst &II) { auto *OpVal = II.getOperand(0); @@ -831,6 +853,11 @@ return instCombineSVEVectorMul(IC, II); case Intrinsic::aarch64_sve_tbl: return instCombineSVETBL(IC, II); + case Intrinsic::aarch64_sve_uunpkhi: + case Intrinsic::aarch64_sve_uunpklo: + case Intrinsic::aarch64_sve_sunpkhi: + case Intrinsic::aarch64_sve_sunpklo: + return instCombineSVEUnpack(IC, II); } return None; Index: llvm/test/Transforms/InstCombine/AArch64/sve-intrinsic-opts-unpkhi-unpklo.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/InstCombine/AArch64/sve-intrinsic-opts-unpkhi-unpklo.ll @@ -0,0 +1,63 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -S -instcombine < %s | FileCheck %s + +target triple = "aarch64" + +define @uunpkhi_splat(i16 %a) #0 { +; CHECK-LABEL: @uunpkhi_splat( +; CHECK-NEXT: [[TMP1:%.*]] = zext i16 [[A:%.*]] to i32 +; CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement poison, i32 [[TMP1]], i32 0 +; CHECK-NEXT: [[UNPACK:%.*]] = shufflevector [[DOTSPLATINSERT]], poison, zeroinitializer +; CHECK-NEXT: ret [[UNPACK]] +; + %splat_insert = insertelement poison, i16 %a, i32 0 + %splat = shufflevector %splat_insert, poison, zeroinitializer + %unpack = tail call @llvm.aarch64.sve.uunpkhi.nxv8i16( %splat) + ret %unpack +} + +define @uunpklo_splat(i16 %a) #0 { +; CHECK-LABEL: @uunpklo_splat( +; CHECK-NEXT: [[TMP1:%.*]] = zext i16 [[A:%.*]] to i32 +; CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement poison, i32 [[TMP1]], i32 0 +; CHECK-NEXT: [[UNPACK:%.*]] = shufflevector [[DOTSPLATINSERT]], poison, zeroinitializer +; CHECK-NEXT: ret [[UNPACK]] +; + %splat_insert = insertelement poison, i16 %a, i32 0 + %splat = shufflevector %splat_insert, poison, zeroinitializer + %unpack = tail call @llvm.aarch64.sve.uunpklo.nxv8i16( %splat) + ret %unpack +} + +define @sunpkhi_splat(i16 %a) #0 { +; CHECK-LABEL: @sunpkhi_splat( +; CHECK-NEXT: [[TMP1:%.*]] = sext i16 [[A:%.*]] to i32 +; CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement poison, i32 [[TMP1]], i32 0 +; CHECK-NEXT: [[UNPACK:%.*]] = shufflevector [[DOTSPLATINSERT]], poison, zeroinitializer +; CHECK-NEXT: ret [[UNPACK]] +; + %splat_insert = insertelement poison, i16 %a, i32 0 + %splat = shufflevector %splat_insert, poison, zeroinitializer + %unpack = tail call @llvm.aarch64.sve.sunpkhi.nxv8i16( %splat) + ret %unpack +} + +define @sunpklo_splat(i16 %a) #0 { +; CHECK-LABEL: @sunpklo_splat( +; CHECK-NEXT: [[TMP1:%.*]] = sext i16 [[A:%.*]] to i32 +; CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement poison, i32 [[TMP1]], i32 0 +; CHECK-NEXT: [[UNPACK:%.*]] = shufflevector [[DOTSPLATINSERT]], poison, zeroinitializer +; CHECK-NEXT: ret [[UNPACK]] +; + %splat_insert = insertelement poison, i16 %a, i32 0 + %splat = shufflevector %splat_insert, poison, zeroinitializer + %unpack = tail call @llvm.aarch64.sve.sunpklo.nxv8i16( %splat) + ret %unpack +} + +declare @llvm.aarch64.sve.uunpkhi.nxv8i16() +declare @llvm.aarch64.sve.uunpklo.nxv8i16() +declare @llvm.aarch64.sve.sunpkhi.nxv8i16() +declare @llvm.aarch64.sve.sunpklo.nxv8i16() + +attributes #0 = { "target-features"="+sve" }