Skip to content

Commit

Permalink
[SVE][InstCombine] Delete redundante sel instructions with ptrue
Browse files Browse the repository at this point in the history
svsel(pture, x, y) => x. depend on D121792
Reviewed By: paulwalker-arm, david-arm
  • Loading branch information
vfdff committed Oct 13, 2023
1 parent 127cf4e commit bf90ffb
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 21 deletions.
41 changes: 23 additions & 18 deletions llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
Expand Up @@ -798,10 +798,31 @@ instCombineConvertFromSVBool(InstCombiner &IC, IntrinsicInst &II) {
return IC.replaceInstUsesWith(II, EarliestReplacement);
}

static bool isAllActivePredicate(Value *Pred) {
// Look through convert.from.svbool(convert.to.svbool(...) chain.
Value *UncastedPred;
if (match(Pred, m_Intrinsic<Intrinsic::aarch64_sve_convert_from_svbool>(
m_Intrinsic<Intrinsic::aarch64_sve_convert_to_svbool>(
m_Value(UncastedPred)))))
// If the predicate has the same or less lanes than the uncasted
// predicate then we know the casting has no effect.
if (cast<ScalableVectorType>(Pred->getType())->getMinNumElements() <=
cast<ScalableVectorType>(UncastedPred->getType())->getMinNumElements())
Pred = UncastedPred;

return match(Pred, m_Intrinsic<Intrinsic::aarch64_sve_ptrue>(
m_ConstantInt<AArch64SVEPredPattern::all>()));
}

static std::optional<Instruction *> instCombineSVESel(InstCombiner &IC,
IntrinsicInst &II) {
auto Select = IC.Builder.CreateSelect(II.getOperand(0), II.getOperand(1),
II.getOperand(2));
// svsel(ptrue, x, y) => x
auto *OpPredicate = II.getOperand(0);
if (isAllActivePredicate(OpPredicate))
return IC.replaceInstUsesWith(II, II.getOperand(1));

auto Select =
IC.Builder.CreateSelect(OpPredicate, II.getOperand(1), II.getOperand(2));
return IC.replaceInstUsesWith(II, Select);
}

Expand Down Expand Up @@ -1200,22 +1221,6 @@ instCombineSVEVectorFuseMulAddSub(InstCombiner &IC, IntrinsicInst &II,
return IC.replaceInstUsesWith(II, Res);
}

static bool isAllActivePredicate(Value *Pred) {
// Look through convert.from.svbool(convert.to.svbool(...) chain.
Value *UncastedPred;
if (match(Pred, m_Intrinsic<Intrinsic::aarch64_sve_convert_from_svbool>(
m_Intrinsic<Intrinsic::aarch64_sve_convert_to_svbool>(
m_Value(UncastedPred)))))
// If the predicate has the same or less lanes than the uncasted
// predicate then we know the casting has no effect.
if (cast<ScalableVectorType>(Pred->getType())->getMinNumElements() <=
cast<ScalableVectorType>(UncastedPred->getType())->getMinNumElements())
Pred = UncastedPred;

return match(Pred, m_Intrinsic<Intrinsic::aarch64_sve_ptrue>(
m_ConstantInt<AArch64SVEPredPattern::all>()));
}

static std::optional<Instruction *>
instCombineSVELD1(InstCombiner &IC, IntrinsicInst &II, const DataLayout &DL) {
Value *Pred = II.getOperand(0);
Expand Down
Expand Up @@ -14,9 +14,7 @@ define <vscale x 4 x i32> @replace_sel_intrinsic(<vscale x 4 x i1> %p, <vscale x

define <vscale x 4 x i32> @sel_ptrue(<vscale x 4 x i32> %a, <vscale x 4 x i32> %b) {
; CHECK-LABEL: @sel_ptrue(
; CHECK-NEXT: [[PRED:%.*]] = call <vscale x 4 x i1> @llvm.aarch64.sve.ptrue.nxv4i1(i32 31)
; CHECK-NEXT: [[RES:%.*]] = select <vscale x 4 x i1> [[PRED]], <vscale x 4 x i32> [[A:%.*]], <vscale x 4 x i32> [[B:%.*]]
; CHECK-NEXT: ret <vscale x 4 x i32> [[RES]]
; CHECK-NEXT: ret <vscale x 4 x i32> [[A:%.*]]
;
%pred = call <vscale x 4 x i1> @llvm.aarch64.sve.ptrue.nxv4i1(i32 31)
%res = call <vscale x 4 x i32> @llvm.aarch64.sve.sel.nxv4i32(<vscale x 4 x i1> %pred, <vscale x 4 x i32> %a, <vscale x 4 x i32> %b)
Expand Down

0 comments on commit bf90ffb

Please sign in to comment.