@@ -237,6 +237,10 @@ class InstrLowerer final {
237237 GlobalVariable *NamesVar = nullptr ;
238238 size_t NamesSize = 0 ;
239239
240+ // / The instance of [[alwaysinline]] rmw_or(ptr, i8).
241+ // / This is name-insensitive.
242+ Function *RMWOrFunc = nullptr ;
243+
240244 // vector of counter load/store pairs to be register promoted.
241245 std::vector<LoadStorePair> PromotionCandidates;
242246
@@ -297,6 +301,14 @@ class InstrLowerer final {
297301 StringRef Name,
298302 GlobalValue::LinkageTypes Linkage);
299303
304+ // / Create [[alwaysinline]] rmw_or(ptr, i8).
305+ // / This doesn't update `RMWOrFunc`.
306+ Function *createRMWOrFunc ();
307+
308+ // / Get the call to `rmw_or`.
309+ // / Create the instance if it is unknown.
310+ CallInst *getRMWOrCall (Value *Addr, Value *Val);
311+
300312 // / Compute the address of the test vector bitmap that this profiling
301313 // / instruction acts on.
302314 Value *getBitmapAddress (InstrProfMCDCTVBitmapUpdate *I);
@@ -937,6 +949,45 @@ Value *InstrLowerer::getCounterAddress(InstrProfCntrInstBase *I) {
937949 return Builder.CreateIntToPtr (Add, Addr->getType ());
938950}
939951
952+ // / Create `void [[alwaysinline]] rmw_or(uint8_t *ArgAddr, uint8_t ArgVal)`
953+ // / "Basic" sequence is `*ArgAddr |= ArgVal`
954+ Function *InstrLowerer::createRMWOrFunc () {
955+ auto &Ctx = M.getContext ();
956+ auto *Int8Ty = Type::getInt8Ty (Ctx);
957+ Function *Fn = Function::Create (
958+ FunctionType::get (Type::getVoidTy (Ctx),
959+ {PointerType::getUnqual (Ctx), Int8Ty}, false ),
960+ Function::LinkageTypes::PrivateLinkage, " rmw_or" , M);
961+ Fn->addFnAttr (Attribute::AlwaysInline);
962+ auto *ArgAddr = Fn->getArg (0 );
963+ auto *ArgVal = Fn->getArg (1 );
964+ IRBuilder<> Builder (BasicBlock::Create (Ctx, " " , Fn));
965+
966+ // Load profile bitmap byte.
967+ // %mcdc.bits = load i8, ptr %4, align 1
968+ auto *Bitmap = Builder.CreateLoad (Int8Ty, ArgAddr, " mcdc.bits" );
969+
970+ // Perform logical OR of profile bitmap byte and shifted bit offset.
971+ // %8 = or i8 %mcdc.bits, %7
972+ auto *Result = Builder.CreateOr (Bitmap, ArgVal);
973+
974+ // Store the updated profile bitmap byte.
975+ // store i8 %8, ptr %3, align 1
976+ Builder.CreateStore (Result, ArgAddr);
977+
978+ // Terminator
979+ Builder.CreateRetVoid ();
980+
981+ return Fn;
982+ }
983+
984+ CallInst *InstrLowerer::getRMWOrCall (Value *Addr, Value *Val) {
985+ if (!RMWOrFunc)
986+ RMWOrFunc = createRMWOrFunc ();
987+
988+ return CallInst::Create (RMWOrFunc, {Addr, Val});
989+ }
990+
940991Value *InstrLowerer::getBitmapAddress (InstrProfMCDCTVBitmapUpdate *I) {
941992 auto *Bitmaps = getOrCreateRegionBitmaps (I);
942993 IRBuilder<> Builder (I);
@@ -1044,17 +1095,7 @@ void InstrLowerer::lowerMCDCTestVectorBitmapUpdate(
10441095 // %7 = shl i8 1, %6
10451096 auto *ShiftedVal = Builder.CreateShl (Builder.getInt8 (0x1 ), BitToSet);
10461097
1047- // Load profile bitmap byte.
1048- // %mcdc.bits = load i8, ptr %4, align 1
1049- auto *Bitmap = Builder.CreateLoad (Int8Ty, BitmapByteAddr, " mcdc.bits" );
1050-
1051- // Perform logical OR of profile bitmap byte and shifted bit offset.
1052- // %8 = or i8 %mcdc.bits, %7
1053- auto *Result = Builder.CreateOr (Bitmap, ShiftedVal);
1054-
1055- // Store the updated profile bitmap byte.
1056- // store i8 %8, ptr %3, align 1
1057- Builder.CreateStore (Result, BitmapByteAddr);
1098+ Builder.Insert (getRMWOrCall (BitmapByteAddr, ShiftedVal));
10581099 Update->eraseFromParent ();
10591100}
10601101
0 commit comments