@@ -411,6 +411,12 @@ bool isAllowedIRIntrinsic(Intrinsic::ID ID) {
411411 case Intrinsic::usub_sat:
412412 case Intrinsic::sadd_sat:
413413 case Intrinsic::ssub_sat:
414+ case Intrinsic::uadd_with_overflow:
415+ case Intrinsic::usub_with_overflow:
416+ case Intrinsic::umul_with_overflow:
417+ case Intrinsic::sadd_with_overflow:
418+ case Intrinsic::ssub_with_overflow:
419+ case Intrinsic::smul_with_overflow:
414420 case Intrinsic::fshl:
415421 case Intrinsic::fshr:
416422 return true ;
@@ -623,6 +629,41 @@ bool isValidVectorInstruction(const Instruction &I) {
623629 return true ;
624630}
625631
632+ bool isOverflowIntrinsic (Intrinsic::ID ID ) {
633+ switch (ID ) {
634+ case Intrinsic::uadd_with_overflow:
635+ case Intrinsic::usub_with_overflow:
636+ case Intrinsic::umul_with_overflow:
637+ case Intrinsic::sadd_with_overflow:
638+ case Intrinsic::ssub_with_overflow:
639+ case Intrinsic::smul_with_overflow:
640+ return true ;
641+ default :
642+ return false ;
643+ }
644+ }
645+
646+ bool isValidAggregateInstruction (const Instruction &I) {
647+ const auto *Extract = dyn_cast<ExtractValueInst>(&I);
648+ if (!Extract)
649+ return true ;
650+ if (Extract->getNumIndices () != 1 )
651+ return false ;
652+ const auto *Call = dyn_cast<CallInst>(Extract->getAggregateOperand ());
653+ if (!Call)
654+ return false ;
655+ const Function *Callee = Call->getCalledFunction ();
656+ if (!Callee || !Callee->isIntrinsic () ||
657+ !isOverflowIntrinsic (Callee->getIntrinsicID ()))
658+ return false ;
659+ unsigned Index = *Extract->idx_begin ();
660+ if (Index == 0 )
661+ return Extract->getType ()->isIntegerTy (32 );
662+ if (Index == 1 )
663+ return Extract->getType ()->isIntegerTy (1 );
664+ return false ;
665+ }
666+
626667bool isValidFPConversionInstruction (const Instruction &I) {
627668 const auto *UIToFP = dyn_cast<UIToFPInst>(&I);
628669 if (!UIToFP)
@@ -638,7 +679,7 @@ bool isValidFPConversionInstruction(const Instruction &I) {
638679}
639680
640681bool isAllowedIRInstruction (const Instruction &I) {
641- if (isa<InsertElementInst, ExtractElementInst>(&I))
682+ if (isa<InsertElementInst, ExtractElementInst, ExtractValueInst >(&I))
642683 return true ;
643684 if (isa<BranchInst, SwitchInst, ReturnInst, LoadInst, StoreInst,
644685 GetElementPtrInst, ZExtInst, SExtInst, TruncInst, UIToFPInst,
@@ -1484,6 +1525,7 @@ bool validateIRCorpusModule(Module &M) {
14841525 for (Instruction &I : BB )
14851526 if (!isAllowedIRInstruction (I) ||
14861527 !isValidVectorInstruction (I) ||
1528+ !isValidAggregateInstruction (I) ||
14871529 !isValidFPConversionInstruction (I) ||
14881530 !isValidLoopControlInstruction (I) ||
14891531 (!AllowM019 && triggersM019HighBitOrXor (I)) ||
@@ -2382,6 +2424,42 @@ Value *emitRandomFiniteSignedFPInstruction(IRBuilder<NoFolder> &B, Value *A,
23822424 }
23832425}
23842426
2427+ Intrinsic::ID randomOverflowIntrinsic (std::minstd_rand &Gen) {
2428+ static constexpr std::array<Intrinsic::ID , 6 > IDs = {
2429+ Intrinsic::uadd_with_overflow, Intrinsic::usub_with_overflow,
2430+ Intrinsic::umul_with_overflow, Intrinsic::sadd_with_overflow,
2431+ Intrinsic::ssub_with_overflow, Intrinsic::smul_with_overflow};
2432+ return IDs[Gen () % IDs.size ()];
2433+ }
2434+
2435+ Value *emitRandomOverflowInstruction (IRBuilder<NoFolder> &B, Module &M,
2436+ Value *A, Value *Bv,
2437+ std::minstd_rand &Gen,
2438+ StringRef NamePrefix) {
2439+ LLVMContext &Ctx = M.getContext ();
2440+ Type *I32 = Type::getInt32Ty (Ctx);
2441+ FunctionCallee Fn =
2442+ Intrinsic::getOrInsertDeclaration (&M, randomOverflowIntrinsic (Gen), {I32 });
2443+ Value *Pair = B.CreateCall (Fn, {A, Bv}, Twine (NamePrefix) + " .call" );
2444+ Value *Result = B.CreateExtractValue (Pair, {0 }, Twine (NamePrefix) + " .value" );
2445+ Value *Overflow =
2446+ B.CreateExtractValue (Pair, {1 }, Twine (NamePrefix) + " .overflow" );
2447+ Value *OverflowI32 =
2448+ B.CreateZExt (Overflow, I32 , Twine (NamePrefix) + " .overflow.i32" );
2449+ switch (Gen () % 5 ) {
2450+ case 0 :
2451+ return Result;
2452+ case 1 :
2453+ return B.CreateXor (Result, OverflowI32, Twine (NamePrefix) + " .xor" );
2454+ case 2 :
2455+ return B.CreateAdd (Result, OverflowI32, Twine (NamePrefix) + " .add" );
2456+ case 3 :
2457+ return B.CreateSub (Result, OverflowI32, Twine (NamePrefix) + " .sub" );
2458+ default :
2459+ return B.CreateSelect (Overflow, Bv, Result, Twine (NamePrefix) + " .select" );
2460+ }
2461+ }
2462+
23852463Value *emitSafeSignedDivRemInstruction (IRBuilder<NoFolder> &B, Value *A,
23862464 Value *Bv, bool IsRem,
23872465 StringRef NamePrefix) {
@@ -2448,7 +2526,7 @@ Value *emitRandomIRInstruction(IRBuilder<NoFolder> &B, Module &M,
24482526 Type *I32 = Type::getInt32Ty (Ctx);
24492527 Value *A = Current;
24502528 Value *Bv = chooseI32Value (InsertPt, Gen);
2451- switch (Gen () % 82 ) {
2529+ switch (Gen () % 88 ) {
24522530 case 0 :
24532531 return B.CreateAdd (A, Bv, " fuzz.add" );
24542532 case 1 :
@@ -2606,6 +2684,13 @@ Value *emitRandomIRInstruction(IRBuilder<NoFolder> &B, Module &M,
26062684 case 66 :
26072685 case 67 :
26082686 return emitRandomFiniteHalfFPInstruction (B, A, Bv, Gen, " fuzz.fp16" );
2687+ case 68 :
2688+ case 69 :
2689+ case 70 :
2690+ case 71 :
2691+ case 72 :
2692+ case 73 :
2693+ return emitRandomOverflowInstruction (B, M, A, Bv, Gen, " fuzz.overflow" );
26092694 default :
26102695 switch (Gen () % 5 ) {
26112696 case 0 :
@@ -2640,7 +2725,7 @@ Value *emitRandomCFGArmInstruction(IRBuilder<NoFolder> &B, Module &M, Value *A,
26402725 Type *I8 = Type::getInt8Ty (Ctx);
26412726 Type *I16 = Type::getInt16Ty (Ctx);
26422727 Type *I32 = Type::getInt32Ty (Ctx);
2643- switch (Gen () % 68 ) {
2728+ switch (Gen () % 74 ) {
26442729 case 0 :
26452730 return B.CreateAdd (A, Bv, " fuzz.cfg.add" );
26462731 case 1 :
@@ -2785,6 +2870,14 @@ Value *emitRandomCFGArmInstruction(IRBuilder<NoFolder> &B, Module &M, Value *A,
27852870 case 58 :
27862871 case 59 :
27872872 return emitRandomFiniteHalfFPInstruction (B, A, Bv, Gen, " fuzz.cfg.fp16" );
2873+ case 60 :
2874+ case 61 :
2875+ case 62 :
2876+ case 63 :
2877+ case 64 :
2878+ case 65 :
2879+ return emitRandomOverflowInstruction (B, M, A, Bv, Gen,
2880+ " fuzz.cfg.overflow" );
27882881 default :
27892882 switch (Gen () % 5 ) {
27902883 case 0 :
0 commit comments