[SVE] Bail from VectorUtils heuristics for scalable vectors

Bail from maskIsAllZeroOrUndef and maskIsAllOneOrUndef prior to iterating over the number of
elements for scalable vectors.

Assert that the mask type is not scalable in possiblyDemandedEltsInMask .

Assert that the types are correct in all three functions.

Reviewed By: efriedma

Differential Revision: https://reviews.llvm.org/D87424
This commit is contained in:
Christopher Tetreault 2020-09-10 11:29:16 -07:00
parent 783e28a508
commit 7ddfd9b3eb
4 changed files with 61 additions and 13 deletions

View File

@ -544,14 +544,14 @@ createSequentialMask(unsigned Start, unsigned NumInts, unsigned NumUndefs);
/// elements, it will be padded with undefs. /// elements, it will be padded with undefs.
Value *concatenateVectors(IRBuilderBase &Builder, ArrayRef<Value *> Vecs); Value *concatenateVectors(IRBuilderBase &Builder, ArrayRef<Value *> Vecs);
/// Given a mask vector of the form <Y x i1>, Return true if all of the /// Given a mask vector of i1, Return true if all of the elements of this
/// elements of this predicate mask are false or undef. That is, return true /// predicate mask are known to be false or undef. That is, return true if all
/// if all lanes can be assumed inactive. /// lanes can be assumed inactive.
bool maskIsAllZeroOrUndef(Value *Mask); bool maskIsAllZeroOrUndef(Value *Mask);
/// Given a mask vector of the form <Y x i1>, Return true if all of the /// Given a mask vector of i1, Return true if all of the elements of this
/// elements of this predicate mask are true or undef. That is, return true /// predicate mask are known to be true or undef. That is, return true if all
/// if all lanes can be assumed active. /// lanes can be assumed active.
bool maskIsAllOneOrUndef(Value *Mask); bool maskIsAllOneOrUndef(Value *Mask);
/// Given a mask vector of the form <Y x i1>, return an APInt (of bitwidth Y) /// Given a mask vector of the form <Y x i1>, return an APInt (of bitwidth Y)

View File

@ -863,11 +863,19 @@ Value *llvm::concatenateVectors(IRBuilderBase &Builder,
} }
bool llvm::maskIsAllZeroOrUndef(Value *Mask) { bool llvm::maskIsAllZeroOrUndef(Value *Mask) {
assert(isa<VectorType>(Mask->getType()) &&
isa<IntegerType>(Mask->getType()->getScalarType()) &&
cast<IntegerType>(Mask->getType()->getScalarType())->getBitWidth() ==
1 &&
"Mask must be a vector of i1");
auto *ConstMask = dyn_cast<Constant>(Mask); auto *ConstMask = dyn_cast<Constant>(Mask);
if (!ConstMask) if (!ConstMask)
return false; return false;
if (ConstMask->isNullValue() || isa<UndefValue>(ConstMask)) if (ConstMask->isNullValue() || isa<UndefValue>(ConstMask))
return true; return true;
if (isa<ScalableVectorType>(ConstMask->getType()))
return false;
for (unsigned for (unsigned
I = 0, I = 0,
E = cast<FixedVectorType>(ConstMask->getType())->getNumElements(); E = cast<FixedVectorType>(ConstMask->getType())->getNumElements();
@ -882,11 +890,19 @@ bool llvm::maskIsAllZeroOrUndef(Value *Mask) {
bool llvm::maskIsAllOneOrUndef(Value *Mask) { bool llvm::maskIsAllOneOrUndef(Value *Mask) {
assert(isa<VectorType>(Mask->getType()) &&
isa<IntegerType>(Mask->getType()->getScalarType()) &&
cast<IntegerType>(Mask->getType()->getScalarType())->getBitWidth() ==
1 &&
"Mask must be a vector of i1");
auto *ConstMask = dyn_cast<Constant>(Mask); auto *ConstMask = dyn_cast<Constant>(Mask);
if (!ConstMask) if (!ConstMask)
return false; return false;
if (ConstMask->isAllOnesValue() || isa<UndefValue>(ConstMask)) if (ConstMask->isAllOnesValue() || isa<UndefValue>(ConstMask))
return true; return true;
if (isa<ScalableVectorType>(ConstMask->getType()))
return false;
for (unsigned for (unsigned
I = 0, I = 0,
E = cast<FixedVectorType>(ConstMask->getType())->getNumElements(); E = cast<FixedVectorType>(ConstMask->getType())->getNumElements();
@ -902,6 +918,11 @@ bool llvm::maskIsAllOneOrUndef(Value *Mask) {
/// TODO: This is a lot like known bits, but for /// TODO: This is a lot like known bits, but for
/// vectors. Is there something we can common this with? /// vectors. Is there something we can common this with?
APInt llvm::possiblyDemandedEltsInMask(Value *Mask) { APInt llvm::possiblyDemandedEltsInMask(Value *Mask) {
assert(isa<FixedVectorType>(Mask->getType()) &&
isa<IntegerType>(Mask->getType()->getScalarType()) &&
cast<IntegerType>(Mask->getType()->getScalarType())->getBitWidth() ==
1 &&
"Mask must be a fixed width vector of i1");
const unsigned VWidth = const unsigned VWidth =
cast<FixedVectorType>(Mask->getType())->getNumElements(); cast<FixedVectorType>(Mask->getType())->getNumElements();

View File

@ -319,11 +319,14 @@ Instruction *InstCombinerImpl::simplifyMaskedStore(IntrinsicInst &II) {
return new StoreInst(II.getArgOperand(0), StorePtr, false, Alignment); return new StoreInst(II.getArgOperand(0), StorePtr, false, Alignment);
} }
if (isa<ScalableVectorType>(ConstMask->getType()))
return nullptr;
// Use masked off lanes to simplify operands via SimplifyDemandedVectorElts // Use masked off lanes to simplify operands via SimplifyDemandedVectorElts
APInt DemandedElts = possiblyDemandedEltsInMask(ConstMask); APInt DemandedElts = possiblyDemandedEltsInMask(ConstMask);
APInt UndefElts(DemandedElts.getBitWidth(), 0); APInt UndefElts(DemandedElts.getBitWidth(), 0);
if (Value *V = SimplifyDemandedVectorElts(II.getOperand(0), if (Value *V =
DemandedElts, UndefElts)) SimplifyDemandedVectorElts(II.getOperand(0), DemandedElts, UndefElts))
return replaceOperand(II, 0, V); return replaceOperand(II, 0, V);
return nullptr; return nullptr;
@ -355,14 +358,17 @@ Instruction *InstCombinerImpl::simplifyMaskedScatter(IntrinsicInst &II) {
if (ConstMask->isNullValue()) if (ConstMask->isNullValue())
return eraseInstFromFunction(II); return eraseInstFromFunction(II);
if (isa<ScalableVectorType>(ConstMask->getType()))
return nullptr;
// Use masked off lanes to simplify operands via SimplifyDemandedVectorElts // Use masked off lanes to simplify operands via SimplifyDemandedVectorElts
APInt DemandedElts = possiblyDemandedEltsInMask(ConstMask); APInt DemandedElts = possiblyDemandedEltsInMask(ConstMask);
APInt UndefElts(DemandedElts.getBitWidth(), 0); APInt UndefElts(DemandedElts.getBitWidth(), 0);
if (Value *V = SimplifyDemandedVectorElts(II.getOperand(0), if (Value *V =
DemandedElts, UndefElts)) SimplifyDemandedVectorElts(II.getOperand(0), DemandedElts, UndefElts))
return replaceOperand(II, 0, V); return replaceOperand(II, 0, V);
if (Value *V = SimplifyDemandedVectorElts(II.getOperand(1), if (Value *V =
DemandedElts, UndefElts)) SimplifyDemandedVectorElts(II.getOperand(1), DemandedElts, UndefElts))
return replaceOperand(II, 1, V); return replaceOperand(II, 1, V);
return nullptr; return nullptr;

View File

@ -0,0 +1,21 @@
; RUN: opt -S -instcombine < %s | FileCheck %s
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
target triple = "aarch64-unknown-linux-gnu"
; This test checks that instcombine does not crash while invoking
; maskIsAllOneOrUndef, maskIsAllZeroOrUndef, or possiblyDemandedEltsInMask.
; CHECK-LABEL: novel_algorithm
; CHECK: unreachable
define void @novel_algorithm() {
entry:
%a = call <vscale x 16 x i8> @llvm.masked.load.nxv16i8.p0nxv16i8(<vscale x 16 x i8>* undef, i32 1, <vscale x 16 x i1> shufflevector (<vscale x 16 x i1> insertelement (<vscale x 16 x i1> undef, i1 true, i32 0), <vscale x 16 x i1> undef, <vscale x 16 x i32> zeroinitializer), <vscale x 16 x i8> undef)
%b = add <vscale x 16 x i8> undef, %a
call void @llvm.masked.store.nxv16i8.p0nxv16i8(<vscale x 16 x i8> %b, <vscale x 16 x i8>* undef, i32 1, <vscale x 16 x i1> shufflevector (<vscale x 16 x i1> insertelement (<vscale x 16 x i1> undef, i1 true, i32 0), <vscale x 16 x i1> undef, <vscale x 16 x i32> zeroinitializer))
unreachable
}
declare <vscale x 16 x i8> @llvm.masked.load.nxv16i8.p0nxv16i8(<vscale x 16 x i8>*, i32 immarg, <vscale x 16 x i1>, <vscale x 16 x i8>)
declare void @llvm.masked.store.nxv16i8.p0nxv16i8(<vscale x 16 x i8>, <vscale x 16 x i8>*, i32 immarg, <vscale x 16 x i1>)