[llvm] [TTI][TLI] Expose TargetLowering::isOffsetFoldingLegal (backend) to TargetTransformInfo for middle-end cost-benefit analysis (PR #104644)

Mingming Liu via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 20 23:09:31 PDT 2024


https://github.com/minglotus-6 updated https://github.com/llvm/llvm-project/pull/104644

>From c9e880bc0f065d55e5d5f86e814fa29b252c8a2a Mon Sep 17 00:00:00 2001
From: mingmingl <mingmingl at google.com>
Date: Fri, 16 Aug 2024 15:00:11 -0700
Subject: [PATCH] resolve comments and add unit tests

---
 .../llvm/Analysis/TargetTransformInfo.h       | 10 +++
 .../llvm/Analysis/TargetTransformInfoImpl.h   |  2 +
 llvm/include/llvm/CodeGen/BasicTTIImpl.h      |  4 ++
 llvm/include/llvm/CodeGen/TargetLowering.h    |  6 +-
 llvm/lib/Analysis/TargetTransformInfo.cpp     |  4 ++
 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp |  5 +-
 .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp |  4 +-
 .../CodeGen/SelectionDAG/TargetLowering.cpp   |  4 +-
 .../Target/AArch64/AArch64ISelLowering.cpp    |  3 +-
 llvm/lib/Target/AArch64/AArch64ISelLowering.h |  2 +-
 llvm/lib/Target/AMDGPU/SIISelLowering.cpp     | 11 ++--
 llvm/lib/Target/AMDGPU/SIISelLowering.h       |  2 +-
 llvm/lib/Target/ARM/ARMISelLowering.cpp       |  3 +-
 llvm/lib/Target/ARM/ARMISelLowering.h         |  2 +-
 llvm/unittests/Target/AArch64/CMakeLists.txt  |  1 +
 .../Target/AArch64/TargetTransformInfo.cpp    | 60 +++++++++++++++++
 llvm/unittests/Target/X86/CMakeLists.txt      |  1 +
 .../Target/X86/TargetTransformInfo.cpp        | 64 +++++++++++++++++++
 18 files changed, 167 insertions(+), 21 deletions(-)
 create mode 100644 llvm/unittests/Target/AArch64/TargetTransformInfo.cpp
 create mode 100644 llvm/unittests/Target/X86/TargetTransformInfo.cpp

diff --git a/llvm/include/llvm/Analysis/TargetTransformInfo.h b/llvm/include/llvm/Analysis/TargetTransformInfo.h
index 38e8b9da213974..4956fc2c4303b0 100644
--- a/llvm/include/llvm/Analysis/TargetTransformInfo.h
+++ b/llvm/include/llvm/Analysis/TargetTransformInfo.h
@@ -665,6 +665,12 @@ class TargetTransformInfo {
   void getPeelingPreferences(Loop *L, ScalarEvolution &SE,
                              PeelingPreferences &PP) const;
 
+  /// Return true if folding a constant offset with the given GlobalValue
+  /// (representing a GlobalAddress) is legal.  It is frequently not legal
+  /// in PIC relocation models.
+  /// Caller must guarantee that GlobalValue represents a global address.
+  bool isOffsetFoldingLegal(const GlobalValue *GV) const;
+
   /// Targets can implement their own combinations for target-specific
   /// intrinsics. This function will be called from the InstCombine pass every
   /// time a target-specific intrinsic is encountered.
@@ -1880,6 +1886,7 @@ class TargetTransformInfo::Concept {
       APInt &UndefElts, APInt &UndefElts2, APInt &UndefElts3,
       std::function<void(Instruction *, unsigned, APInt, APInt &)>
           SimplifyAndSetOp) = 0;
+  virtual bool isOffsetFoldingLegal(const GlobalValue *GV) const = 0;
   virtual bool isLegalAddImmediate(int64_t Imm) = 0;
   virtual bool isLegalAddScalableImmediate(int64_t Imm) = 0;
   virtual bool isLegalICmpImmediate(int64_t Imm) = 0;
@@ -2348,6 +2355,9 @@ class TargetTransformInfo::Model final : public TargetTransformInfo::Concept {
         IC, II, DemandedElts, UndefElts, UndefElts2, UndefElts3,
         SimplifyAndSetOp);
   }
+  bool isOffsetFoldingLegal(const GlobalValue *GV) const override {
+    return Impl.isOffsetFoldingLegal(GV);
+  }
   bool isLegalAddImmediate(int64_t Imm) override {
     return Impl.isLegalAddImmediate(Imm);
   }
diff --git a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h b/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
index d208a710bb27fd..bb81f4defcd633 100644
--- a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
+++ b/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
@@ -220,6 +220,8 @@ class TargetTransformInfoImplBase {
   void getPeelingPreferences(Loop *, ScalarEvolution &,
                              TTI::PeelingPreferences &) const {}
 
+  bool isOffsetFoldingLegal(const GlobalValue *GV) const { return false; }
+
   bool isLegalAddImmediate(int64_t Imm) const { return false; }
 
   bool isLegalAddScalableImmediate(int64_t Imm) const { return false; }
diff --git a/llvm/include/llvm/CodeGen/BasicTTIImpl.h b/llvm/include/llvm/CodeGen/BasicTTIImpl.h
index 890c2b8ca36e11..8059191c6dd471 100644
--- a/llvm/include/llvm/CodeGen/BasicTTIImpl.h
+++ b/llvm/include/llvm/CodeGen/BasicTTIImpl.h
@@ -354,6 +354,10 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
     return getTLI()->getPreferredLargeGEPBaseOffset(MinOffset, MaxOffset);
   }
 
+  bool isOffsetFoldingLegal(const GlobalValue *GV) const {
+    return getTLI()->isOffsetFoldingLegal(GV);
+  }
+
   unsigned getStoreMinimumVF(unsigned VF, Type *ScalarMemTy,
                              Type *ScalarValTy) const {
     auto &&IsSupportedByTarget = [this, ScalarMemTy, ScalarValTy](unsigned VF) {
diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h
index 9ccdbab008aec8..72fd58c0f87536 100644
--- a/llvm/include/llvm/CodeGen/TargetLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetLowering.h
@@ -2811,6 +2811,10 @@ class TargetLoweringBase {
                                      Type *Ty, unsigned AddrSpace,
                                      Instruction *I = nullptr) const;
 
+  virtual bool isOffsetFoldingLegal(const GlobalValue *GV) const {
+    return false;
+  }
+
   /// Returns true if the targets addressing mode can target thread local
   /// storage (TLS).
   virtual bool addressingModeSupportsTLS(const GlobalValue &) const {
@@ -3862,7 +3866,7 @@ class TargetLowering : public TargetLoweringBase {
 
   /// Return true if folding a constant offset with the given GlobalAddress is
   /// legal.  It is frequently not legal in PIC relocation models.
-  virtual bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const;
+  bool isOffsetFoldingLegal(const GlobalValue *GV) const override;
 
   /// On x86, return true if the operand with index OpNo is a CALL or JUMP
   /// instruction, which can use either a memory constraint or an address
diff --git a/llvm/lib/Analysis/TargetTransformInfo.cpp b/llvm/lib/Analysis/TargetTransformInfo.cpp
index dcde78925bfa98..5e80c40c41a286 100644
--- a/llvm/lib/Analysis/TargetTransformInfo.cpp
+++ b/llvm/lib/Analysis/TargetTransformInfo.cpp
@@ -396,6 +396,10 @@ void TargetTransformInfo::getPeelingPreferences(Loop *L, ScalarEvolution &SE,
   return TTIImpl->getPeelingPreferences(L, SE, PP);
 }
 
+bool TargetTransformInfo::isOffsetFoldingLegal(const GlobalValue *GV) const {
+  return TTIImpl->isOffsetFoldingLegal(GV);
+}
+
 bool TargetTransformInfo::isLegalAddImmediate(int64_t Imm) const {
   return TTIImpl->isLegalAddImmediate(Imm);
 }
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index f827eb559a01cf..9ad75fd328ceea 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -1161,7 +1161,8 @@ bool DAGCombiner::reassociationCanBreakAddressingModePattern(unsigned Opc,
     }
   } else {
     if (auto *GA = dyn_cast<GlobalAddressSDNode>(N0.getOperand(1)))
-      if (GA->getOpcode() == ISD::GlobalAddress && TLI.isOffsetFoldingLegal(GA))
+      if (GA->getOpcode() == ISD::GlobalAddress &&
+          TLI.isOffsetFoldingLegal(GA->getGlobal()))
         return false;
 
     for (SDNode *Node : N->uses()) {
@@ -4006,7 +4007,7 @@ SDValue DAGCombiner::visitSUB(SDNode *N) {
 
   // If the relocation model supports it, consider symbol offsets.
   if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(N0))
-    if (!LegalOperations && TLI.isOffsetFoldingLegal(GA)) {
+    if (!LegalOperations && TLI.isOffsetFoldingLegal(GA->getGlobal())) {
       // fold (sub Sym+c1, Sym+c2) -> c1-c2
       if (GlobalAddressSDNode *GB = dyn_cast<GlobalAddressSDNode>(N1))
         if (GA->getGlobal() == GB->getGlobal())
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index c3a7df5361cd45..9a8b6ae7da4053 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -6339,7 +6339,7 @@ SDValue SelectionDAG::FoldSymbolOffset(unsigned Opcode, EVT VT,
                                        const SDNode *N2) {
   if (GA->getOpcode() != ISD::GlobalAddress)
     return SDValue();
-  if (!TLI->isOffsetFoldingLegal(GA))
+  if (!TLI->isOffsetFoldingLegal(GA->getGlobal()))
     return SDValue();
   auto *C2 = dyn_cast<ConstantSDNode>(N2);
   if (!C2)
@@ -13112,7 +13112,7 @@ SDNode *SelectionDAG::isConstantIntBuildVectorOrConstantInt(SDValue N) const {
   // constant integer.
   if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(N))
     if (GA->getOpcode() == ISD::GlobalAddress &&
-        TLI->isOffsetFoldingLegal(GA))
+        TLI->isOffsetFoldingLegal(GA->getGlobal()))
       return GA;
   if ((N.getOpcode() == ISD::SPLAT_VECTOR) &&
       isa<ConstantSDNode>(N.getOperand(0)))
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index bef70dcb71f567..df63617c2d6883 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -485,10 +485,8 @@ SDValue TargetLowering::expandIndirectJTBranch(const SDLoc &dl, SDValue Value,
   return DAG.getNode(ISD::BRIND, dl, MVT::Other, Chain, Addr);
 }
 
-bool
-TargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
+bool TargetLowering::isOffsetFoldingLegal(const GlobalValue *GV) const {
   const TargetMachine &TM = getTargetMachine();
-  const GlobalValue *GV = GA->getGlobal();
 
   // If the address is not even local to this DSO we will have to load it from
   // a got and then add the offset.
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index f0c3afc4f9b5d5..7e7bd9a924d9b6 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -11282,8 +11282,7 @@ SDValue AArch64TargetLowering::LowerShiftParts(SDValue Op,
   return DAG.getMergeValues({Lo, Hi}, SDLoc(Op));
 }
 
-bool AArch64TargetLowering::isOffsetFoldingLegal(
-    const GlobalAddressSDNode *GA) const {
+bool AArch64TargetLowering::isOffsetFoldingLegal(const GlobalValue *GV) const {
   // Offsets are folded in the DAG combine rather than here so that we can
   // intelligently choose an offset based on the uses.
   return false;
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.h b/llvm/lib/Target/AArch64/AArch64ISelLowering.h
index 81e15185f985d5..eb02484bcbe95b 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.h
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.h
@@ -622,7 +622,7 @@ class AArch64TargetLowering : public TargetLowering {
   FastISel *createFastISel(FunctionLoweringInfo &funcInfo,
                            const TargetLibraryInfo *libInfo) const override;
 
-  bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override;
+  bool isOffsetFoldingLegal(const GlobalValue *GV) const override;
 
   bool isFPImmLegal(const APFloat &Imm, EVT VT,
                     bool ForCodeSize) const override;
diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
index f8767e00949bf0..da4c5c998b5dbd 100644
--- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
@@ -7551,8 +7551,7 @@ SDValue SITargetLowering::lowerBUILD_VECTOR(SDValue Op,
   return DAG.getNode(ISD::BITCAST, SL, VT, Or);
 }
 
-bool
-SITargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
+bool SITargetLowering::isOffsetFoldingLegal(const GlobalValue *GV) const {
   // OSes that use ELF REL relocations (instead of RELA) can only store a
   // 32-bit addend in the instruction, so it is not safe to allow offset folding
   // which can create arbitrary 64-bit addends. (This is only a problem for
@@ -7565,10 +7564,10 @@ SITargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
     return false;
 
   // We can fold offsets for anything that doesn't require a GOT relocation.
-  return (GA->getAddressSpace() == AMDGPUAS::GLOBAL_ADDRESS ||
-          GA->getAddressSpace() == AMDGPUAS::CONSTANT_ADDRESS ||
-          GA->getAddressSpace() == AMDGPUAS::CONSTANT_ADDRESS_32BIT) &&
-         !shouldEmitGOTReloc(GA->getGlobal());
+  return (GV->getAddressSpace() == AMDGPUAS::GLOBAL_ADDRESS ||
+          GV->getAddressSpace() == AMDGPUAS::CONSTANT_ADDRESS ||
+          GV->getAddressSpace() == AMDGPUAS::CONSTANT_ADDRESS_32BIT) &&
+         !shouldEmitGOTReloc(GV);
 }
 
 static SDValue
diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.h b/llvm/lib/Target/AMDGPU/SIISelLowering.h
index 1f198a92c0fa6a..e9137614ecdf20 100644
--- a/llvm/lib/Target/AMDGPU/SIISelLowering.h
+++ b/llvm/lib/Target/AMDGPU/SIISelLowering.h
@@ -364,7 +364,7 @@ class SITargetLowering final : public AMDGPUTargetLowering {
 
   bool isTypeDesirableForOp(unsigned Op, EVT VT) const override;
 
-  bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override;
+  bool isOffsetFoldingLegal(const GlobalValue *GV) const override;
 
   unsigned combineRepeatedFPDivisors() const override {
     // Combine multiple FDIVs with the same divisor into multiple FMULs by the
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index 75d16a42d0205a..ed8a9ffd65dc84 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -20974,8 +20974,7 @@ SDValue ARMTargetLowering::LowerFP_ROUND(SDValue Op, SelectionDAG &DAG) const {
   return IsStrict ? DAG.getMergeValues({Result, Chain}, Loc) : Result;
 }
 
-bool
-ARMTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
+bool ARMTargetLowering::isOffsetFoldingLegal(const GlobalValue *GV) const {
   // The ARM target isn't yet aware of offsets.
   return false;
 }
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.h b/llvm/lib/Target/ARM/ARMISelLowering.h
index a255e9b6fc365f..758b09786f05d2 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.h
+++ b/llvm/lib/Target/ARM/ARMISelLowering.h
@@ -595,7 +595,7 @@ class VectorType;
 
     bool
     isShuffleMaskLegal(ArrayRef<int> M, EVT VT) const override;
-    bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override;
+    bool isOffsetFoldingLegal(const GlobalValue *GV) const override;
 
     /// isFPImmLegal - Returns true if the target can instruction select the
     /// specified FP immediate natively. If false, the legalizer will
diff --git a/llvm/unittests/Target/AArch64/CMakeLists.txt b/llvm/unittests/Target/AArch64/CMakeLists.txt
index f53668373efee9..726fa46ba97eb0 100644
--- a/llvm/unittests/Target/AArch64/CMakeLists.txt
+++ b/llvm/unittests/Target/AArch64/CMakeLists.txt
@@ -30,4 +30,5 @@ add_llvm_target_unittest(AArch64Tests
   SMEAttributesTest.cpp
   AArch64SVESchedPseudoTest.cpp
   Immediates.cpp
+  TargetTransformInfo.cpp
   )
diff --git a/llvm/unittests/Target/AArch64/TargetTransformInfo.cpp b/llvm/unittests/Target/AArch64/TargetTransformInfo.cpp
new file mode 100644
index 00000000000000..b87675b9230650
--- /dev/null
+++ b/llvm/unittests/Target/AArch64/TargetTransformInfo.cpp
@@ -0,0 +1,60 @@
+#include "llvm/Analysis/TargetTransformInfo.h"
+#include "AArch64Subtarget.h"
+#include "AArch64TargetMachine.h"
+#include "llvm/AsmParser/Parser.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Module.h"
+#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/TargetSelect.h"
+
+#include "gtest/gtest.h"
+#include <initializer_list>
+#include <memory>
+
+using namespace llvm;
+
+namespace {
+
+static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {
+  SMDiagnostic Err;
+  std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C);
+  if (!Mod)
+    Err.print(__FILE__, errs());
+  return Mod;
+}
+
+TEST(TargetTransformInfo, isOffsetFoldingLegal) {
+  LLVMInitializeAArch64TargetInfo();
+  LLVMInitializeAArch64Target();
+  LLVMInitializeAArch64TargetMC();
+
+  LLVMContext Ctx;
+  std::unique_ptr<Module> M = parseIR(Ctx, R"(
+    target triple = "aarch64-unknown-linux-gnu"
+
+    @Base1 = dso_local constant { [4 x ptr] } { [4 x ptr] [ptr null, ptr null, ptr @Base1_foo, ptr @Base1_bar] }
+    @Base2 = constant { [4 x ptr] } { [4 x ptr] [ptr null, ptr null, ptr @Base1_foo, ptr @Base1_bar] }
+    
+    define void @Base1_bar(ptr %this) {
+      ret void
+    }
+
+    declare i32 @Base1_foo(ptr)
+  )");
+
+  std::string Error;
+  const Target *T = TargetRegistry::lookupTarget(M->getTargetTriple(), Error);
+  std::unique_ptr<TargetMachine> TM(T->createTargetMachine(
+      M->getTargetTriple(), "generic", "", TargetOptions(), std::nullopt,
+      std::nullopt, CodeGenOptLevel::Default));
+
+  ASSERT_FALSE(TM->isPositionIndependent());
+
+  TargetTransformInfo TTI =
+      TM->getTargetTransformInfo(*M->getFunction("Base1_bar"));
+
+  EXPECT_FALSE(TTI.isOffsetFoldingLegal(M->getNamedValue("Base1")));
+  EXPECT_FALSE(TTI.isOffsetFoldingLegal(M->getNamedValue("Base2")));
+}
+} // namespace
diff --git a/llvm/unittests/Target/X86/CMakeLists.txt b/llvm/unittests/Target/X86/CMakeLists.txt
index b011681aa3b95a..236ab8aebf4f6a 100644
--- a/llvm/unittests/Target/X86/CMakeLists.txt
+++ b/llvm/unittests/Target/X86/CMakeLists.txt
@@ -23,5 +23,6 @@ set(LLVM_LINK_COMPONENTS
 
 add_llvm_unittest(X86Tests
   MachineSizeOptsTest.cpp
+  TargetTransformInfo.cpp
   TernlogTest.cpp
   )
diff --git a/llvm/unittests/Target/X86/TargetTransformInfo.cpp b/llvm/unittests/Target/X86/TargetTransformInfo.cpp
new file mode 100644
index 00000000000000..f38062c8691277
--- /dev/null
+++ b/llvm/unittests/Target/X86/TargetTransformInfo.cpp
@@ -0,0 +1,64 @@
+#include "llvm/Analysis/TargetTransformInfo.h"
+#include "X86Subtarget.h"
+#include "X86TargetMachine.h"
+#include "llvm/AsmParser/Parser.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Module.h"
+#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Target/TargetMachine.h"
+
+#include "gtest/gtest.h"
+#include <initializer_list>
+#include <memory>
+
+using namespace llvm;
+
+namespace {
+
+static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {
+  SMDiagnostic Err;
+  std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C);
+  if (!Mod)
+    Err.print(__FILE__, errs());
+  return Mod;
+}
+
+TEST(TargetTransformInfo, isOffsetFoldingLegal) {
+  LLVMInitializeX86TargetInfo();
+  LLVMInitializeX86Target();
+  LLVMInitializeX86TargetMC();
+
+  LLVMContext Ctx;
+  std::unique_ptr<Module> M = parseIR(Ctx, R"(
+    
+    target triple = "x86_64-unknown-linux-gnu"
+    @Base1 = dso_local constant { [4 x ptr] } { [4 x ptr] [ptr null, ptr null, ptr @Base1_foo, ptr @Base1_bar] }
+    @Base2 = constant { [4 x ptr] } { [4 x ptr] [ptr null, ptr null, ptr @Base1_foo, ptr @Base1_bar] }
+    
+    define void @Base1_bar(ptr %this) {
+      ret void
+    }
+
+    declare i32 @Base1_foo(ptr)
+  )");
+
+  std::string Error;
+  const Target *T = TargetRegistry::lookupTarget(M->getTargetTriple(), Error);
+  std::unique_ptr<TargetMachine> TM(T->createTargetMachine(
+      M->getTargetTriple(), "generic", "", TargetOptions(), std::nullopt,
+      std::nullopt, CodeGenOptLevel::Default));
+  ASSERT_FALSE(TM->isPositionIndependent());
+
+  Function *Func = M->getFunction("Base1_bar");
+
+  TargetTransformInfo TTI = TM->getTargetTransformInfo(*Func);
+
+  // Base1 is dso_local.
+  EXPECT_TRUE(TTI.isOffsetFoldingLegal(M->getNamedValue("Base1")));
+
+  // Base2 is not dso_local.
+  EXPECT_FALSE(TTI.isOffsetFoldingLegal(M->getNamedValue("Base2")));
+}
+} // namespace



More information about the llvm-commits mailing list