@@ -608,6 +608,8 @@ bool isAllowedIRInstruction(const Instruction &I) {
608608 isAllowedFPVectorType (BO ->getType ());
609609 case Instruction::UDiv:
610610 case Instruction::URem:
611+ if (BO ->hasName () && BO ->getName ().starts_with (" fuzz.load.idx" ))
612+ return true ;
611613 return isKnownNonZeroI32 (BO ->getOperand (1 ));
612614 case Instruction::SDiv:
613615 case Instruction::SRem:
@@ -1311,29 +1313,68 @@ bool hasName(const Value *V, StringRef Name) {
13111313 return V && V->hasName () && V->getName () == Name;
13121314}
13131315
1314- bool validateFixedMemoryShape (Function &Kernel) {
1315- unsigned GEPs = 0 ;
1316- unsigned Loads = 0 ;
1316+ bool hasNameStartingWith (const Value *V, StringRef Prefix) {
1317+ return V && V->hasName () && V->getName ().starts_with (Prefix);
1318+ }
1319+
1320+ bool isFuzzInputLoadIndex (const Value *V, Function &Kernel) {
1321+ const auto *ZExt = dyn_cast<ZExtInst>(V);
1322+ if (!ZExt || !hasNameStartingWith (ZExt, " fuzz.load.idx64" ) ||
1323+ !ZExt->getType ()->isIntegerTy (64 ))
1324+ return false ;
1325+
1326+ const auto *URem = dyn_cast<BinaryOperator>(ZExt->getOperand (0 ));
1327+ return URem && URem->getOpcode () == Instruction::URem &&
1328+ hasNameStartingWith (URem, " fuzz.load.idx" ) &&
1329+ URem->getOperand (1 ) == Kernel.getArg (2 );
1330+ }
1331+
1332+ bool isFuzzInputLoadPtr (const Value *V) {
1333+ return hasNameStartingWith (V, " fuzz.load.ptr" );
1334+ }
1335+
1336+ bool validateMemoryShape (Function &Kernel) {
1337+ bool SawBaseInGEP = false ;
1338+ bool SawBaseOutGEP = false ;
1339+ unsigned BaseLoads = 0 ;
1340+ unsigned ExtraLoadGEPs = 0 ;
1341+ unsigned ExtraLoads = 0 ;
13171342 unsigned Stores = 0 ;
13181343 for (BasicBlock &BB : Kernel) {
13191344 for (Instruction &I : BB ) {
13201345 if (auto *GEP = dyn_cast<GetElementPtrInst>(&I)) {
1321- ++GEPs;
13221346 if (GEP ->getSourceElementType () != Type::getInt32Ty (Kernel.getContext ()))
13231347 return false ;
1324- if (!hasName (GEP , " in.ptr" ) && !hasName (GEP , " out.ptr" ))
1325- return false ;
1326- if (GEP ->getNumIndices () != 1 ||
1327- !hasName (GEP ->idx_begin ()->get (), " idx64" ))
1328- return false ;
1329- unsigned ArgNo = hasName (GEP , " in.ptr" ) ? 0 : 1 ;
1330- if (GEP ->getPointerOperand () != Kernel.getArg (ArgNo))
1348+ if (hasName (GEP , " in.ptr" ) || hasName (GEP , " out.ptr" )) {
1349+ if (GEP ->getNumIndices () != 1 ||
1350+ !hasName (GEP ->idx_begin ()->get (), " idx64" ))
1351+ return false ;
1352+ unsigned ArgNo = hasName (GEP , " in.ptr" ) ? 0 : 1 ;
1353+ if (GEP ->getPointerOperand () != Kernel.getArg (ArgNo))
1354+ return false ;
1355+ if (ArgNo == 0 )
1356+ SawBaseInGEP = true ;
1357+ else
1358+ SawBaseOutGEP = true ;
1359+ } else if (isFuzzInputLoadPtr (GEP )) {
1360+ if (GEP ->getPointerOperand () != Kernel.getArg (0 ) ||
1361+ GEP ->getNumIndices () != 1 ||
1362+ !isFuzzInputLoadIndex (GEP ->idx_begin ()->get (), Kernel))
1363+ return false ;
1364+ ++ExtraLoadGEPs;
1365+ } else {
13311366 return false ;
1367+ }
13321368 } else if (auto *Load = dyn_cast<LoadInst>(&I)) {
1333- ++Loads;
1334- if (!Load->getType ()->isIntegerTy (32 ) ||
1335- !hasName (Load->getPointerOperand (), " in.ptr" ))
1369+ if (!Load->getType ()->isIntegerTy (32 ))
13361370 return false ;
1371+ if (hasName (Load->getPointerOperand (), " in.ptr" )) {
1372+ ++BaseLoads;
1373+ } else if (isFuzzInputLoadPtr (Load->getPointerOperand ())) {
1374+ ++ExtraLoads;
1375+ } else {
1376+ return false ;
1377+ }
13371378 } else if (auto *Store = dyn_cast<StoreInst>(&I)) {
13381379 ++Stores;
13391380 if (!Store->getValueOperand ()->getType ()->isIntegerTy (32 ) ||
@@ -1342,7 +1383,8 @@ bool validateFixedMemoryShape(Function &Kernel) {
13421383 }
13431384 }
13441385 }
1345- return GEPs == 2 && Loads == 1 && Stores == 1 ;
1386+ return SawBaseInGEP && SawBaseOutGEP && BaseLoads == 1 && Stores == 1 &&
1387+ ExtraLoadGEPs == ExtraLoads && ExtraLoads <= 32 ;
13461388}
13471389
13481390bool validateIRCorpusModule (Module &M) {
@@ -1370,7 +1412,7 @@ bool validateIRCorpusModule(Module &M) {
13701412 if (&F == Kernel) {
13711413 if (F.empty ())
13721414 return false ;
1373- if (!validateFixedMemoryShape (F))
1415+ if (!validateMemoryShape (F))
13741416 return false ;
13751417 for (BasicBlock &BB : F)
13761418 for (Instruction &I : BB )
@@ -2081,6 +2123,51 @@ Value *emitSafeSignedDivRemInstruction(IRBuilder<NoFolder> &B, Value *A,
20812123 return B.CreateSDiv (A, Den, Twine (NamePrefix) + " .op" );
20822124}
20832125
2126+ Value *emitSafeInputLoadInstruction (IRBuilder<NoFolder> &B, Module &M,
2127+ Value *A, Value *Bv,
2128+ std::minstd_rand &Gen,
2129+ StringRef NamePrefix) {
2130+ Function *F = B.GetInsertBlock ()->getParent ();
2131+ LLVMContext &Ctx = M.getContext ();
2132+ Type *I32 = Type::getInt32Ty (Ctx);
2133+ Type *I64 = Type::getInt64Ty (Ctx);
2134+ Value *In = F->getArg (0 );
2135+ Value *N = F->getArg (2 );
2136+ Value *Seed = nullptr ;
2137+ switch (Gen () % 4 ) {
2138+ case 0 :
2139+ Seed = A;
2140+ break ;
2141+ case 1 :
2142+ Seed = Bv;
2143+ break ;
2144+ case 2 :
2145+ Seed = B.CreateAdd (A, Bv, Twine (NamePrefix) + " .seed.add" );
2146+ break ;
2147+ default :
2148+ Seed = B.CreateXor (A, Bv, Twine (NamePrefix) + " .seed.xor" );
2149+ break ;
2150+ }
2151+
2152+ Value *Idx = B.CreateURem (Seed, N, Twine (NamePrefix) + " .idx" );
2153+ Value *Idx64 = B.CreateZExt (Idx, I64 , Twine (NamePrefix) + " .idx64" );
2154+ Value *Ptr = B.CreateGEP (I32 , In, Idx64, Twine (NamePrefix) + " .ptr" );
2155+ Value *Loaded = B.CreateLoad (I32 , Ptr, Twine (NamePrefix) + " .value" );
2156+ switch (Gen () % 4 ) {
2157+ case 0 :
2158+ return B.CreateXor (A, Loaded, Twine (NamePrefix) + " .xor" );
2159+ case 1 :
2160+ return B.CreateAdd (Bv, Loaded, Twine (NamePrefix) + " .add" );
2161+ case 2 :
2162+ return B.CreateSub (Loaded, A, Twine (NamePrefix) + " .sub" );
2163+ default : {
2164+ Value *Cmp = B.CreateICmp (randomICmpPredicate (Gen), Loaded, A,
2165+ Twine (NamePrefix) + " .cmp" );
2166+ return B.CreateSelect (Cmp, Loaded, Bv, Twine (NamePrefix) + " .select" );
2167+ }
2168+ }
2169+ }
2170+
20842171Value *emitRandomIRInstruction (IRBuilder<NoFolder> &B, Module &M,
20852172 Instruction *InsertPt, Value *Current,
20862173 std::minstd_rand &Gen) {
@@ -2090,7 +2177,7 @@ Value *emitRandomIRInstruction(IRBuilder<NoFolder> &B, Module &M,
20902177 Type *I32 = Type::getInt32Ty (Ctx);
20912178 Value *A = Current;
20922179 Value *Bv = chooseI32Value (InsertPt, Gen);
2093- switch (Gen () % 70 ) {
2180+ switch (Gen () % 74 ) {
20942181 case 0 :
20952182 return B.CreateAdd (A, Bv, " fuzz.add" );
20962183 case 1 :
@@ -2236,6 +2323,11 @@ Value *emitRandomIRInstruction(IRBuilder<NoFolder> &B, Module &M,
22362323 case 57 :
22372324 return emitRandomFiniteSignedFPInstruction (B, A, Bv, Gen,
22382325 " fuzz.fp.signed" );
2326+ case 58 :
2327+ case 59 :
2328+ case 60 :
2329+ case 61 :
2330+ return emitSafeInputLoadInstruction (B, M, A, Bv, Gen, " fuzz.load" );
22392331 default :
22402332 switch (Gen () % 4 ) {
22412333 case 0 :
@@ -2268,7 +2360,7 @@ Value *emitRandomCFGArmInstruction(IRBuilder<NoFolder> &B, Module &M, Value *A,
22682360 Type *I8 = Type::getInt8Ty (Ctx);
22692361 Type *I16 = Type::getInt16Ty (Ctx);
22702362 Type *I32 = Type::getInt32Ty (Ctx);
2271- switch (Gen () % 56 ) {
2363+ switch (Gen () % 60 ) {
22722364 case 0 :
22732365 return B.CreateAdd (A, Bv, " fuzz.cfg.add" );
22742366 case 1 :
@@ -2401,6 +2493,11 @@ Value *emitRandomCFGArmInstruction(IRBuilder<NoFolder> &B, Module &M, Value *A,
24012493 case 49 :
24022494 return emitRandomFiniteSignedFPInstruction (B, A, Bv, Gen,
24032495 " fuzz.cfg.fp.signed" );
2496+ case 50 :
2497+ case 51 :
2498+ case 52 :
2499+ case 53 :
2500+ return emitSafeInputLoadInstruction (B, M, A, Bv, Gen, " fuzz.load" );
24042501 default :
24052502 switch (Gen () % 4 ) {
24062503 case 0 :
@@ -3172,6 +3269,8 @@ bool isCrossOverCloneableInstruction(const Instruction &I) {
31723269 if (I.isTerminator () || I.mayReadOrWriteMemory () ||
31733270 isa<GetElementPtrInst, PHINode>(&I))
31743271 return false ;
3272+ if (I.hasName () && I.getName ().starts_with (" fuzz.load." ))
3273+ return false ;
31753274 Type *Ty = I.getType ();
31763275 if (!Ty->isIntegerTy (1 ) && !Ty->isIntegerTy (32 ))
31773276 return false ;
0 commit comments