Skip to content

Commit

Permalink
InstructionSimplify: Relanding r301766
Browse files Browse the repository at this point in the history
Summary:
Re-applying r301766 with a fix to a typo and a regression test.

The log message for r301766 was:
==================================================================================
    InstructionSimplify: Canonicalize shuffle operands. NFC-ish.

    Summary:
     Apply canonicalization rules:
        1. Input vectors with no elements selected from can be replaced with undef.
        2. If only one input vector is constant it shall be the second one.

    This allows constant-folding to cover more ad-hoc simplifications that
    were in place and avoid duplication for RHS and LHS checks.

    There are more rules we may want to add in the future when we see a
    justification. e.g. mask elements that select undef elements can be
    replaced with undef.
==================================================================================

Reviewers: spatel, RKSimon

Reviewed By: spatel

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D32863

llvm-svn: 302373
  • Loading branch information
Zvi Rackover committed May 7, 2017
1 parent ff41150 commit 973ff7c
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 20 deletions.
51 changes: 31 additions & 20 deletions llvm/lib/Analysis/InstructionSimplify.cpp
Expand Up @@ -4094,20 +4094,13 @@ static Value *SimplifyShuffleVectorInst(Value *Op0, Value *Op1, Constant *Mask,
unsigned MaskNumElts = Mask->getType()->getVectorNumElements();
unsigned InVecNumElts = InVecTy->getVectorNumElements();

auto *Op0Const = dyn_cast<Constant>(Op0);
auto *Op1Const = dyn_cast<Constant>(Op1);

// If all operands are constant, constant fold the shuffle.
if (Op0Const && Op1Const)
return ConstantFoldShuffleVectorInstruction(Op0Const, Op1Const, Mask);

SmallVector<int, 32> Indices;
ShuffleVectorInst::getShuffleMask(Mask, Indices);
assert(MaskNumElts == Indices.size() &&
"Size of Indices not same as number of mask elements?");

// If only one of the operands is constant, constant fold the shuffle if the
// mask does not select elements from the variable operand.
// Canonicalization: If mask does not select elements from an input vector,
// replace that input vector with undef.
bool MaskSelects0 = false, MaskSelects1 = false;
for (unsigned i = 0; i != MaskNumElts; ++i) {
if (Indices[i] == -1)
Expand All @@ -4117,23 +4110,41 @@ static Value *SimplifyShuffleVectorInst(Value *Op0, Value *Op1, Constant *Mask,
else
MaskSelects1 = true;
}
if (!MaskSelects0 && Op1Const)
return ConstantFoldShuffleVectorInstruction(UndefValue::get(InVecTy),
Op1Const, Mask);
if (!MaskSelects1 && Op0Const)
return ConstantFoldShuffleVectorInstruction(Op0Const,
UndefValue::get(InVecTy), Mask);
if (!MaskSelects0)
Op0 = UndefValue::get(InVecTy);
if (!MaskSelects1)
Op1 = UndefValue::get(InVecTy);

auto *Op0Const = dyn_cast<Constant>(Op0);
auto *Op1Const = dyn_cast<Constant>(Op1);

// If all operands are constant, constant fold the shuffle.
if (Op0Const && Op1Const)
return ConstantFoldShuffleVectorInstruction(Op0Const, Op1Const, Mask);

// Canonicalization: if only one input vector is constant, it shall be the
// second one.
if (Op0Const && !Op1Const) {
std::swap(Op0, Op1);
for (int &Idx : Indices) {
if (Idx == -1)
continue;
Idx = Idx < (int)InVecNumElts ? Idx + InVecNumElts : Idx - InVecNumElts;
assert(Idx >= 0 && Idx < (int)InVecNumElts * 2 &&
"shufflevector mask index out of range");
}
Mask = ConstantDataVector::get(
Mask->getContext(),
makeArrayRef(reinterpret_cast<uint32_t *>(Indices.data()),
MaskNumElts));
}

// A shuffle of a splat is always the splat itself. Legal if the shuffle's
// value type is same as the input vectors' type.
if (auto *OpShuf = dyn_cast<ShuffleVectorInst>(Op0))
if (!MaskSelects1 && RetTy == InVecTy &&
if (isa<UndefValue>(Op1) && RetTy == InVecTy &&
OpShuf->getMask()->getSplatValue())
return Op0;
if (auto *OpShuf = dyn_cast<ShuffleVectorInst>(Op1))
if (!MaskSelects0 && RetTy == InVecTy &&
OpShuf->getMask()->getSplatValue())
return Op1;

// Don't fold a shuffle with undef mask elements. This may get folded in a
// better way using demanded bits or other analysis.
Expand Down
14 changes: 14 additions & 0 deletions llvm/test/Transforms/InstSimplify/shufflevector.ll
Expand Up @@ -233,3 +233,17 @@ define <8 x i64> @PR30630(<8 x i64> %x) {
ret <8 x i64> %s7
}

; This case covers internal canonicalization of shuffles with one constant input vector.

;FIXME: Another issue exposed here, this whole function could be simplified to:
; ret <2 x float> zeroinitializer
define <2 x float> @PR32872(<2 x float> %x) {
; CHECK-LABEL: @PR32872(
; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <2 x float> [[X:%.*]], <2 x float> zeroinitializer, <4 x i32> <i32 2, i32 2, i32 0, i32 1>
; CHECK-NEXT: [[TMP4:%.*]] = shufflevector <4 x float> zeroinitializer, <4 x float> [[TMP1]], <2 x i32> <i32 4, i32 5>
; CHECK-NEXT: ret <2 x float> [[TMP4]]
;
%tmp1 = shufflevector <2 x float> %x, <2 x float> zeroinitializer, <4 x i32> <i32 2, i32 2, i32 0, i32 1>
%tmp4 = shufflevector <4 x float> zeroinitializer, <4 x float> %tmp1, <2 x i32> <i32 4, i32 5>
ret <2 x float> %tmp4
}

0 comments on commit 973ff7c

Please sign in to comment.