diff options
Diffstat (limited to 'llvm/lib/Analysis/ValueTracking.cpp')
-rw-r--r-- | llvm/lib/Analysis/ValueTracking.cpp | 50 |
1 files changed, 29 insertions, 21 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index a975f1c..8fe98b5 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -5197,6 +5197,31 @@ bool llvm::isOverflowIntrinsicNoWrap(const WithOverflowInst *WO, return llvm::any_of(GuardingBranches, AllUsesGuardedByBranch); } +/// Shifts return poison if shiftwidth is larger than the bitwidth. +static bool shiftAmountKnownInRange(const Value *ShiftAmount) { + auto *C = dyn_cast<Constant>(ShiftAmount); + if (!C) + return false; + + // Shifts return poison if shiftwidth is larger than the bitwidth. + SmallVector<const Constant *, 4> ShiftAmounts; + if (auto *FVTy = dyn_cast<FixedVectorType>(C->getType())) { + unsigned NumElts = FVTy->getNumElements(); + for (unsigned i = 0; i < NumElts; ++i) + ShiftAmounts.push_back(C->getAggregateElement(i)); + } else if (isa<ScalableVectorType>(C->getType())) + return false; // Can't tell, just return false to be safe + else + ShiftAmounts.push_back(C); + + bool Safe = llvm::all_of(ShiftAmounts, [](const Constant *C) { + auto *CI = dyn_cast_or_null<ConstantInt>(C); + return CI && CI->getValue().ult(C->getType()->getIntegerBitWidth()); + }); + + return Safe; +} + static bool canCreateUndefOrPoison(const Operator *Op, bool PoisonOnly, bool ConsiderFlags) { @@ -5209,27 +5234,8 @@ static bool canCreateUndefOrPoison(const Operator *Op, bool PoisonOnly, switch (Opcode) { case Instruction::Shl: case Instruction::AShr: - case Instruction::LShr: { - // Shifts return poison if shiftwidth is larger than the bitwidth. - if (auto *C = dyn_cast<Constant>(Op->getOperand(1))) { - SmallVector<Constant *, 4> ShiftAmounts; - if (auto *FVTy = dyn_cast<FixedVectorType>(C->getType())) { - unsigned NumElts = FVTy->getNumElements(); - for (unsigned i = 0; i < NumElts; ++i) - ShiftAmounts.push_back(C->getAggregateElement(i)); - } else if (isa<ScalableVectorType>(C->getType())) - return true; // Can't tell, just return true to be safe - else - ShiftAmounts.push_back(C); - - bool Safe = llvm::all_of(ShiftAmounts, [](Constant *C) { - auto *CI = dyn_cast_or_null<ConstantInt>(C); - return CI && CI->getValue().ult(C->getType()->getIntegerBitWidth()); - }); - return !Safe; - } - return true; - } + case Instruction::LShr: + return !shiftAmountKnownInRange(Op->getOperand(1)); case Instruction::FPToSI: case Instruction::FPToUI: // fptosi/ui yields poison if the resulting value does not fit in the @@ -5267,8 +5273,10 @@ static bool canCreateUndefOrPoison(const Operator *Op, bool PoisonOnly, case Intrinsic::uadd_sat: case Intrinsic::ssub_sat: case Intrinsic::usub_sat: + return false; case Intrinsic::sshl_sat: case Intrinsic::ushl_sat: + return !shiftAmountKnownInRange(II->getArgOperand(1)); case Intrinsic::fma: case Intrinsic::fmuladd: case Intrinsic::sqrt: |