@@ -6560,10 +6560,25 @@ static bool shiftAmountKnownInRange(const Value *ShiftAmount) {
6560
6560
return Safe;
6561
6561
}
6562
6562
6563
- static bool canCreateUndefOrPoison (const Operator *Op, bool PoisonOnly,
6563
+ enum class UndefPoisonKind {
6564
+ PoisonOnly = (1 << 0 ),
6565
+ UndefOnly = (1 << 1 ),
6566
+ UndefOrPoison = PoisonOnly | UndefOnly,
6567
+ };
6568
+
6569
+ static bool includesPoison (UndefPoisonKind Kind) {
6570
+ return (unsigned (Kind) & unsigned (UndefPoisonKind::PoisonOnly)) != 0 ;
6571
+ }
6572
+
6573
+ static bool includesUndef (UndefPoisonKind Kind) {
6574
+ return (unsigned (Kind) & unsigned (UndefPoisonKind::UndefOnly)) != 0 ;
6575
+ }
6576
+
6577
+ static bool canCreateUndefOrPoison (const Operator *Op, UndefPoisonKind Kind,
6564
6578
bool ConsiderFlagsAndMetadata) {
6565
6579
6566
- if (ConsiderFlagsAndMetadata && Op->hasPoisonGeneratingFlagsOrMetadata ())
6580
+ if (ConsiderFlagsAndMetadata && includesPoison (Kind) &&
6581
+ Op->hasPoisonGeneratingFlagsOrMetadata ())
6567
6582
return true ;
6568
6583
6569
6584
unsigned Opcode = Op->getOpcode ();
@@ -6573,7 +6588,7 @@ static bool canCreateUndefOrPoison(const Operator *Op, bool PoisonOnly,
6573
6588
case Instruction::Shl:
6574
6589
case Instruction::AShr:
6575
6590
case Instruction::LShr:
6576
- return !shiftAmountKnownInRange (Op->getOperand (1 ));
6591
+ return includesPoison (Kind) && !shiftAmountKnownInRange (Op->getOperand (1 ));
6577
6592
case Instruction::FPToSI:
6578
6593
case Instruction::FPToUI:
6579
6594
// fptosi/ui yields poison if the resulting value does not fit in the
@@ -6614,7 +6629,8 @@ static bool canCreateUndefOrPoison(const Operator *Op, bool PoisonOnly,
6614
6629
return false ;
6615
6630
case Intrinsic::sshl_sat:
6616
6631
case Intrinsic::ushl_sat:
6617
- return !shiftAmountKnownInRange (II->getArgOperand (1 ));
6632
+ return includesPoison (Kind) &&
6633
+ !shiftAmountKnownInRange (II->getArgOperand (1 ));
6618
6634
case Intrinsic::fma:
6619
6635
case Intrinsic::fmuladd:
6620
6636
case Intrinsic::sqrt:
@@ -6669,15 +6685,16 @@ static bool canCreateUndefOrPoison(const Operator *Op, bool PoisonOnly,
6669
6685
auto *VTy = cast<VectorType>(Op->getOperand (0 )->getType ());
6670
6686
unsigned IdxOp = Op->getOpcode () == Instruction::InsertElement ? 2 : 1 ;
6671
6687
auto *Idx = dyn_cast<ConstantInt>(Op->getOperand (IdxOp));
6672
- if (!Idx || Idx->getValue ().uge (VTy->getElementCount ().getKnownMinValue ()))
6673
- return true ;
6688
+ if (includesPoison (Kind))
6689
+ return !Idx ||
6690
+ Idx->getValue ().uge (VTy->getElementCount ().getKnownMinValue ());
6674
6691
return false ;
6675
6692
}
6676
6693
case Instruction::ShuffleVector: {
6677
6694
ArrayRef<int > Mask = isa<ConstantExpr>(Op)
6678
6695
? cast<ConstantExpr>(Op)->getShuffleMask ()
6679
6696
: cast<ShuffleVectorInst>(Op)->getShuffleMask ();
6680
- return is_contained (Mask, PoisonMaskElem);
6697
+ return includesPoison (Kind) && is_contained (Mask, PoisonMaskElem);
6681
6698
}
6682
6699
case Instruction::FNeg:
6683
6700
case Instruction::PHI:
@@ -6713,17 +6730,17 @@ static bool canCreateUndefOrPoison(const Operator *Op, bool PoisonOnly,
6713
6730
6714
6731
bool llvm::canCreateUndefOrPoison (const Operator *Op,
6715
6732
bool ConsiderFlagsAndMetadata) {
6716
- return ::canCreateUndefOrPoison (Op, /* PoisonOnly= */ false ,
6733
+ return ::canCreateUndefOrPoison (Op, UndefPoisonKind::UndefOrPoison ,
6717
6734
ConsiderFlagsAndMetadata);
6718
6735
}
6719
6736
6720
6737
bool llvm::canCreatePoison (const Operator *Op, bool ConsiderFlagsAndMetadata) {
6721
- return ::canCreateUndefOrPoison (Op, /* PoisonOnly= */ true ,
6738
+ return ::canCreateUndefOrPoison (Op, UndefPoisonKind:: PoisonOnly,
6722
6739
ConsiderFlagsAndMetadata);
6723
6740
}
6724
6741
6725
- static bool directlyImpliesPoison (const Value *ValAssumedPoison,
6726
- const Value *V, unsigned Depth) {
6742
+ static bool directlyImpliesPoison (const Value *ValAssumedPoison, const Value *V,
6743
+ unsigned Depth) {
6727
6744
if (ValAssumedPoison == V)
6728
6745
return true ;
6729
6746
@@ -6775,14 +6792,11 @@ bool llvm::impliesPoison(const Value *ValAssumedPoison, const Value *V) {
6775
6792
return ::impliesPoison (ValAssumedPoison, V, /* Depth */ 0 );
6776
6793
}
6777
6794
6778
- static bool programUndefinedIfUndefOrPoison (const Value *V,
6779
- bool PoisonOnly);
6795
+ static bool programUndefinedIfUndefOrPoison (const Value *V, bool PoisonOnly);
6780
6796
6781
- static bool isGuaranteedNotToBeUndefOrPoison (const Value *V,
6782
- AssumptionCache *AC,
6783
- const Instruction *CtxI,
6784
- const DominatorTree *DT,
6785
- unsigned Depth, bool PoisonOnly) {
6797
+ static bool isGuaranteedNotToBeUndefOrPoison (
6798
+ const Value *V, AssumptionCache *AC, const Instruction *CtxI,
6799
+ const DominatorTree *DT, unsigned Depth, UndefPoisonKind Kind) {
6786
6800
if (Depth >= MaxAnalysisRecursionDepth)
6787
6801
return false ;
6788
6802
@@ -6797,16 +6811,19 @@ static bool isGuaranteedNotToBeUndefOrPoison(const Value *V,
6797
6811
}
6798
6812
6799
6813
if (auto *C = dyn_cast<Constant>(V)) {
6814
+ if (isa<PoisonValue>(C))
6815
+ return !includesPoison (Kind);
6816
+
6800
6817
if (isa<UndefValue>(C))
6801
- return PoisonOnly && !isa<PoisonValue>(C );
6818
+ return ! includesUndef (Kind );
6802
6819
6803
6820
if (isa<ConstantInt>(C) || isa<GlobalVariable>(C) || isa<ConstantFP>(V) ||
6804
6821
isa<ConstantPointerNull>(C) || isa<Function>(C))
6805
6822
return true ;
6806
6823
6807
6824
if (C->getType ()->isVectorTy () && !isa<ConstantExpr>(C))
6808
- return (PoisonOnly ? !C->containsPoisonElement ()
6809
- : !C->containsUndefOrPoisonElement ()) &&
6825
+ return (! includesUndef (Kind) ? !C->containsPoisonElement ()
6826
+ : !C->containsUndefOrPoisonElement ()) &&
6810
6827
!C->containsConstantExpression ();
6811
6828
}
6812
6829
@@ -6824,8 +6841,7 @@ static bool isGuaranteedNotToBeUndefOrPoison(const Value *V,
6824
6841
return true ;
6825
6842
6826
6843
auto OpCheck = [&](const Value *V) {
6827
- return isGuaranteedNotToBeUndefOrPoison (V, AC, CtxI, DT, Depth + 1 ,
6828
- PoisonOnly);
6844
+ return isGuaranteedNotToBeUndefOrPoison (V, AC, CtxI, DT, Depth + 1 , Kind);
6829
6845
};
6830
6846
6831
6847
if (auto *Opr = dyn_cast<Operator>(V)) {
@@ -6847,14 +6863,16 @@ static bool isGuaranteedNotToBeUndefOrPoison(const Value *V,
6847
6863
for (unsigned i = 0 ; i < Num; ++i) {
6848
6864
auto *TI = PN->getIncomingBlock (i)->getTerminator ();
6849
6865
if (!isGuaranteedNotToBeUndefOrPoison (PN->getIncomingValue (i), AC, TI,
6850
- DT, Depth + 1 , PoisonOnly )) {
6866
+ DT, Depth + 1 , Kind )) {
6851
6867
IsWellDefined = false ;
6852
6868
break ;
6853
6869
}
6854
6870
}
6855
6871
if (IsWellDefined)
6856
6872
return true ;
6857
- } else if (!canCreateUndefOrPoison (Opr) && all_of (Opr->operands (), OpCheck))
6873
+ } else if (!::canCreateUndefOrPoison (Opr, Kind,
6874
+ /* ConsiderFlagsAndMetadata*/ true ) &&
6875
+ all_of (Opr->operands (), OpCheck))
6858
6876
return true ;
6859
6877
}
6860
6878
@@ -6864,7 +6882,7 @@ static bool isGuaranteedNotToBeUndefOrPoison(const Value *V,
6864
6882
I->hasMetadata (LLVMContext::MD_dereferenceable_or_null))
6865
6883
return true ;
6866
6884
6867
- if (programUndefinedIfUndefOrPoison (V, PoisonOnly ))
6885
+ if (programUndefinedIfUndefOrPoison (V, ! includesUndef (Kind) ))
6868
6886
return true ;
6869
6887
6870
6888
// CxtI may be null or a cloned instruction.
@@ -6896,7 +6914,7 @@ static bool isGuaranteedNotToBeUndefOrPoison(const Value *V,
6896
6914
if (Cond) {
6897
6915
if (Cond == V)
6898
6916
return true ;
6899
- else if (PoisonOnly && isa<Operator>(Cond)) {
6917
+ else if (! includesUndef (Kind) && isa<Operator>(Cond)) {
6900
6918
// For poison, we can analyze further
6901
6919
auto *Opr = cast<Operator>(Cond);
6902
6920
if (any_of (Opr->operands (),
@@ -6918,20 +6936,22 @@ bool llvm::isGuaranteedNotToBeUndefOrPoison(const Value *V, AssumptionCache *AC,
6918
6936
const Instruction *CtxI,
6919
6937
const DominatorTree *DT,
6920
6938
unsigned Depth) {
6921
- return ::isGuaranteedNotToBeUndefOrPoison (V, AC, CtxI, DT, Depth, false );
6939
+ return ::isGuaranteedNotToBeUndefOrPoison (V, AC, CtxI, DT, Depth,
6940
+ UndefPoisonKind::UndefOrPoison);
6922
6941
}
6923
6942
6924
6943
bool llvm::isGuaranteedNotToBePoison (const Value *V, AssumptionCache *AC,
6925
6944
const Instruction *CtxI,
6926
6945
const DominatorTree *DT, unsigned Depth) {
6927
- return ::isGuaranteedNotToBeUndefOrPoison (V, AC, CtxI, DT, Depth, true );
6946
+ return ::isGuaranteedNotToBeUndefOrPoison (V, AC, CtxI, DT, Depth,
6947
+ UndefPoisonKind::PoisonOnly);
6928
6948
}
6929
6949
6930
6950
bool llvm::isGuaranteedNotToBeUndef (const Value *V, AssumptionCache *AC,
6931
6951
const Instruction *CtxI,
6932
6952
const DominatorTree *DT, unsigned Depth) {
6933
- // TODO: This is currently equivalent to isGuaranteedNotToBeUndefOrPoison().
6934
- return :: isGuaranteedNotToBeUndefOrPoison (V, AC, CtxI, DT, Depth, false );
6953
+ return :: isGuaranteedNotToBeUndefOrPoison (V, AC, CtxI, DT, Depth,
6954
+ UndefPoisonKind::UndefOnly );
6935
6955
}
6936
6956
6937
6957
// / Return true if undefined behavior would provably be executed on the path to
0 commit comments