[llvm] [RelLookupTableConverter] Enable relative lookup tables on Arm. (PR #77910)
Simon Tatham via llvm-commits
llvm-commits at lists.llvm.org
Fri Jan 12 03:57:59 PST 2024
https://github.com/statham-arm created https://github.com/llvm/llvm-project/pull/77910
This pass was only enabled for arrays of 64-bit pointers. But 64-bit architectures aren't the only place where you want to turn arrays of absolute pointers into arrays of relative offsets. It's just as useful for making lookup tables PIC-compatible on 32-bit architectures.
In this patch I've enabled it for just the 32-bit Arm architecture, because I know that that has an ELF relocation type (R_ARM_REL32) that makes it possible to express the relative offsets. Possibly it could be enabled for other 32-bit architectures too.
>From 66f42927fdc0cfd3decaf042b74015b8cfc3337f Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Thu, 11 Jan 2024 17:22:29 +0000
Subject: [PATCH] [RelLookupTableConverter] Enable relative lookup tables on
Arm.
This pass was only enabled for arrays of 64-bit pointers. But 64-bit
architectures aren't the only place where you want to turn arrays of
absolute pointers into arrays of relative offsets. It's just as useful
for making lookup tables PIC-compatible on 32-bit architectures.
In this patch I've enabled it for just the 32-bit Arm architecture,
because I know that that has an ELF relocation type (R_ARM_REL32) that
makes it possible to express the relative offsets. Possibly it could
be enabled for other 32-bit architectures too.
---
llvm/include/llvm/CodeGen/BasicTTIImpl.h | 4 +-
.../Utils/RelLookupTableConverter.cpp | 25 ++++++++----
.../ARM/rel_lookup_table.ll | 39 +++++++++++++++++++
3 files changed, 60 insertions(+), 8 deletions(-)
create mode 100644 llvm/test/Transforms/RelLookupTableConverter/ARM/rel_lookup_table.ll
diff --git a/llvm/include/llvm/CodeGen/BasicTTIImpl.h b/llvm/include/llvm/CodeGen/BasicTTIImpl.h
index 5e7bdcdf72a49f..ad043877254984 100644
--- a/llvm/include/llvm/CodeGen/BasicTTIImpl.h
+++ b/llvm/include/llvm/CodeGen/BasicTTIImpl.h
@@ -512,8 +512,10 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
TM.getCodeModel() == CodeModel::Large)
return false;
+ // Currently we permit relative lookup table entries on 64-bit targets,
+ // and on 32-bit Arm. TODO: better comment explaining why just these
Triple TargetTriple = TM.getTargetTriple();
- if (!TargetTriple.isArch64Bit())
+ if (!TargetTriple.isArch64Bit() && TargetTriple.getArch() != Triple::arm)
return false;
// TODO: Triggers issues on aarch64 on darwin, so temporarily disable it
diff --git a/llvm/lib/Transforms/Utils/RelLookupTableConverter.cpp b/llvm/lib/Transforms/Utils/RelLookupTableConverter.cpp
index ea628d7c3d7d6b..deb23e009b27f5 100644
--- a/llvm/lib/Transforms/Utils/RelLookupTableConverter.cpp
+++ b/llvm/lib/Transforms/Utils/RelLookupTableConverter.cpp
@@ -18,10 +18,12 @@
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
+#include "llvm/TargetParser/Triple.h"
using namespace llvm;
-static bool shouldConvertToRelLookupTable(Module &M, GlobalVariable &GV) {
+static bool shouldConvertToRelLookupTable(Module &M, GlobalVariable &GV,
+ unsigned PointerSize) {
// If lookup table has more than one user,
// do not generate a relative lookup table.
// This is to simplify the analysis that needs to be done for this pass.
@@ -60,10 +62,12 @@ static bool shouldConvertToRelLookupTable(Module &M, GlobalVariable &GV) {
if (!Array)
return false;
- // If values are not 64-bit pointers, do not generate a relative lookup table.
+ // If values are not pointers of the full width permitted by the
+ // architecture, do not generate a relative lookup table.
const DataLayout &DL = M.getDataLayout();
Type *ElemType = Array->getType()->getElementType();
- if (!ElemType->isPointerTy() || DL.getPointerTypeSizeInBits(ElemType) != 64)
+ if (!ElemType->isPointerTy() ||
+ DL.getPointerTypeSizeInBits(ElemType) != PointerSize)
return false;
for (const Use &Op : Array->operands()) {
@@ -96,8 +100,8 @@ static GlobalVariable *createRelLookupTable(Function &Func,
ConstantArray *LookupTableArr =
cast<ConstantArray>(LookupTable.getInitializer());
unsigned NumElts = LookupTableArr->getType()->getNumElements();
- ArrayType *IntArrayTy =
- ArrayType::get(Type::getInt32Ty(M.getContext()), NumElts);
+ Type *IntTy = Type::getInt32Ty(M.getContext());
+ ArrayType *IntArrayTy = ArrayType::get(IntTy, NumElts);
GlobalVariable *RelLookupTable = new GlobalVariable(
M, IntArrayTy, LookupTable.isConstant(), LookupTable.getLinkage(),
@@ -115,7 +119,9 @@ static GlobalVariable *createRelLookupTable(Function &Func,
Constant *Target = llvm::ConstantExpr::getPtrToInt(Element, IntPtrTy);
Constant *Sub = llvm::ConstantExpr::getSub(Target, Base);
Constant *RelOffset =
- llvm::ConstantExpr::getTrunc(Sub, Type::getInt32Ty(M.getContext()));
+ IntPtrTy->getScalarSizeInBits() > IntTy->getScalarSizeInBits()
+ ? llvm::ConstantExpr::getTrunc(Sub, IntTy)
+ : Sub;
RelLookupTableContents[Idx++] = RelOffset;
}
@@ -183,8 +189,13 @@ static bool convertToRelativeLookupTables(
bool Changed = false;
+ auto Triple = llvm::Triple(M.getTargetTriple());
+ unsigned PointerSize = Triple.isArch64Bit() ? 64
+ : Triple.isArch32Bit() ? 32
+ : 16;
+
for (GlobalVariable &GV : llvm::make_early_inc_range(M.globals())) {
- if (!shouldConvertToRelLookupTable(M, GV))
+ if (!shouldConvertToRelLookupTable(M, GV, PointerSize))
continue;
convertToRelLookupTable(GV);
diff --git a/llvm/test/Transforms/RelLookupTableConverter/ARM/rel_lookup_table.ll b/llvm/test/Transforms/RelLookupTableConverter/ARM/rel_lookup_table.ll
new file mode 100644
index 00000000000000..e7df904fdc8e45
--- /dev/null
+++ b/llvm/test/Transforms/RelLookupTableConverter/ARM/rel_lookup_table.ll
@@ -0,0 +1,39 @@
+; RUN: opt -passes=rel-lookup-table-converter -mtriple=arm-none-eabi -S < %s | FileCheck %s --check-prefix=ABS
+; RUN: opt -passes=rel-lookup-table-converter -relocation-model=pic -mtriple=arm-none-eabi -S < %s | FileCheck %s --check-prefix=REL
+
+ at .str.0 = private unnamed_addr constant [6 x i8] c"Lorem\00", align 1
+ at .str.1 = private unnamed_addr constant [6 x i8] c"ipsum\00", align 1
+ at .str.2 = private unnamed_addr constant [6 x i8] c"dolor\00", align 1
+ at .str.3 = private unnamed_addr constant [4 x i8] c"sit\00", align 1
+ at .str.4 = private unnamed_addr constant [5 x i8] c"amet\00", align 1
+ at .str.5 = private unnamed_addr constant [12 x i8] c"consectetur\00", align 1
+ at .str.6 = private unnamed_addr constant [12 x i8] c"adipisicing\00", align 1
+ at .str.default = private unnamed_addr constant [5 x i8] c"elit\00", align 1
+ at .table = private unnamed_addr constant [7 x ptr] [
+ ptr @.str.0,
+ ptr @.str.1,
+ ptr @.str.2,
+ ptr @.str.3,
+ ptr @.str.4,
+ ptr @.str.5,
+ ptr @.str.6
+], align 4
+; ABS: @.table = private unnamed_addr constant [7 x ptr] [ptr @.str.0, ptr @.str.1, ptr @.str.2, ptr @.str.3, ptr @.str.4, ptr @.str.5, ptr @.str.6], align 4
+; REL: @reltable.lookup = private unnamed_addr constant [7 x i32] [i32 sub (i32 ptrtoint (ptr @.str.0 to i32), i32 ptrtoint (ptr @reltable.lookup to i32)), i32 sub (i32 ptrtoint (ptr @.str.1 to i32), i32 ptrtoint (ptr @reltable.lookup to i32)), i32 sub (i32 ptrtoint (ptr @.str.2 to i32), i32 ptrtoint (ptr @reltable.lookup to i32)), i32 sub (i32 ptrtoint (ptr @.str.3 to i32), i32 ptrtoint (ptr @reltable.lookup to i32)), i32 sub (i32 ptrtoint (ptr @.str.4 to i32), i32 ptrtoint (ptr @reltable.lookup to i32)), i32 sub (i32 ptrtoint (ptr @.str.5 to i32), i32 ptrtoint (ptr @reltable.lookup to i32)), i32 sub (i32 ptrtoint (ptr @.str.6 to i32), i32 ptrtoint (ptr @reltable.lookup to i32))], align 4
+
+define noundef nonnull ptr @lookup(i32 noundef %s) {
+entry:
+ %0 = icmp ult i32 %s, 7
+ br i1 %0, label %table, label %return
+
+table:
+ %gep = getelementptr inbounds [7 x ptr], ptr @.table, i32 0, i32 %s
+ %element = load ptr, ptr %gep, align 4
+; ABS: %element = load ptr, ptr %gep, align 4
+; REL: {{%.*}} = call ptr @llvm.load.relative.i32(ptr @reltable.lookup, i32 {{%.*}})
+ br label %return
+
+return: ; preds = %entry, %switch.lookup
+ %ret = phi ptr [ %element, %table ], [ @.str.default, %entry ]
+ ret ptr %ret
+}
More information about the llvm-commits
mailing list