Skip to content

Commit 5178ffc

Browse files
committed
[Passes] Add relative lookup table converter pass
Lookup tables generate non PIC-friendly code, which requires dynamic relocation as described in: https://bugs.llvm.org/show_bug.cgi?id=45244 This patch adds a new pass that converts lookup tables to relative lookup tables to make them PIC-friendly. Differential Revision: https://reviews.llvm.org/D94355
1 parent 4822830 commit 5178ffc

26 files changed

+743
-16
lines changed

llvm/docs/Passes.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -973,6 +973,11 @@ corresponding to the reverse post order traversal of current function (starting
973973
at 2), which effectively gives values in deep loops higher rank than values not
974974
in loops.
975975

976+
``-rel-lookup-table-converter``: Relative lookup table converter
977+
----------------------------------------------------------------
978+
979+
This pass converts lookup tables to PIC-friendly relative lookup tables.
980+
976981
``-reg2mem``: Demote all values to stack slots
977982
----------------------------------------------
978983

llvm/include/llvm/Analysis/TargetTransformInfo.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,9 @@ class TargetTransformInfo {
720720
/// containing this constant value for the target.
721721
bool shouldBuildLookupTablesForConstant(Constant *C) const;
722722

723+
/// Return true if lookup tables should be turned into relative lookup tables.
724+
bool shouldBuildRelLookupTables() const;
725+
723726
/// Return true if the input function which is cold at all call sites,
724727
/// should use coldcc calling convention.
725728
bool useColdCCForColdCall(Function &F) const;
@@ -1483,6 +1486,7 @@ class TargetTransformInfo::Concept {
14831486
virtual unsigned getRegUsageForType(Type *Ty) = 0;
14841487
virtual bool shouldBuildLookupTables() = 0;
14851488
virtual bool shouldBuildLookupTablesForConstant(Constant *C) = 0;
1489+
virtual bool shouldBuildRelLookupTables() = 0;
14861490
virtual bool useColdCCForColdCall(Function &F) = 0;
14871491
virtual unsigned getScalarizationOverhead(VectorType *Ty,
14881492
const APInt &DemandedElts,
@@ -1869,6 +1873,9 @@ class TargetTransformInfo::Model final : public TargetTransformInfo::Concept {
18691873
bool shouldBuildLookupTablesForConstant(Constant *C) override {
18701874
return Impl.shouldBuildLookupTablesForConstant(C);
18711875
}
1876+
bool shouldBuildRelLookupTables() override {
1877+
return Impl.shouldBuildRelLookupTables();
1878+
}
18721879
bool useColdCCForColdCall(Function &F) override {
18731880
return Impl.useColdCCForColdCall(F);
18741881
}

llvm/include/llvm/Analysis/TargetTransformInfoImpl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,8 +292,11 @@ class TargetTransformInfoImplBase {
292292
unsigned getRegUsageForType(Type *Ty) const { return 1; }
293293

294294
bool shouldBuildLookupTables() const { return true; }
295+
295296
bool shouldBuildLookupTablesForConstant(Constant *C) const { return true; }
296297

298+
bool shouldBuildRelLookupTables() const { return false; }
299+
297300
bool useColdCCForColdCall(Function &F) const { return false; }
298301

299302
unsigned getScalarizationOverhead(VectorType *Ty, const APInt &DemandedElts,

llvm/include/llvm/CodeGen/BasicTTIImpl.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#include "llvm/Support/ErrorHandling.h"
4646
#include "llvm/Support/MachineValueType.h"
4747
#include "llvm/Support/MathExtras.h"
48+
#include "llvm/Target/TargetMachine.h"
4849
#include <algorithm>
4950
#include <cassert>
5051
#include <cstdint>
@@ -379,6 +380,25 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
379380
TLI->isOperationLegalOrCustom(ISD::BRIND, MVT::Other);
380381
}
381382

383+
bool shouldBuildRelLookupTables() {
384+
const TargetMachine &TM = getTLI()->getTargetMachine();
385+
// If non-PIC mode, do not generate a relative lookup table.
386+
if (!TM.isPositionIndependent())
387+
return false;
388+
389+
if (!TM.getTargetTriple().isArch64Bit())
390+
return false;
391+
392+
/// Relative lookup table entries consist of 32-bit offsets.
393+
/// Do not generate relative lookup tables for large code models
394+
/// in 64-bit achitectures where 32-bit offsets might not be enough.
395+
if (TM.getCodeModel() == CodeModel::Medium ||
396+
TM.getCodeModel() == CodeModel::Large)
397+
return false;
398+
399+
return true;
400+
}
401+
382402
bool haveFastSqrt(Type *Ty) {
383403
const TargetLoweringBase *TLI = getTLI();
384404
EVT VT = TLI->getValueType(DL, Ty);

llvm/include/llvm/InitializePasses.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,7 @@ void initializeModuloScheduleTestPass(PassRegistry&);
318318
void initializeMustExecutePrinterPass(PassRegistry&);
319319
void initializeMustBeExecutedContextPrinterPass(PassRegistry&);
320320
void initializeNameAnonGlobalLegacyPassPass(PassRegistry&);
321+
void initializeRelLookupTableConverterLegacyPassPass(PassRegistry &);
321322
void initializeNaryReassociateLegacyPassPass(PassRegistry&);
322323
void initializeNewGVNLegacyPassPass(PassRegistry&);
323324
void initializeObjCARCAAWrapperPassPass(PassRegistry&);

llvm/include/llvm/Transforms/Scalar.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,7 @@ FunctionPass *createLoopDataPrefetchPass();
517517

518518
///===---------------------------------------------------------------------===//
519519
ModulePass *createNameAnonGlobalPass();
520+
ModulePass *createRelLookupTableConverterPass();
520521
ModulePass *createCanonicalizeAliasesPass();
521522

522523
//===----------------------------------------------------------------------===//
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
//===-- RelLookupTableConverterPass.h - Rel Table Conv ----------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
/// \file
10+
/// This file implements relative lookup table converter that converts
11+
/// lookup tables to relative lookup tables to make them PIC-friendly.
12+
///
13+
/// Switch lookup table example:
14+
/// @switch.table.foo = private unnamed_addr constant [3 x i8*]
15+
/// [
16+
/// i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0),
17+
/// i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.1, i64 0, i64 0),
18+
/// i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.2, i64 0, i64 0)
19+
/// ], align 8
20+
///
21+
/// switch.lookup:
22+
/// %1 = sext i32 %cond to i64
23+
/// %switch.gep = getelementptr inbounds [3 x i8*],
24+
/// [3 x i8*]* @switch.table.foo, i64 0, i64 %1
25+
/// %switch.load = load i8*, i8** %switch.gep, align 8
26+
/// ret i8* %switch.load
27+
///
28+
/// Switch lookup table will become a relative lookup table that
29+
/// consists of relative offsets.
30+
///
31+
/// @reltable.foo = private unnamed_addr constant [3 x i32]
32+
/// [
33+
/// i32 trunc (i64 sub (i64 ptrtoint ([5 x i8]* @.str to i64),
34+
/// i64 ptrtoint ([3 x i32]* @reltable.foo to i64)) to i32),
35+
/// i32 trunc (i64 sub (i64 ptrtoint ([4 x i8]* @.str.1 to i64),
36+
/// i64 ptrtoint ([3 x i32]* @reltable.foo to i64)) to i32),
37+
/// i32 trunc (i64 sub (i64 ptrtoint ([4 x i8]* @.str.2 to i64),
38+
/// i64 ptrtoint ([3 x i32]* @reltable.foo to i64)) to i32)
39+
/// ], align 4
40+
///
41+
/// IR after converting to a relative lookup table:
42+
/// switch.lookup:
43+
/// %1 = sext i32 %cond to i64
44+
/// %reltable.shift = shl i64 %1, 2
45+
/// %reltable.intrinsic = call i8* @llvm.load.relative.i64(
46+
/// i8* bitcast ([3 x i32]* @reltable.foo to i8*),
47+
/// i64 %reltable.shift)
48+
/// ret i8* %reltable.intrinsic
49+
//===----------------------------------------------------------------------===//
50+
51+
#ifndef LLVM_TRANSFORMS_UTILS_RELLOOKUPTABLECONVERTER_H
52+
#define LLVM_TRANSFORMS_UTILS_RELLOOKUPTABLECONVERTER_H
53+
54+
#include "llvm/IR/Module.h"
55+
#include "llvm/IR/PassManager.h"
56+
57+
namespace llvm {
58+
59+
// Pass that converts lookup tables to relative lookup tables.
60+
class RelLookupTableConverterPass
61+
: public PassInfoMixin<RelLookupTableConverterPass> {
62+
public:
63+
RelLookupTableConverterPass() = default;
64+
65+
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
66+
};
67+
68+
} // end namespace llvm
69+
70+
#endif // LLVM_TRANSFORMS_UTILS_RELLOOKUPTABLECONVERTER_H

llvm/lib/Analysis/TargetTransformInfo.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,11 +456,16 @@ unsigned TargetTransformInfo::getRegUsageForType(Type *Ty) const {
456456
bool TargetTransformInfo::shouldBuildLookupTables() const {
457457
return TTIImpl->shouldBuildLookupTables();
458458
}
459+
459460
bool TargetTransformInfo::shouldBuildLookupTablesForConstant(
460461
Constant *C) const {
461462
return TTIImpl->shouldBuildLookupTablesForConstant(C);
462463
}
463464

465+
bool TargetTransformInfo::shouldBuildRelLookupTables() const {
466+
return TTIImpl->shouldBuildRelLookupTables();
467+
}
468+
464469
bool TargetTransformInfo::useColdCCForColdCall(Function &F) const {
465470
return TTIImpl->useColdCCForColdCall(F);
466471
}

llvm/lib/Passes/PassBuilder.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,7 @@
227227
#include "llvm/Transforms/Utils/Mem2Reg.h"
228228
#include "llvm/Transforms/Utils/MetaRenamer.h"
229229
#include "llvm/Transforms/Utils/NameAnonGlobals.h"
230+
#include "llvm/Transforms/Utils/RelLookupTableConverter.h"
230231
#include "llvm/Transforms/Utils/StripGCRelocates.h"
231232
#include "llvm/Transforms/Utils/StripNonLineTableDebugInfo.h"
232233
#include "llvm/Transforms/Utils/SymbolRewriter.h"
@@ -1408,6 +1409,8 @@ PassBuilder::buildModuleOptimizationPipeline(OptimizationLevel Level,
14081409
MPM.addPass(GlobalDCEPass());
14091410
MPM.addPass(ConstantMergePass());
14101411

1412+
MPM.addPass(RelLookupTableConverterPass());
1413+
14111414
return MPM;
14121415
}
14131416

llvm/lib/Passes/PassRegistry.def

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ MODULE_PASS("khwasan", HWAddressSanitizerPass(true, true))
6363
MODULE_PASS("inferattrs", InferFunctionAttrsPass())
6464
MODULE_PASS("inliner-wrapper", ModuleInlinerWrapperPass())
6565
MODULE_PASS("inliner-wrapper-no-mandatory-first", ModuleInlinerWrapperPass(
66-
getInlineParams(),
67-
DebugLogging,
66+
getInlineParams(),
67+
DebugLogging,
6868
false))
6969
MODULE_PASS("insert-gcov-profiling", GCOVProfilerPass())
7070
MODULE_PASS("instrorderfile", InstrOrderFilePass())
@@ -93,6 +93,7 @@ MODULE_PASS("print-lcg-dot", LazyCallGraphDOTPrinterPass(dbgs()))
9393
MODULE_PASS("print-must-be-executed-contexts", MustBeExecutedContextPrinterPass(dbgs()))
9494
MODULE_PASS("print-stack-safety", StackSafetyGlobalPrinterPass(dbgs()))
9595
MODULE_PASS("print<module-debuginfo>", ModuleDebugInfoPrinterPass(dbgs()))
96+
MODULE_PASS("rel-lookup-table-converter", RelLookupTableConverterPass())
9697
MODULE_PASS("rewrite-statepoints-for-gc", RewriteStatepointsForGC())
9798
MODULE_PASS("rewrite-symbols", RewriteSymbolPass())
9899
MODULE_PASS("rpo-function-attrs", ReversePostOrderFunctionAttrsPass())
@@ -281,7 +282,7 @@ FUNCTION_PASS("print<demanded-bits>", DemandedBitsPrinterPass(dbgs()))
281282
FUNCTION_PASS("print<domfrontier>", DominanceFrontierPrinterPass(dbgs()))
282283
FUNCTION_PASS("print<func-properties>", FunctionPropertiesPrinterPass(dbgs()))
283284
FUNCTION_PASS("print<inline-cost>", InlineCostAnnotationPrinterPass(dbgs()))
284-
FUNCTION_PASS("print<inliner-size-estimator>",
285+
FUNCTION_PASS("print<inliner-size-estimator>",
285286
InlineSizeEstimatorAnalysisPrinterPass(dbgs()))
286287
FUNCTION_PASS("print<loops>", LoopPrinterPass(dbgs()))
287288
FUNCTION_PASS("print<memoryssa>", MemorySSAPrinterPass(dbgs()))

llvm/lib/Transforms/IPO/PassManagerBuilder.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -909,6 +909,8 @@ void PassManagerBuilder::populateModulePassManager(
909909
// resulted in single-entry-single-exit or empty blocks. Clean up the CFG.
910910
MPM.add(createCFGSimplificationPass());
911911

912+
MPM.add(createRelLookupTableConverterPass());
913+
912914
addExtensionsToPM(EP_OptimizerLast, MPM);
913915

914916
if (PrepareForLTO) {

llvm/lib/Transforms/Utils/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ add_llvm_component_library(LLVMTransformUtils
5454
NameAnonGlobals.cpp
5555
PredicateInfo.cpp
5656
PromoteMemoryToRegister.cpp
57+
RelLookupTableConverter.cpp
5758
ScalarEvolutionExpander.cpp
5859
StripGCRelocates.cpp
5960
SSAUpdater.cpp

0 commit comments

Comments
 (0)