@@ -7226,84 +7226,108 @@ bool llvm::propagatesPoison(const Use &PoisonOp) {
7226
7226
}
7227
7227
}
7228
7228
7229
- void llvm::getGuaranteedWellDefinedOps (
7230
- const Instruction *I, SmallVectorImpl<const Value *> &Operands) {
7229
+ // / Enumerates all operands of \p I that are guaranteed to not be undef or
7230
+ // / poison. If the callback \p Handle returns true, stop processing and return
7231
+ // / true. Otherwise, return false.
7232
+ template <typename CallableT>
7233
+ static bool handleGuaranteedWellDefinedOps (const Instruction *I,
7234
+ const CallableT &Handle ) {
7231
7235
switch (I->getOpcode ()) {
7232
7236
case Instruction::Store:
7233
- Operands.push_back (cast<StoreInst>(I)->getPointerOperand ());
7237
+ if (Handle (cast<StoreInst>(I)->getPointerOperand ()))
7238
+ return true ;
7234
7239
break ;
7235
7240
7236
7241
case Instruction::Load:
7237
- Operands.push_back (cast<LoadInst>(I)->getPointerOperand ());
7242
+ if (Handle (cast<LoadInst>(I)->getPointerOperand ()))
7243
+ return true ;
7238
7244
break ;
7239
7245
7240
7246
// Since dereferenceable attribute imply noundef, atomic operations
7241
7247
// also implicitly have noundef pointers too
7242
7248
case Instruction::AtomicCmpXchg:
7243
- Operands.push_back (cast<AtomicCmpXchgInst>(I)->getPointerOperand ());
7249
+ if (Handle (cast<AtomicCmpXchgInst>(I)->getPointerOperand ()))
7250
+ return true ;
7244
7251
break ;
7245
7252
7246
7253
case Instruction::AtomicRMW:
7247
- Operands.push_back (cast<AtomicRMWInst>(I)->getPointerOperand ());
7254
+ if (Handle (cast<AtomicRMWInst>(I)->getPointerOperand ()))
7255
+ return true ;
7248
7256
break ;
7249
7257
7250
7258
case Instruction::Call:
7251
7259
case Instruction::Invoke: {
7252
7260
const CallBase *CB = cast<CallBase>(I);
7253
- if (CB->isIndirectCall ())
7254
- Operands. push_back (CB-> getCalledOperand ()) ;
7255
- for (unsigned i = 0 ; i < CB->arg_size (); ++i) {
7256
- if (CB->paramHasAttr (i, Attribute::NoUndef) ||
7257
- CB->paramHasAttr (i, Attribute::Dereferenceable) ||
7258
- CB->paramHasAttr (i, Attribute::DereferenceableOrNull))
7259
- Operands. push_back (CB->getArgOperand (i));
7260
- }
7261
+ if (CB->isIndirectCall () && Handle (CB-> getCalledOperand ()) )
7262
+ return true ;
7263
+ for (unsigned i = 0 ; i < CB->arg_size (); ++i)
7264
+ if (( CB->paramHasAttr (i, Attribute::NoUndef) ||
7265
+ CB->paramHasAttr (i, Attribute::Dereferenceable) ||
7266
+ CB->paramHasAttr (i, Attribute::DereferenceableOrNull)) &&
7267
+ Handle (CB->getArgOperand (i)))
7268
+ return true ;
7261
7269
break ;
7262
7270
}
7263
7271
case Instruction::Ret:
7264
- if (I->getFunction ()->hasRetAttribute (Attribute::NoUndef))
7265
- Operands.push_back (I->getOperand (0 ));
7272
+ if (I->getFunction ()->hasRetAttribute (Attribute::NoUndef) &&
7273
+ Handle (I->getOperand (0 )))
7274
+ return true ;
7266
7275
break ;
7267
7276
case Instruction::Switch:
7268
- Operands.push_back (cast<SwitchInst>(I)->getCondition ());
7277
+ if (Handle (cast<SwitchInst>(I)->getCondition ()))
7278
+ return true ;
7269
7279
break ;
7270
7280
case Instruction::Br: {
7271
7281
auto *BR = cast<BranchInst>(I);
7272
- if (BR->isConditional ())
7273
- Operands. push_back (BR-> getCondition ()) ;
7282
+ if (BR->isConditional () && Handle (BR-> getCondition ()) )
7283
+ return true ;
7274
7284
break ;
7275
7285
}
7276
7286
default :
7277
7287
break ;
7278
7288
}
7289
+
7290
+ return false ;
7279
7291
}
7280
7292
7281
- void llvm::getGuaranteedNonPoisonOps (const Instruction *I,
7282
- SmallVectorImpl<const Value *> &Operands) {
7283
- getGuaranteedWellDefinedOps (I, Operands);
7293
+ void llvm::getGuaranteedWellDefinedOps (
7294
+ const Instruction *I, SmallVectorImpl<const Value *> &Operands) {
7295
+ handleGuaranteedWellDefinedOps (I, [&](const Value *V) {
7296
+ Operands.push_back (V);
7297
+ return false ;
7298
+ });
7299
+ }
7300
+
7301
+ // / Enumerates all operands of \p I that are guaranteed to not be poison.
7302
+ template <typename CallableT>
7303
+ static bool handleGuaranteedNonPoisonOps (const Instruction *I,
7304
+ const CallableT &Handle ) {
7305
+ if (handleGuaranteedWellDefinedOps (I, Handle ))
7306
+ return true ;
7284
7307
switch (I->getOpcode ()) {
7285
7308
// Divisors of these operations are allowed to be partially undef.
7286
7309
case Instruction::UDiv:
7287
7310
case Instruction::SDiv:
7288
7311
case Instruction::URem:
7289
7312
case Instruction::SRem:
7290
- Operands.push_back (I->getOperand (1 ));
7291
- break ;
7313
+ return Handle (I->getOperand (1 ));
7292
7314
default :
7293
- break ;
7315
+ return false ;
7294
7316
}
7295
7317
}
7296
7318
7319
+ void llvm::getGuaranteedNonPoisonOps (const Instruction *I,
7320
+ SmallVectorImpl<const Value *> &Operands) {
7321
+ handleGuaranteedNonPoisonOps (I, [&](const Value *V) {
7322
+ Operands.push_back (V);
7323
+ return false ;
7324
+ });
7325
+ }
7326
+
7297
7327
bool llvm::mustTriggerUB (const Instruction *I,
7298
7328
const SmallPtrSetImpl<const Value *> &KnownPoison) {
7299
- SmallVector<const Value *, 4 > NonPoisonOps;
7300
- getGuaranteedNonPoisonOps (I, NonPoisonOps);
7301
-
7302
- for (const auto *V : NonPoisonOps)
7303
- if (KnownPoison.count (V))
7304
- return true ;
7305
-
7306
- return false ;
7329
+ return handleGuaranteedNonPoisonOps (
7330
+ I, [&](const Value *V) { return KnownPoison.count (V); });
7307
7331
}
7308
7332
7309
7333
static bool programUndefinedIfUndefOrPoison (const Value *V,
@@ -7346,9 +7370,9 @@ static bool programUndefinedIfUndefOrPoison(const Value *V,
7346
7370
if (--ScanLimit == 0 )
7347
7371
break ;
7348
7372
7349
- SmallVector< const Value *, 4 > WellDefinedOps;
7350
- getGuaranteedWellDefinedOps (&I, WellDefinedOps) ;
7351
- if ( is_contained (WellDefinedOps, V ))
7373
+ if ( handleGuaranteedWellDefinedOps (&I, [V]( const Value *WellDefinedOp) {
7374
+ return WellDefinedOp == V ;
7375
+ } ))
7352
7376
return true ;
7353
7377
7354
7378
if (!isGuaranteedToTransferExecutionToSuccessor (&I))
0 commit comments