Changeset View
Changeset View
Standalone View
Standalone View
llvm/lib/Transforms/IPO/LowerTypeTests.cpp
Show First 20 Lines • Show All 376 Lines • ▼ Show 20 Lines | struct ScopedSaveAliaseesAndUsed { | ||||
} | } | ||||
}; | }; | ||||
class LowerTypeTestsModule { | class LowerTypeTestsModule { | ||||
Module &M; | Module &M; | ||||
ModuleSummaryIndex *ExportSummary; | ModuleSummaryIndex *ExportSummary; | ||||
const ModuleSummaryIndex *ImportSummary; | const ModuleSummaryIndex *ImportSummary; | ||||
// Set when the client has invoked this to simply drop all type test assume | |||||
// sequences. | |||||
bool DropTypeTests; | |||||
Triple::ArchType Arch; | Triple::ArchType Arch; | ||||
Triple::OSType OS; | Triple::OSType OS; | ||||
Triple::ObjectFormatType ObjectFormat; | Triple::ObjectFormatType ObjectFormat; | ||||
IntegerType *Int1Ty = Type::getInt1Ty(M.getContext()); | IntegerType *Int1Ty = Type::getInt1Ty(M.getContext()); | ||||
IntegerType *Int8Ty = Type::getInt8Ty(M.getContext()); | IntegerType *Int8Ty = Type::getInt8Ty(M.getContext()); | ||||
PointerType *Int8PtrTy = Type::getInt8PtrTy(M.getContext()); | PointerType *Int8PtrTy = Type::getInt8PtrTy(M.getContext()); | ||||
▲ Show 20 Lines • Show All 102 Lines • ▼ Show 20 Lines | class LowerTypeTestsModule { | ||||
void replaceCfiUses(Function *Old, Value *New, bool IsJumpTableCanonical); | void replaceCfiUses(Function *Old, Value *New, bool IsJumpTableCanonical); | ||||
/// replaceDirectCalls - Go through the uses list for this definition and | /// replaceDirectCalls - Go through the uses list for this definition and | ||||
/// replace each use, which is a direct function call. | /// replace each use, which is a direct function call. | ||||
void replaceDirectCalls(Value *Old, Value *New); | void replaceDirectCalls(Value *Old, Value *New); | ||||
public: | public: | ||||
LowerTypeTestsModule(Module &M, ModuleSummaryIndex *ExportSummary, | LowerTypeTestsModule(Module &M, ModuleSummaryIndex *ExportSummary, | ||||
const ModuleSummaryIndex *ImportSummary); | const ModuleSummaryIndex *ImportSummary, | ||||
bool DropTypeTests); | |||||
bool lower(); | bool lower(); | ||||
// Lower the module using the action and summary passed as command line | // Lower the module using the action and summary passed as command line | ||||
// arguments. For testing purposes only. | // arguments. For testing purposes only. | ||||
static bool runForTesting(Module &M); | static bool runForTesting(Module &M); | ||||
}; | }; | ||||
struct LowerTypeTests : public ModulePass { | struct LowerTypeTests : public ModulePass { | ||||
static char ID; | static char ID; | ||||
bool UseCommandLine = false; | bool UseCommandLine = false; | ||||
ModuleSummaryIndex *ExportSummary; | ModuleSummaryIndex *ExportSummary; | ||||
const ModuleSummaryIndex *ImportSummary; | const ModuleSummaryIndex *ImportSummary; | ||||
bool DropTypeTests; | |||||
LowerTypeTests() : ModulePass(ID), UseCommandLine(true) { | LowerTypeTests() : ModulePass(ID), UseCommandLine(true) { | ||||
initializeLowerTypeTestsPass(*PassRegistry::getPassRegistry()); | initializeLowerTypeTestsPass(*PassRegistry::getPassRegistry()); | ||||
} | } | ||||
LowerTypeTests(ModuleSummaryIndex *ExportSummary, | LowerTypeTests(ModuleSummaryIndex *ExportSummary, | ||||
const ModuleSummaryIndex *ImportSummary) | const ModuleSummaryIndex *ImportSummary, bool DropTypeTests) | ||||
: ModulePass(ID), ExportSummary(ExportSummary), | : ModulePass(ID), ExportSummary(ExportSummary), | ||||
ImportSummary(ImportSummary) { | ImportSummary(ImportSummary), DropTypeTests(DropTypeTests) { | ||||
initializeLowerTypeTestsPass(*PassRegistry::getPassRegistry()); | initializeLowerTypeTestsPass(*PassRegistry::getPassRegistry()); | ||||
} | } | ||||
bool runOnModule(Module &M) override { | bool runOnModule(Module &M) override { | ||||
if (UseCommandLine) | if (UseCommandLine) | ||||
return LowerTypeTestsModule::runForTesting(M); | return LowerTypeTestsModule::runForTesting(M); | ||||
return LowerTypeTestsModule(M, ExportSummary, ImportSummary).lower(); | return LowerTypeTestsModule(M, ExportSummary, ImportSummary, DropTypeTests) | ||||
.lower(); | |||||
} | } | ||||
}; | }; | ||||
} // end anonymous namespace | } // end anonymous namespace | ||||
char LowerTypeTests::ID = 0; | char LowerTypeTests::ID = 0; | ||||
INITIALIZE_PASS(LowerTypeTests, "lowertypetests", "Lower type metadata", false, | INITIALIZE_PASS(LowerTypeTests, "lowertypetests", "Lower type metadata", false, | ||||
false) | false) | ||||
ModulePass * | ModulePass * | ||||
llvm::createLowerTypeTestsPass(ModuleSummaryIndex *ExportSummary, | llvm::createLowerTypeTestsPass(ModuleSummaryIndex *ExportSummary, | ||||
const ModuleSummaryIndex *ImportSummary) { | const ModuleSummaryIndex *ImportSummary, | ||||
return new LowerTypeTests(ExportSummary, ImportSummary); | bool DropTypeTests) { | ||||
return new LowerTypeTests(ExportSummary, ImportSummary, DropTypeTests); | |||||
} | } | ||||
/// Build a bit set for TypeId using the object layouts in | /// Build a bit set for TypeId using the object layouts in | ||||
/// GlobalLayout. | /// GlobalLayout. | ||||
BitSetInfo LowerTypeTestsModule::buildBitSet( | BitSetInfo LowerTypeTestsModule::buildBitSet( | ||||
Metadata *TypeId, | Metadata *TypeId, | ||||
const DenseMap<GlobalTypeMember *, uint64_t> &GlobalLayout) { | const DenseMap<GlobalTypeMember *, uint64_t> &GlobalLayout) { | ||||
BitSetBuilder BSB; | BitSetBuilder BSB; | ||||
▲ Show 20 Lines • Show All 1,093 Lines • ▼ Show 20 Lines | if (IsGlobalSet) | ||||
buildBitSetsFromGlobalVariables(TypeIds, OrderedGTMs); | buildBitSetsFromGlobalVariables(TypeIds, OrderedGTMs); | ||||
else | else | ||||
buildBitSetsFromFunctions(TypeIds, OrderedGTMs); | buildBitSetsFromFunctions(TypeIds, OrderedGTMs); | ||||
} | } | ||||
/// Lower all type tests in this module. | /// Lower all type tests in this module. | ||||
LowerTypeTestsModule::LowerTypeTestsModule( | LowerTypeTestsModule::LowerTypeTestsModule( | ||||
Module &M, ModuleSummaryIndex *ExportSummary, | Module &M, ModuleSummaryIndex *ExportSummary, | ||||
const ModuleSummaryIndex *ImportSummary) | const ModuleSummaryIndex *ImportSummary, bool DropTypeTests) | ||||
: M(M), ExportSummary(ExportSummary), ImportSummary(ImportSummary) { | : M(M), ExportSummary(ExportSummary), ImportSummary(ImportSummary), | ||||
DropTypeTests(DropTypeTests) { | |||||
assert(!(ExportSummary && ImportSummary)); | assert(!(ExportSummary && ImportSummary)); | ||||
Triple TargetTriple(M.getTargetTriple()); | Triple TargetTriple(M.getTargetTriple()); | ||||
Arch = TargetTriple.getArch(); | Arch = TargetTriple.getArch(); | ||||
OS = TargetTriple.getOS(); | OS = TargetTriple.getOS(); | ||||
ObjectFormat = TargetTriple.getObjectFormat(); | ObjectFormat = TargetTriple.getObjectFormat(); | ||||
} | } | ||||
bool LowerTypeTestsModule::runForTesting(Module &M) { | bool LowerTypeTestsModule::runForTesting(Module &M) { | ||||
Show All 10 Lines | if (!ClReadSummary.empty()) { | ||||
yaml::Input In(ReadSummaryFile->getBuffer()); | yaml::Input In(ReadSummaryFile->getBuffer()); | ||||
In >> Summary; | In >> Summary; | ||||
ExitOnErr(errorCodeToError(In.error())); | ExitOnErr(errorCodeToError(In.error())); | ||||
} | } | ||||
bool Changed = | bool Changed = | ||||
LowerTypeTestsModule( | LowerTypeTestsModule( | ||||
M, ClSummaryAction == PassSummaryAction::Export ? &Summary : nullptr, | M, ClSummaryAction == PassSummaryAction::Export ? &Summary : nullptr, | ||||
ClSummaryAction == PassSummaryAction::Import ? &Summary : nullptr) | ClSummaryAction == PassSummaryAction::Import ? &Summary : nullptr, | ||||
/*DropTypeTests*/ false) | |||||
.lower(); | .lower(); | ||||
if (!ClWriteSummary.empty()) { | if (!ClWriteSummary.empty()) { | ||||
ExitOnError ExitOnErr("-lowertypetests-write-summary: " + ClWriteSummary + | ExitOnError ExitOnErr("-lowertypetests-write-summary: " + ClWriteSummary + | ||||
": "); | ": "); | ||||
std::error_code EC; | std::error_code EC; | ||||
raw_fd_ostream OS(ClWriteSummary, EC, sys::fs::OF_Text); | raw_fd_ostream OS(ClWriteSummary, EC, sys::fs::OF_Text); | ||||
ExitOnErr(errorCodeToError(EC)); | ExitOnErr(errorCodeToError(EC)); | ||||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | for (auto *C : Constants) | ||||
C->handleOperandChange(Old, New); | C->handleOperandChange(Old, New); | ||||
} | } | ||||
void LowerTypeTestsModule::replaceDirectCalls(Value *Old, Value *New) { | void LowerTypeTestsModule::replaceDirectCalls(Value *Old, Value *New) { | ||||
Old->replaceUsesWithIf(New, [](Use &U) { return isDirectCall(U); }); | Old->replaceUsesWithIf(New, [](Use &U) { return isDirectCall(U); }); | ||||
} | } | ||||
bool LowerTypeTestsModule::lower() { | bool LowerTypeTestsModule::lower() { | ||||
Function *TypeTestFunc = | |||||
M.getFunction(Intrinsic::getName(Intrinsic::type_test)); | |||||
if (DropTypeTests && TypeTestFunc) { | |||||
for (auto UI = TypeTestFunc->use_begin(), UE = TypeTestFunc->use_end(); | |||||
UI != UE;) { | |||||
auto *CI = cast<CallInst>((*UI++).getUser()); | |||||
// Find and erase llvm.assume intrinsics for this llvm.type.test call. | |||||
for (auto CIU = CI->use_begin(), CIUE = CI->use_end(); CIU != CIUE;) { | |||||
if (auto *AssumeCI = dyn_cast<CallInst>((*CIU++).getUser())) { | |||||
Function *F = AssumeCI->getCalledFunction(); | |||||
if (F && F->getIntrinsicID() == Intrinsic::assume) | |||||
AssumeCI->eraseFromParent(); | |||||
} | |||||
evgeny777: Fold identical code blocks | |||||
After looking at this code again, I have changed it a bit. We should only be removing assumes that are consuming type test instructions. I have changed this (which removes the redundancy in any case). I also added a check to the test mentioned earlier for this handling (clang/test/CodeGenCXX/thinlto-distributed-type-metadata.cpp) to ensure we don't remove unrelated llvm.assume. tejohnson: After looking at this code again, I have changed it a bit. We should only be removing assumes… | |||||
} | |||||
CI->eraseFromParent(); | |||||
} | |||||
// We have deleted the type intrinsics, so we no longer have enough | |||||
// information to reason about the liveness of virtual function pointers | |||||
// in GlobalDCE. | |||||
for (GlobalVariable &GV : M.globals()) | |||||
GV.eraseMetadata(LLVMContext::MD_vcall_visibility); | |||||
return true; | |||||
} | |||||
// If only some of the modules were split, we cannot correctly perform | // If only some of the modules were split, we cannot correctly perform | ||||
// this transformation. We already checked for the presense of type tests | // this transformation. We already checked for the presense of type tests | ||||
// with partially split modules during the thin link, and would have emitted | // with partially split modules during the thin link, and would have emitted | ||||
// an error if any were found, so here we can simply return. | // an error if any were found, so here we can simply return. | ||||
if ((ExportSummary && ExportSummary->partiallySplitLTOUnits()) || | if ((ExportSummary && ExportSummary->partiallySplitLTOUnits()) || | ||||
(ImportSummary && ImportSummary->partiallySplitLTOUnits())) | (ImportSummary && ImportSummary->partiallySplitLTOUnits())) | ||||
return false; | return false; | ||||
Function *TypeTestFunc = | |||||
M.getFunction(Intrinsic::getName(Intrinsic::type_test)); | |||||
Function *ICallBranchFunnelFunc = | Function *ICallBranchFunnelFunc = | ||||
M.getFunction(Intrinsic::getName(Intrinsic::icall_branch_funnel)); | M.getFunction(Intrinsic::getName(Intrinsic::icall_branch_funnel)); | ||||
if ((!TypeTestFunc || TypeTestFunc->use_empty()) && | if ((!TypeTestFunc || TypeTestFunc->use_empty()) && | ||||
(!ICallBranchFunnelFunc || ICallBranchFunnelFunc->use_empty()) && | (!ICallBranchFunnelFunc || ICallBranchFunnelFunc->use_empty()) && | ||||
!ExportSummary && !ImportSummary) | !ExportSummary && !ImportSummary) | ||||
return false; | return false; | ||||
if (ImportSummary) { | if (ImportSummary) { | ||||
▲ Show 20 Lines • Show All 420 Lines • ▼ Show 20 Lines | if (ExportSummary) { | ||||
} | } | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
PreservedAnalyses LowerTypeTestsPass::run(Module &M, | PreservedAnalyses LowerTypeTestsPass::run(Module &M, | ||||
ModuleAnalysisManager &AM) { | ModuleAnalysisManager &AM) { | ||||
bool Changed = LowerTypeTestsModule(M, ExportSummary, ImportSummary).lower(); | bool Changed = | ||||
LowerTypeTestsModule(M, ExportSummary, ImportSummary, DropTypeTests) | |||||
.lower(); | |||||
if (!Changed) | if (!Changed) | ||||
return PreservedAnalyses::all(); | return PreservedAnalyses::all(); | ||||
return PreservedAnalyses::none(); | return PreservedAnalyses::none(); | ||||
} | } |
Fold identical code blocks