Skip to content

Commit

Permalink
[InstCombine] Bubble vector.reverse of select operands to their result.
Browse files Browse the repository at this point in the history
This mirrors a similar shufflevector transformation so the same
effect is obtained for scalable vectors. The transformation is
only performed when it can be proven the number of resulting
reversals is not increased. By bubbling the reversals from operand
to result this should typically be the case and ideally leads to
back-back shuffles that can be elimitated entirely.

Differential Revision: https://reviews.llvm.org/D139339
  • Loading branch information
paulwalker-arm committed Dec 21, 2022
1 parent 362c52a commit 87c494b
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 44 deletions.
40 changes: 36 additions & 4 deletions llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
Expand Up @@ -19,6 +19,7 @@
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/OverflowInstAnalysis.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/Analysis/VectorUtils.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/ConstantRange.h"
Expand Down Expand Up @@ -2352,6 +2353,41 @@ static Instruction *foldSelectToCopysign(SelectInst &Sel,
}

Instruction *InstCombinerImpl::foldVectorSelect(SelectInst &Sel) {
if (!isa<VectorType>(Sel.getType()))
return nullptr;

Value *Cond = Sel.getCondition();
Value *TVal = Sel.getTrueValue();
Value *FVal = Sel.getFalseValue();
Value *C, *X, *Y;

if (match(Cond, m_VecReverse(m_Value(C)))) {
auto createSelReverse = [&](Value *C, Value *X, Value *Y) {
Value *V = Builder.CreateSelect(C, X, Y, Sel.getName(), &Sel);
if (auto *I = dyn_cast<Instruction>(V))
I->copyIRFlags(&Sel);
Module *M = Sel.getModule();
Function *F = Intrinsic::getDeclaration(
M, Intrinsic::experimental_vector_reverse, V->getType());
return CallInst::Create(F, V);
};

if (match(TVal, m_VecReverse(m_Value(X)))) {
// select rev(C), rev(X), rev(Y) --> rev(select C, X, Y)
if (match(FVal, m_VecReverse(m_Value(Y))) &&
(Cond->hasOneUse() || TVal->hasOneUse() || FVal->hasOneUse()))
return createSelReverse(C, X, Y);

// select rev(C), rev(X), FValSplat --> rev(select C, X, FValSplat)
if ((Cond->hasOneUse() || TVal->hasOneUse()) && isSplatValue(FVal))
return createSelReverse(C, X, FVal);
}
// select rev(C), TValSplat, rev(Y) --> rev(select C, TValSplat, Y)
else if (isSplatValue(TVal) && match(FVal, m_VecReverse(m_Value(Y))) &&
(Cond->hasOneUse() || FVal->hasOneUse()))
return createSelReverse(C, TVal, Y);
}

auto *VecTy = dyn_cast<FixedVectorType>(Sel.getType());
if (!VecTy)
return nullptr;
Expand All @@ -2368,10 +2404,6 @@ Instruction *InstCombinerImpl::foldVectorSelect(SelectInst &Sel) {
// A select of a "select shuffle" with a common operand can be rearranged
// to select followed by "select shuffle". Because of poison, this only works
// in the case of a shuffle with no undefined mask elements.
Value *Cond = Sel.getCondition();
Value *TVal = Sel.getTrueValue();
Value *FVal = Sel.getFalseValue();
Value *X, *Y;
ArrayRef<int> Mask;
if (match(TVal, m_OneUse(m_Shuffle(m_Value(X), m_Value(Y), m_Mask(Mask)))) &&
!is_contained(Mask, UndefMaskElem) &&
Expand Down

0 comments on commit 87c494b

Please sign in to comment.