[WebAssembly] Avoid unused function imports in PIC mode

In PIC mode we import function address via `GOT.mem` imports but for
direct function calls we still import the first class function.
However, if the function is never directly called we can avoid the first
class import completely.

Differential Revision: https://reviews.llvm.org/D108345
This commit is contained in:
Sam Clegg 2021-08-18 22:20:55 -04:00
parent a9095f005f
commit e4888be74e
4 changed files with 22 additions and 19 deletions

View File

@ -167,10 +167,6 @@ get_local_func_address:
# CHECK-NEXT: Kind: GLOBAL
# CHECK-NEXT: GlobalType: I32
# CHECK-NEXT: GlobalMutable: false
# CHECK-NEXT: - Module: env
# CHECK-NEXT: Field: func_external
# CHECK-NEXT: Kind: FUNCTION
# CHECK-NEXT: SigIndex: 1
# CHECK-NEXT: - Module: GOT.mem
# CHECK-NEXT: Field: indirect_func
# CHECK-NEXT: Kind: GLOBAL
@ -197,7 +193,7 @@ get_local_func_address:
# CHECK-NEXT: Exports:
# CHECK-NEXT: - Name: __wasm_call_ctors
# CHECK-NEXT: Kind: FUNCTION
# CHECK-NEXT: Index: 1
# CHECK-NEXT: Index: 0
# check for elem segment initialized with __table_base global as offset
@ -206,17 +202,17 @@ get_local_func_address:
# CHECK-NEXT: - Offset:
# CHECK-NEXT: Opcode: GLOBAL_GET
# CHECK-NEXT: Index: 2
# CHECK-NEXT: Functions: [ 4, 3 ]
# CHECK-NEXT: Functions: [ 3, 2 ]
# check the generated code in __wasm_call_ctors and __wasm_apply_data_relocs functions
# TODO(sbc): Disassemble and verify instructions.
# CHECK: - Type: CODE
# CHECK-NEXT: Functions:
# CHECK-NEXT: - Index: 1
# CHECK-NEXT: - Index: 0
# CHECK-NEXT: Locals: []
# CHECK-NEXT: Body: 10020B
# CHECK-NEXT: - Index: 2
# CHECK-NEXT: Body: 10010B
# CHECK-NEXT: - Index: 1
# CHECK-NEXT: Locals: []
# CHECK-NEXT: Body: 230141046A2304360200230141086A230241016A3602002301410C6A230141006A360200230141106A2305360200230141146A230641046A3602000B

View File

@ -174,10 +174,6 @@ get_local_func_address:
# CHECK-NEXT: Kind: GLOBAL
# CHECK-NEXT: GlobalType: I32
# CHECK-NEXT: GlobalMutable: false
# CHECK-NEXT: - Module: env
# CHECK-NEXT: Field: func_external
# CHECK-NEXT: Kind: FUNCTION
# CHECK-NEXT: SigIndex: 1
# CHECK-NEXT: - Module: GOT.mem
# CHECK-NEXT: Field: indirect_func
# CHECK-NEXT: Kind: GLOBAL
@ -204,7 +200,7 @@ get_local_func_address:
# CHECK-NEXT: Exports:
# CHECK-NEXT: - Name: __wasm_call_ctors
# CHECK-NEXT: Kind: FUNCTION
# CHECK-NEXT: Index: 1
# CHECK-NEXT: Index: 0
# check for elem segment initialized with __table_base global as offset
@ -213,17 +209,17 @@ get_local_func_address:
# CHECK-NEXT: - Offset:
# CHECK-NEXT: Opcode: GLOBAL_GET
# CHECK-NEXT: Index: 3
# CHECK-NEXT: Functions: [ 4, 3 ]
# CHECK-NEXT: Functions: [ 3, 2 ]
# check the generated code in __wasm_call_ctors and __wasm_apply_data_relocs functions
# TODO(sbc): Disassemble and verify instructions.
# CHECK: - Type: CODE
# CHECK-NEXT: Functions:
# CHECK-NEXT: - Index: 1
# CHECK-NEXT: - Index: 0
# CHECK-NEXT: Locals: []
# CHECK-NEXT: Body: 10020B
# CHECK-NEXT: - Index: 2
# CHECK-NEXT: Body: 10010B
# CHECK-NEXT: - Index: 1
# CHECK-NEXT: Locals: []
# CHECK-NEXT: Body: 230142047C23053702002301420C7C230242017C370200230142147C230141006A360200230142187C2306370200230142207C230741046A3602000B

View File

@ -548,9 +548,12 @@ Symbol *SymbolTable::addUndefinedFunction(StringRef name,
else if (getFunctionVariant(s, sig, file, &s))
replaceSym();
}
if (existingUndefined)
if (existingUndefined) {
setImportAttributes(existingUndefined, importName, importModule, flags,
file);
if (isCalledDirectly)
existingUndefined->isCalledDirectly = true;
}
}
return s;

View File

@ -562,6 +562,14 @@ static bool shouldImport(Symbol *sym) {
if (isa<DataSymbol>(sym))
return false;
// In PIC mode we only need to import functions when they are called directly.
// Indirect usage all goes via GOT imports.
if (config->isPic) {
if (auto *f = dyn_cast<UndefinedFunction>(sym))
if (!f->isCalledDirectly)
return false;
}
if (config->isPic || config->relocatable || config->importUndefined)
return true;
if (config->allowUndefinedSymbols.count(sym->getName()) != 0)