@@ -237,6 +237,10 @@ class InstrLowerer final {
237
237
GlobalVariable *NamesVar = nullptr ;
238
238
size_t NamesSize = 0 ;
239
239
240
+ // / The instance of [[alwaysinline]] rmw_or(ptr, i8).
241
+ // / This is name-insensitive.
242
+ Function *RMWOrFunc = nullptr ;
243
+
240
244
// vector of counter load/store pairs to be register promoted.
241
245
std::vector<LoadStorePair> PromotionCandidates;
242
246
@@ -297,6 +301,14 @@ class InstrLowerer final {
297
301
StringRef Name,
298
302
GlobalValue::LinkageTypes Linkage);
299
303
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
+
300
312
// / Compute the address of the test vector bitmap that this profiling
301
313
// / instruction acts on.
302
314
Value *getBitmapAddress (InstrProfMCDCTVBitmapUpdate *I);
@@ -937,6 +949,45 @@ Value *InstrLowerer::getCounterAddress(InstrProfCntrInstBase *I) {
937
949
return Builder.CreateIntToPtr (Add, Addr->getType ());
938
950
}
939
951
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
+
940
991
Value *InstrLowerer::getBitmapAddress (InstrProfMCDCTVBitmapUpdate *I) {
941
992
auto *Bitmaps = getOrCreateRegionBitmaps (I);
942
993
IRBuilder<> Builder (I);
@@ -1044,17 +1095,7 @@ void InstrLowerer::lowerMCDCTestVectorBitmapUpdate(
1044
1095
// %7 = shl i8 1, %6
1045
1096
auto *ShiftedVal = Builder.CreateShl (Builder.getInt8 (0x1 ), BitToSet);
1046
1097
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));
1058
1099
Update->eraseFromParent ();
1059
1100
}
1060
1101
0 commit comments