llvm.org GIT mirror llvm / e53e585
IPO: Const correctness for summaries passed into passes. Pass const qualified summaries into importers and unqualified summaries into exporters. This lets us const-qualify the summary argument to thinBackend. Differential Revision: https://reviews.llvm.org/D31230 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@298534 91177308-0d34-0410-b5e6-96231b3b80d8 Peter Collingbourne 2 years ago
7 changed file(s) with 120 addition(s) and 78 deletion(s). Raw diff Collapse all Expand all
4141
4242 /// Runs a ThinLTO backend.
4343 Error thinBackend(Config &C, unsigned Task, AddStreamFn AddStream, Module &M,
44 ModuleSummaryIndex &CombinedIndex,
44 const ModuleSummaryIndex &CombinedIndex,
4545 const FunctionImporter::ImportMapTy &ImportList,
4646 const GVSummaryMapTy &DefinedGlobals,
4747 MapVector &ModuleMap);
131131 /// added to the per-module passes.
132132 Pass *Inliner;
133133
134 /// The module summary index to use for passing information between the
135 /// regular LTO phase and the thin LTO backends, for example the CFI and
136 /// devirtualization type tests.
137 ModuleSummaryIndex *Summary = nullptr;
134 /// The module summary index to use for exporting information from the
135 /// regular LTO phase, for example for the CFI and devirtualization type
136 /// tests.
137 ModuleSummaryIndex *ExportSummary = nullptr;
138
139 /// The module summary index to use for importing information to the
140 /// thin LTO backends, for example for the CFI and devirtualization type
141 /// tests.
142 const ModuleSummaryIndex *ImportSummary = nullptr;
138143
139144 bool DisableTailCalls;
140145 bool DisableUnitAtATime;
224224
225225 /// \brief This pass lowers type metadata and the llvm.type.test intrinsic to
226226 /// bitsets.
227 /// \param Action What to do with the summary passed as Index.
228 /// \param Index The summary to use for importing or exporting, this can be null
229 /// when Action is None.
230 ModulePass *createLowerTypeTestsPass(PassSummaryAction Action,
231 ModuleSummaryIndex *Index);
227 ///
228 /// The behavior depends on the summary arguments:
229 /// - If ExportSummary is non-null, this pass will export type identifiers to
230 /// the given summary.
231 /// - Otherwise, if ImportSummary is non-null, this pass will import type
232 /// identifiers from the given summary.
233 /// - Otherwise it does neither.
234 /// It is invalid for both ExportSummary and ImportSummary to be non-null.
235 ModulePass *createLowerTypeTestsPass(ModuleSummaryIndex *ExportSummary,
236 const ModuleSummaryIndex *ImportSummary);
232237
233238 /// \brief This pass export CFI checks for use by external modules.
234239 ModulePass *createCrossDSOCFIPass();
235240
236241 /// \brief This pass implements whole-program devirtualization using type
237242 /// metadata.
238 ModulePass *createWholeProgramDevirtPass(PassSummaryAction Action,
239 ModuleSummaryIndex *Index);
243 ///
244 /// The behavior depends on the summary arguments:
245 /// - If ExportSummary is non-null, this pass will export type identifiers to
246 /// the given summary.
247 /// - Otherwise, if ImportSummary is non-null, this pass will import type
248 /// identifiers from the given summary.
249 /// - Otherwise it does neither.
250 /// It is invalid for both ExportSummary and ImportSummary to be non-null.
251 ModulePass *
252 createWholeProgramDevirtPass(ModuleSummaryIndex *ExportSummary,
253 const ModuleSummaryIndex *ImportSummary);
240254
241255 /// This pass splits globals into pieces for the benefit of whole-program
242256 /// devirtualization and control-flow integrity.
222222 }
223223
224224 static void runOldPMPasses(Config &Conf, Module &Mod, TargetMachine *TM,
225 bool IsThinLTO, ModuleSummaryIndex &CombinedIndex) {
225 bool IsThinLTO, ModuleSummaryIndex *ExportSummary,
226 const ModuleSummaryIndex *ImportSummary) {
226227 legacy::PassManager passes;
227228 passes.add(createTargetTransformInfoWrapperPass(TM->getTargetIRAnalysis()));
228229
229230 PassManagerBuilder PMB;
230231 PMB.LibraryInfo = new TargetLibraryInfoImpl(Triple(TM->getTargetTriple()));
231232 PMB.Inliner = createFunctionInliningPass();
232 PMB.Summary = &CombinedIndex;
233 PMB.ExportSummary = ExportSummary;
234 PMB.ImportSummary = ImportSummary;
233235 // Unconditionally verify input since it is not verified before this
234236 // point and has unknown origin.
235237 PMB.VerifyInput = true;
246248 }
247249
248250 bool opt(Config &Conf, TargetMachine *TM, unsigned Task, Module &Mod,
249 bool IsThinLTO, ModuleSummaryIndex &CombinedIndex) {
251 bool IsThinLTO, ModuleSummaryIndex *ExportSummary,
252 const ModuleSummaryIndex *ImportSummary) {
250253 // There's still no ThinLTO pipeline hooked up in the new pass manager,
251254 // once there is one, we can just remove this.
252255 if (LTOUseNewPM && IsThinLTO)
259262 else if (LTOUseNewPM)
260263 runNewPMPasses(Mod, TM, Conf.OptLevel);
261264 else
262 runOldPMPasses(Conf, Mod, TM, IsThinLTO, CombinedIndex);
265 runOldPMPasses(Conf, Mod, TM, IsThinLTO, ExportSummary, ImportSummary);
263266 return !Conf.PostOptModuleHook || Conf.PostOptModuleHook(Task, Mod);
264267 }
265268
382385 auto DiagnosticOutputFile = std::move(*DiagFileOrErr);
383386
384387 if (!C.CodeGenOnly) {
385 if (!opt(C, TM.get(), 0, *Mod, /*IsThinLTO=*/false, CombinedIndex)) {
388 if (!opt(C, TM.get(), 0, *Mod, /*IsThinLTO=*/false,
389 /*ExportSummary=*/&CombinedIndex, /*ImportSummary=*/nullptr)) {
386390 finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
387391 return Error::success();
388392 }
399403 }
400404
401405 Error lto::thinBackend(Config &Conf, unsigned Task, AddStreamFn AddStream,
402 Module &Mod, ModuleSummaryIndex &CombinedIndex,
406 Module &Mod, const ModuleSummaryIndex &CombinedIndex,
403407 const FunctionImporter::ImportMapTy &ImportList,
404408 const GVSummaryMapTy &DefinedGlobals,
405409 MapVector &ModuleMap) {
451455 if (Conf.PostImportModuleHook && !Conf.PostImportModuleHook(Task, Mod))
452456 return Error::success();
453457
454 if (!opt(Conf, TM.get(), Task, Mod, /*IsThinLTO=*/true, CombinedIndex))
458 if (!opt(Conf, TM.get(), Task, Mod, /*IsThinLTO=*/true,
459 /*ExportSummary=*/nullptr, /*ImportSummary=*/&CombinedIndex))
455460 return Error::success();
456461
457462 codegen(Conf, TM.get(), AddStream, Task, Mod);
231231 class LowerTypeTestsModule {
232232 Module &M;
233233
234 PassSummaryAction Action;
235 ModuleSummaryIndex *Summary;
234 ModuleSummaryIndex *ExportSummary;
235 const ModuleSummaryIndex *ImportSummary;
236236
237237 bool LinkerSubsectionsViaSymbols;
238238 Triple::ArchType Arch;
331331 void createJumpTable(Function *F, ArrayRef Functions);
332332
333333 public:
334 LowerTypeTestsModule(Module &M, PassSummaryAction Action,
335 ModuleSummaryIndex *Summary);
334 LowerTypeTestsModule(Module &M, ModuleSummaryIndex *ExportSummary,
335 const ModuleSummaryIndex *ImportSummary);
336336 bool lower();
337337
338338 // Lower the module using the action and summary passed as command line
345345
346346 bool UseCommandLine = false;
347347
348 PassSummaryAction Action;
349 ModuleSummaryIndex *Summary;
348 ModuleSummaryIndex *ExportSummary;
349 const ModuleSummaryIndex *ImportSummary;
350350
351351 LowerTypeTests() : ModulePass(ID), UseCommandLine(true) {
352352 initializeLowerTypeTestsPass(*PassRegistry::getPassRegistry());
353353 }
354354
355 LowerTypeTests(PassSummaryAction Action, ModuleSummaryIndex *Summary)
356 : ModulePass(ID), Action(Action), Summary(Summary) {
355 LowerTypeTests(ModuleSummaryIndex *ExportSummary,
356 const ModuleSummaryIndex *ImportSummary)
357 : ModulePass(ID), ExportSummary(ExportSummary),
358 ImportSummary(ImportSummary) {
357359 initializeLowerTypeTestsPass(*PassRegistry::getPassRegistry());
358360 }
359361
362364 return false;
363365 if (UseCommandLine)
364366 return LowerTypeTestsModule::runForTesting(M);
365 return LowerTypeTestsModule(M, Action, Summary).lower();
367 return LowerTypeTestsModule(M, ExportSummary, ImportSummary).lower();
366368 }
367369 };
368370
372374 false)
373375 char LowerTypeTests::ID = 0;
374376
375 ModulePass *llvm::createLowerTypeTestsPass(PassSummaryAction Action,
376 ModuleSummaryIndex *Summary) {
377 return new LowerTypeTests(Action, Summary);
377 ModulePass *
378 llvm::createLowerTypeTestsPass(ModuleSummaryIndex *ExportSummary,
379 const ModuleSummaryIndex *ImportSummary) {
380 return new LowerTypeTests(ExportSummary, ImportSummary);
378381 }
379382
380383 /// Build a bit set for TypeId using the object layouts in
498501 return createMaskedBitTest(B, TIL.InlineBits, BitOffset);
499502 } else {
500503 Constant *ByteArray = TIL.TheByteArray;
501 if (!LinkerSubsectionsViaSymbols && AvoidReuse &&
502 Action != PassSummaryAction::Import) {
504 if (!LinkerSubsectionsViaSymbols && AvoidReuse && !ImportSummary) {
503505 // Each use of the byte array uses a different alias. This makes the
504506 // backend less likely to reuse previously computed byte array addresses,
505507 // improving the security of the CFI mechanism based on this pass.
699701 /// information about the type identifier.
700702 void LowerTypeTestsModule::exportTypeId(StringRef TypeId,
701703 const TypeIdLowering &TIL) {
702 TypeTestResolution &TTRes = Summary->getOrInsertTypeIdSummary(TypeId).TTRes;
704 TypeTestResolution &TTRes =
705 ExportSummary->getOrInsertTypeIdSummary(TypeId).TTRes;
703706 TTRes.TheKind = TIL.TheKind;
704707
705708 auto ExportGlobal = [&](StringRef Name, Constant *C) {
737740
738741 LowerTypeTestsModule::TypeIdLowering
739742 LowerTypeTestsModule::importTypeId(StringRef TypeId) {
740 const TypeIdSummary *TidSummary = Summary->getTypeIdSummary(TypeId);
743 const TypeIdSummary *TidSummary = ImportSummary->getTypeIdSummary(TypeId);
741744 if (!TidSummary)
742745 return {}; // Unsat: no globals match this type id.
743746 const TypeTestResolution &TTRes = TidSummary->TTRes;
12921295 }
12931296
12941297 /// Lower all type tests in this module.
1295 LowerTypeTestsModule::LowerTypeTestsModule(Module &M, PassSummaryAction Action,
1296 ModuleSummaryIndex *Summary)
1297 : M(M), Action(Action), Summary(Summary) {
1298 LowerTypeTestsModule::LowerTypeTestsModule(
1299 Module &M, ModuleSummaryIndex *ExportSummary,
1300 const ModuleSummaryIndex *ImportSummary)
1301 : M(M), ExportSummary(ExportSummary), ImportSummary(ImportSummary) {
1302 assert(!(ExportSummary && ImportSummary));
12981303 Triple TargetTriple(M.getTargetTriple());
12991304 LinkerSubsectionsViaSymbols = TargetTriple.isMacOSX();
13001305 Arch = TargetTriple.getArch();
13181323 ExitOnErr(errorCodeToError(In.error()));
13191324 }
13201325
1321 bool Changed = LowerTypeTestsModule(M, ClSummaryAction, &Summary).lower();
1326 bool Changed =
1327 LowerTypeTestsModule(
1328 M, ClSummaryAction == PassSummaryAction::Export ? &Summary : nullptr,
1329 ClSummaryAction == PassSummaryAction::Import ? &Summary : nullptr)
1330 .lower();
13221331
13231332 if (!ClWriteSummary.empty()) {
13241333 ExitOnError ExitOnErr("-lowertypetests-write-summary: " + ClWriteSummary +
13371346 bool LowerTypeTestsModule::lower() {
13381347 Function *TypeTestFunc =
13391348 M.getFunction(Intrinsic::getName(Intrinsic::type_test));
1340 if ((!TypeTestFunc || TypeTestFunc->use_empty()) &&
1341 Action != PassSummaryAction::Export)
1349 if ((!TypeTestFunc || TypeTestFunc->use_empty()) && !ExportSummary)
13421350 return false;
13431351
1344 if (Action == PassSummaryAction::Import) {
1352 if (ImportSummary) {
13451353 for (auto UI = TypeTestFunc->use_begin(), UE = TypeTestFunc->use_end();
13461354 UI != UE;) {
13471355 auto *CI = cast((*UI++).getUser());
14221430 }
14231431 }
14241432
1425 if (Action == PassSummaryAction::Export) {
1433 if (ExportSummary) {
14261434 DenseMap> MetadataByGUID;
14271435 for (auto &P : TypeIdInfo) {
14281436 if (auto *TypeId = dyn_cast(P.first))
14301438 TypeId);
14311439 }
14321440
1433 for (auto &P : *Summary) {
1441 for (auto &P : *ExportSummary) {
14341442 for (auto &S : P.second) {
14351443 auto *FS = dyn_cast(S.get());
14361444 if (!FS)
15011509
15021510 PreservedAnalyses LowerTypeTestsPass::run(Module &M,
15031511 ModuleAnalysisManager &AM) {
1504 bool Changed =
1505 LowerTypeTestsModule(M, PassSummaryAction::None, /*Summary=*/nullptr)
1506 .lower();
1512 bool Changed = LowerTypeTestsModule(M, /*ExportSummary=*/nullptr,
1513 /*ImportSummary=*/nullptr)
1514 .lower();
15071515 if (!Changed)
15081516 return PreservedAnalyses::all();
15091517 return PreservedAnalyses::none();
703703 PM.add(createGlobalSplitPass());
704704
705705 // Apply whole-program devirtualization and virtual constant propagation.
706 PM.add(createWholeProgramDevirtPass(
707 Summary ? PassSummaryAction::Export : PassSummaryAction::None, Summary));
706 PM.add(createWholeProgramDevirtPass(ExportSummary, nullptr));
708707
709708 // That's all we need at opt level 1.
710709 if (OptLevel == 1)
833832 if (VerifyInput)
834833 PM.add(createVerifierPass());
835834
836 if (Summary) {
835 if (ImportSummary) {
837836 // These passes import type identifier resolutions for whole-program
838837 // devirtualization and CFI. They must run early because other passes may
839838 // disturb the specific instruction patterns that these passes look for,
846845 //
847846 // Also, WPD has access to more precise information than ICP and can
848847 // devirtualize more effectively, so it should operate on the IR first.
849 PM.add(createWholeProgramDevirtPass(PassSummaryAction::Import, Summary));
850 PM.add(createLowerTypeTestsPass(PassSummaryAction::Import, Summary));
848 PM.add(createWholeProgramDevirtPass(nullptr, ImportSummary));
849 PM.add(createLowerTypeTestsPass(nullptr, ImportSummary));
851850 }
852851
853852 populateModulePassManager(PM);
874873 // Lower type metadata and the type.test intrinsic. This pass supports Clang's
875874 // control flow integrity mechanisms (-fsanitize=cfi*) and needs to run at
876875 // link time if CFI is enabled. The pass does nothing if CFI is disabled.
877 PM.add(createLowerTypeTestsPass(
878 Summary ? PassSummaryAction::Export : PassSummaryAction::None, Summary));
876 PM.add(createLowerTypeTestsPass(ExportSummary, nullptr));
879877
880878 if (OptLevel != 0)
881879 addLateLTOOptimizationPasses(PM);
372372 Module &M;
373373 function_ref AARGetter;
374374
375 PassSummaryAction Action;
376 ModuleSummaryIndex *Summary;
375 ModuleSummaryIndex *ExportSummary;
376 const ModuleSummaryIndex *ImportSummary;
377377
378378 IntegerType *Int8Ty;
379379 PointerType *Int8PtrTy;
396396 std::map NumUnsafeUsesForTypeTest;
397397
398398 DevirtModule(Module &M, function_ref AARGetter,
399 PassSummaryAction Action, ModuleSummaryIndex *Summary)
400 : M(M), AARGetter(AARGetter), Action(Action), Summary(Summary),
401 Int8Ty(Type::getInt8Ty(M.getContext())),
399 ModuleSummaryIndex *ExportSummary,
400 const ModuleSummaryIndex *ImportSummary)
401 : M(M), AARGetter(AARGetter), ExportSummary(ExportSummary),
402 ImportSummary(ImportSummary), Int8Ty(Type::getInt8Ty(M.getContext())),
402403 Int8PtrTy(Type::getInt8PtrTy(M.getContext())),
403404 Int32Ty(Type::getInt32Ty(M.getContext())),
404405 Int64Ty(Type::getInt64Ty(M.getContext())),
405406 IntPtrTy(M.getDataLayout().getIntPtrType(M.getContext(), 0)),
406 RemarksEnabled(areRemarksEnabled()) {}
407 RemarksEnabled(areRemarksEnabled()) {
408 assert(!(ExportSummary && ImportSummary));
409 }
407410
408411 bool areRemarksEnabled();
409412
487490
488491 bool UseCommandLine = false;
489492
490 PassSummaryAction Action;
491 ModuleSummaryIndex *Summary;
493 ModuleSummaryIndex *ExportSummary;
494 const ModuleSummaryIndex *ImportSummary;
492495
493496 WholeProgramDevirt() : ModulePass(ID), UseCommandLine(true) {
494497 initializeWholeProgramDevirtPass(*PassRegistry::getPassRegistry());
495498 }
496499
497 WholeProgramDevirt(PassSummaryAction Action, ModuleSummaryIndex *Summary)
498 : ModulePass(ID), Action(Action), Summary(Summary) {
500 WholeProgramDevirt(ModuleSummaryIndex *ExportSummary,
501 const ModuleSummaryIndex *ImportSummary)
502 : ModulePass(ID), ExportSummary(ExportSummary),
503 ImportSummary(ImportSummary) {
499504 initializeWholeProgramDevirtPass(*PassRegistry::getPassRegistry());
500505 }
501506
504509 return false;
505510 if (UseCommandLine)
506511 return DevirtModule::runForTesting(M, LegacyAARGetter(*this));
507 return DevirtModule(M, LegacyAARGetter(*this), Action, Summary).run();
512 return DevirtModule(M, LegacyAARGetter(*this), ExportSummary, ImportSummary)
513 .run();
508514 }
509515
510516 void getAnalysisUsage(AnalysisUsage &AU) const override {
523529 "Whole program devirtualization", false, false)
524530 char WholeProgramDevirt::ID = 0;
525531
526 ModulePass *llvm::createWholeProgramDevirtPass(PassSummaryAction Action,
527 ModuleSummaryIndex *Summary) {
528 return new WholeProgramDevirt(Action, Summary);
532 ModulePass *
533 llvm::createWholeProgramDevirtPass(ModuleSummaryIndex *ExportSummary,
534 const ModuleSummaryIndex *ImportSummary) {
535 return new WholeProgramDevirt(ExportSummary, ImportSummary);
529536 }
530537
531538 PreservedAnalyses WholeProgramDevirtPass::run(Module &M,
534541 auto AARGetter = [&](Function &F) -> AAResults & {
535542 return FAM.getResult(F);
536543 };
537 if (!DevirtModule(M, AARGetter, PassSummaryAction::None, nullptr).run())
544 if (!DevirtModule(M, AARGetter, nullptr, nullptr).run())
538545 return PreservedAnalyses::all();
539546 return PreservedAnalyses::none();
540547 }
556563 ExitOnErr(errorCodeToError(In.error()));
557564 }
558565
559 bool Changed = DevirtModule(M, AARGetter, ClSummaryAction, &Summary).run();
566 bool Changed =
567 DevirtModule(
568 M, AARGetter,
569 ClSummaryAction == PassSummaryAction::Export ? &Summary : nullptr,
570 ClSummaryAction == PassSummaryAction::Import ? &Summary : nullptr)
571 .run();
560572
561573 if (!ClWriteSummary.empty()) {
562574 ExitOnError ExitOnErr(
11961208
11971209 void DevirtModule::importResolution(VTableSlot Slot, VTableSlotInfo &SlotInfo) {
11981210 const TypeIdSummary *TidSummary =
1199 Summary->getTypeIdSummary(cast(Slot.TypeID)->getString());
1211 ImportSummary->getTypeIdSummary(cast(Slot.TypeID)->getString());
12001212 if (!TidSummary)
12011213 return;
12021214 auto ResI = TidSummary->WPDRes.find(Slot.ByteOffset);
12691281 // Normally if there are no users of the devirtualization intrinsics in the
12701282 // module, this pass has nothing to do. But if we are exporting, we also need
12711283 // to handle any users that appear only in the function summaries.
1272 if (Action != PassSummaryAction::Export &&
1284 if (!ExportSummary &&
12731285 (!TypeTestFunc || TypeTestFunc->use_empty() || !AssumeFunc ||
12741286 AssumeFunc->use_empty()) &&
12751287 (!TypeCheckedLoadFunc || TypeCheckedLoadFunc->use_empty()))
12811293 if (TypeCheckedLoadFunc)
12821294 scanTypeCheckedLoadUsers(TypeCheckedLoadFunc);
12831295
1284 if (Action == PassSummaryAction::Import) {
1296 if (ImportSummary) {
12851297 for (auto &S : CallSlots)
12861298 importResolution(S.first, S.second);
12871299
13001312 return true;
13011313
13021314 // Collect information from summary about which calls to try to devirtualize.
1303 if (Action == PassSummaryAction::Export) {
1315 if (ExportSummary) {
13041316 DenseMap> MetadataByGUID;
13051317 for (auto &P : TypeIdMap) {
13061318 if (auto *TypeId = dyn_cast(P.first))
13081320 TypeId);
13091321 }
13101322
1311 for (auto &P : *Summary) {
1323 for (auto &P : *ExportSummary) {
13121324 for (auto &S : P.second) {
13131325 auto *FS = dyn_cast(S.get());
13141326 if (!FS)
13571369 if (tryFindVirtualCallTargets(TargetsForSlot, TypeIdMap[S.first.TypeID],
13581370 S.first.ByteOffset)) {
13591371 WholeProgramDevirtResolution *Res = nullptr;
1360 if (Action == PassSummaryAction::Export && isa(S.first.TypeID))
1361 Res = &Summary
1372 if (ExportSummary && isa(S.first.TypeID))
1373 Res = &ExportSummary
13621374 ->getOrInsertTypeIdSummary(
13631375 cast(S.first.TypeID)->getString())
13641376 .WPDRes[S.first.ByteOffset];
13781390 // intrinsics were *not* devirtualized, we need to add the resulting
13791391 // llvm.type.test intrinsics to the function summaries so that the
13801392 // LowerTypeTests pass will export them.
1381 if (Action == PassSummaryAction::Export && isa(S.first.TypeID)) {
1393 if (ExportSummary && isa(S.first.TypeID)) {
13821394 auto GUID =
13831395 GlobalValue::getGUID(cast(S.first.TypeID)->getString());
13841396 for (auto FS : S.second.CSInfo.SummaryTypeCheckedLoadUsers)