Skip to content

Commit 09a704c

Browse files
[LTO] Ignore unreachable virtual functions in WPD in hybrid LTO.
Differential Revision: https://reviews.llvm.org/D115492
1 parent 1695dd1 commit 09a704c

21 files changed

+452
-40
lines changed

clang/test/CodeGen/thinlto-distributed-cfi-devirt.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
; Round trip it through llvm-as
3737
; RUN: llvm-dis %t.o.thinlto.bc -o - | llvm-as -o - | llvm-dis -o - | FileCheck %s --check-prefix=CHECK-DIS
3838
; CHECK-DIS: ^0 = module: (path: "{{.*}}thinlto-distributed-cfi-devirt.ll.tmp.o", hash: ({{.*}}, {{.*}}, {{.*}}, {{.*}}, {{.*}}))
39-
; CHECK-DIS: ^1 = gv: (guid: 8346051122425466633, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 0, canAutoHide: 0), insts: 18, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1), typeIdInfo: (typeTests: (^2), typeCheckedLoadVCalls: (vFuncId: (^2, offset: 8), vFuncId: (^2, offset: 0))))))
39+
; CHECK-DIS: ^1 = gv: (guid: 8346051122425466633, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 0, canAutoHide: 0), insts: 18, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeTests: (^2), typeCheckedLoadVCalls: (vFuncId: (^2, offset: 8), vFuncId: (^2, offset: 0))))))
4040
; CHECK-DIS: ^2 = typeid: (name: "_ZTS1A", summary: (typeTestRes: (kind: allOnes, sizeM1BitWidth: 7), wpdResolutions: ((offset: 0, wpdRes: (kind: branchFunnel)), (offset: 8, wpdRes: (kind: singleImpl, singleImplName: "_ZN1A1nEi"))))) ; guid = 7004155349499253778
4141

4242
; RUN: %clang_cc1 -triple x86_64-grtev4-linux-gnu \

clang/test/CodeGen/thinlto-distributed-cfi.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
; Round trip it through llvm-as
2525
; RUN: llvm-dis %t.o.thinlto.bc -o - | llvm-as -o - | llvm-dis -o - | FileCheck %s --check-prefix=CHECK-DIS
2626
; CHECK-DIS: ^0 = module: (path: "{{.*}}thinlto-distributed-cfi.ll.tmp.o", hash: ({{.*}}, {{.*}}, {{.*}}, {{.*}}, {{.*}}))
27-
; CHECK-DIS: ^1 = gv: (guid: 8346051122425466633, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 0, canAutoHide: 0), insts: 7, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 1, mayThrow: 0, hasUnknownCall: 0), typeIdInfo: (typeTests: (^2)))))
27+
; CHECK-DIS: ^1 = gv: (guid: 8346051122425466633, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 0, canAutoHide: 0), insts: 7, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 1, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), typeIdInfo: (typeTests: (^2)))))
2828
; CHECK-DIS: ^2 = typeid: (name: "_ZTS1A", summary: (typeTestRes: (kind: single, sizeM1BitWidth: 0))) ; guid = 7004155349499253778
2929

3030
; RUN: %clang_cc1 -triple x86_64-grtev4-linux-gnu \

clang/test/CodeGen/thinlto-funcattr-prop.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
;; Summary for call_extern. Note that llvm-lto2 writes out the index before propagation occurs so call_extern doesn't have its flags updated.
1818
; CHECK-INDEX: ^2 = gv: (guid: 13959900437860518209, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 1, canAutoHide: 0), insts: 2, calls: ((callee: ^3)))))
1919
;; Summary for extern
20-
; CHECK-INDEX: ^3 = gv: (guid: 14959766916849974397, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 0, canAutoHide: 0), insts: 1, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 1, mayThrow: 0, hasUnknownCall: 0))))
20+
; CHECK-INDEX: ^3 = gv: (guid: 14959766916849974397, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 0, canAutoHide: 0), insts: 1, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 1, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0))))
2121

2222
;--- a.ll
2323
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"

llvm/include/llvm/AsmParser/LLToken.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,7 @@ enum Kind {
407407
kw_noUnwind,
408408
kw_mayThrow,
409409
kw_hasUnknownCall,
410+
kw_mustBeUnreachable,
410411
kw_calls,
411412
kw_callee,
412413
kw_params,

llvm/include/llvm/IR/ModuleSummaryIndex.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,13 @@ class FunctionSummary : public GlobalValueSummary {
581581
// If there are calls to unknown targets (e.g. indirect)
582582
unsigned HasUnknownCall : 1;
583583

584+
// Indicate if a function must be an unreachable function.
585+
//
586+
// This bit is sufficient but not necessary;
587+
// if this bit is on, the function must be regarded as unreachable;
588+
// if this bit is off, the function might be reachable or unreachable.
589+
unsigned MustBeUnreachable : 1;
590+
584591
FFlags &operator&=(const FFlags &RHS) {
585592
this->ReadNone &= RHS.ReadNone;
586593
this->ReadOnly &= RHS.ReadOnly;
@@ -591,13 +598,15 @@ class FunctionSummary : public GlobalValueSummary {
591598
this->NoUnwind &= RHS.NoUnwind;
592599
this->MayThrow &= RHS.MayThrow;
593600
this->HasUnknownCall &= RHS.HasUnknownCall;
601+
this->MustBeUnreachable &= RHS.MustBeUnreachable;
594602
return *this;
595603
}
596604

597605
bool anyFlagSet() {
598606
return this->ReadNone | this->ReadOnly | this->NoRecurse |
599607
this->ReturnDoesNotAlias | this->NoInline | this->AlwaysInline |
600-
this->NoUnwind | this->MayThrow | this->HasUnknownCall;
608+
this->NoUnwind | this->MayThrow | this->HasUnknownCall |
609+
this->MustBeUnreachable;
601610
}
602611

603612
operator std::string() {
@@ -613,6 +622,7 @@ class FunctionSummary : public GlobalValueSummary {
613622
OS << ", noUnwind: " << this->NoUnwind;
614623
OS << ", mayThrow: " << this->MayThrow;
615624
OS << ", hasUnknownCall: " << this->HasUnknownCall;
625+
OS << ", mustBeUnreachable: " << this->MustBeUnreachable;
616626
OS << ")";
617627
return OS.str();
618628
}

llvm/lib/Analysis/ModuleSummaryAnalysis.cpp

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,26 @@ static bool isNonVolatileStore(const Instruction *I) {
234234
return false;
235235
}
236236

237+
// Returns true if `F` must be an unreachable function.
238+
//
239+
// Note if this helper function returns true, `F` is guaranteed
240+
// to be unreachable; if it returns false, `F` might still
241+
// be unreachable but not covered by this helper function.
242+
static bool mustBeUnreachableFunction(const Function &F) {
243+
if (!F.empty()) {
244+
const BasicBlock &entryBlock = F.getEntryBlock();
245+
// A function must be unreachable if its entry block
246+
// ends with an 'unreachable'.
247+
if (!entryBlock.empty()) {
248+
const Instruction *inst = &(*entryBlock.rbegin());
249+
if (inst->getOpcode() == Instruction::Unreachable) {
250+
return true;
251+
}
252+
}
253+
}
254+
return false;
255+
}
256+
237257
static void computeFunctionSummary(
238258
ModuleSummaryIndex &Index, const Module &M, const Function &F,
239259
BlockFrequencyInfo *BFI, ProfileSummaryInfo *PSI, DominatorTree &DT,
@@ -488,7 +508,8 @@ static void computeFunctionSummary(
488508
// Don't try to import functions with noinline attribute.
489509
F.getAttributes().hasFnAttr(Attribute::NoInline),
490510
F.hasFnAttribute(Attribute::AlwaysInline),
491-
F.hasFnAttribute(Attribute::NoUnwind), MayThrow, HasUnknownCall};
511+
F.hasFnAttribute(Attribute::NoUnwind), MayThrow, HasUnknownCall,
512+
mustBeUnreachableFunction(F)};
492513
std::vector<FunctionSummary::ParamAccess> ParamAccesses;
493514
if (auto *SSI = GetSSICallback(F))
494515
ParamAccesses = SSI->getParamAccesses(Index);
@@ -737,7 +758,8 @@ ModuleSummaryIndex llvm::buildModuleSummaryIndex(
737758
F->hasFnAttribute(Attribute::AlwaysInline),
738759
F->hasFnAttribute(Attribute::NoUnwind),
739760
/* MayThrow */ true,
740-
/* HasUnknownCall */ true},
761+
/* HasUnknownCall */ true,
762+
/* MustBeUnreachable */ false},
741763
/*EntryCount=*/0, ArrayRef<ValueInfo>{},
742764
ArrayRef<FunctionSummary::EdgeTy>{},
743765
ArrayRef<GlobalValue::GUID>{},

llvm/lib/AsmParser/LLLexer.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -773,6 +773,7 @@ lltok::Kind LLLexer::LexIdentifier() {
773773
KEYWORD(noUnwind);
774774
KEYWORD(mayThrow);
775775
KEYWORD(hasUnknownCall);
776+
KEYWORD(mustBeUnreachable);
776777
KEYWORD(calls);
777778
KEYWORD(callee);
778779
KEYWORD(params);

llvm/lib/AsmParser/LLParser.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8534,6 +8534,7 @@ bool LLParser::parseFlag(unsigned &Val) {
85348534
/// [',' 'noUnwind' ':' Flag]? ')'
85358535
/// [',' 'mayThrow' ':' Flag]? ')'
85368536
/// [',' 'hasUnknownCall' ':' Flag]? ')'
8537+
/// [',' 'mustBeUnreachable' ':' Flag]? ')'
85378538

85388539
bool LLParser::parseOptionalFFlags(FunctionSummary::FFlags &FFlags) {
85398540
assert(Lex.getKind() == lltok::kw_funcFlags);
@@ -8600,6 +8601,12 @@ bool LLParser::parseOptionalFFlags(FunctionSummary::FFlags &FFlags) {
86008601
return true;
86018602
FFlags.HasUnknownCall = Val;
86028603
break;
8604+
case lltok::kw_mustBeUnreachable:
8605+
Lex.Lex();
8606+
if (parseToken(lltok::colon, "expected ':'") || parseFlag(Val))
8607+
return true;
8608+
FFlags.MustBeUnreachable = Val;
8609+
break;
86038610
default:
86048611
return error(Lex.getLoc(), "expected function flag type");
86058612
}

llvm/lib/Bitcode/Reader/BitcodeReader.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -932,6 +932,7 @@ static FunctionSummary::FFlags getDecodedFFlags(uint64_t RawFlags) {
932932
Flags.NoUnwind = (RawFlags >> 6) & 0x1;
933933
Flags.MayThrow = (RawFlags >> 7) & 0x1;
934934
Flags.HasUnknownCall = (RawFlags >> 8) & 0x1;
935+
Flags.MustBeUnreachable = (RawFlags >> 9) & 0x1;
935936
return Flags;
936937
}
937938

llvm/lib/Bitcode/Writer/BitcodeWriter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1066,6 +1066,7 @@ static uint64_t getEncodedFFlags(FunctionSummary::FFlags Flags) {
10661066
RawFlags |= (Flags.NoUnwind << 6);
10671067
RawFlags |= (Flags.MayThrow << 7);
10681068
RawFlags |= (Flags.HasUnknownCall << 8);
1069+
RawFlags |= (Flags.MustBeUnreachable << 9);
10691070
return RawFlags;
10701071
}
10711072

0 commit comments

Comments
 (0)