Skip to content

Commit a3d58bb

Browse files
committed
Detemplate llvm::EmitGEPOffset and move it into a cpp file. NFC.
1 parent a0b7bd4 commit a3d58bb

File tree

6 files changed

+104
-79
lines changed

6 files changed

+104
-79
lines changed

llvm/include/llvm/Analysis/Utils/Local.h

+8-77
Original file line numberDiff line numberDiff line change
@@ -14,90 +14,21 @@
1414
#ifndef LLVM_ANALYSIS_UTILS_LOCAL_H
1515
#define LLVM_ANALYSIS_UTILS_LOCAL_H
1616

17-
#include "llvm/ADT/StringRef.h"
18-
#include "llvm/IR/DataLayout.h"
19-
#include "llvm/IR/GetElementPtrTypeIterator.h"
20-
2117
namespace llvm {
2218

19+
class DataLayout;
20+
class IRBuilderBase;
21+
class User;
22+
class Value;
23+
2324
/// Given a getelementptr instruction/constantexpr, emit the code necessary to
2425
/// compute the offset from the base pointer (without adding in the base
2526
/// pointer). Return the result as a signed integer of intptr size.
2627
/// When NoAssumptions is true, no assumptions about index computation not
2728
/// overflowing is made.
28-
template <typename IRBuilderTy>
29-
Value *EmitGEPOffset(IRBuilderTy *Builder, const DataLayout &DL, User *GEP,
30-
bool NoAssumptions = false) {
31-
GEPOperator *GEPOp = cast<GEPOperator>(GEP);
32-
Type *IntIdxTy = DL.getIndexType(GEP->getType());
33-
Value *Result = nullptr;
34-
35-
// If the GEP is inbounds, we know that none of the addressing operations will
36-
// overflow in a signed sense.
37-
bool isInBounds = GEPOp->isInBounds() && !NoAssumptions;
38-
39-
// Build a mask for high order bits.
40-
unsigned IntPtrWidth = IntIdxTy->getScalarType()->getIntegerBitWidth();
41-
uint64_t PtrSizeMask =
42-
std::numeric_limits<uint64_t>::max() >> (64 - IntPtrWidth);
43-
44-
gep_type_iterator GTI = gep_type_begin(GEP);
45-
for (User::op_iterator i = GEP->op_begin() + 1, e = GEP->op_end(); i != e;
46-
++i, ++GTI) {
47-
Value *Op = *i;
48-
uint64_t Size = DL.getTypeAllocSize(GTI.getIndexedType()) & PtrSizeMask;
49-
Value *Offset;
50-
if (Constant *OpC = dyn_cast<Constant>(Op)) {
51-
if (OpC->isZeroValue())
52-
continue;
53-
54-
// Handle a struct index, which adds its field offset to the pointer.
55-
if (StructType *STy = GTI.getStructTypeOrNull()) {
56-
uint64_t OpValue = OpC->getUniqueInteger().getZExtValue();
57-
Size = DL.getStructLayout(STy)->getElementOffset(OpValue);
58-
if (!Size)
59-
continue;
60-
61-
Offset = ConstantInt::get(IntIdxTy, Size);
62-
} else {
63-
// Splat the constant if needed.
64-
if (IntIdxTy->isVectorTy() && !OpC->getType()->isVectorTy())
65-
OpC = ConstantVector::getSplat(
66-
cast<VectorType>(IntIdxTy)->getElementCount(), OpC);
67-
68-
Constant *Scale = ConstantInt::get(IntIdxTy, Size);
69-
Constant *OC =
70-
ConstantExpr::getIntegerCast(OpC, IntIdxTy, true /*SExt*/);
71-
Offset =
72-
ConstantExpr::getMul(OC, Scale, false /*NUW*/, isInBounds /*NSW*/);
73-
}
74-
} else {
75-
// Splat the index if needed.
76-
if (IntIdxTy->isVectorTy() && !Op->getType()->isVectorTy())
77-
Op = Builder->CreateVectorSplat(
78-
cast<FixedVectorType>(IntIdxTy)->getNumElements(), Op);
79-
80-
// Convert to correct type.
81-
if (Op->getType() != IntIdxTy)
82-
Op = Builder->CreateIntCast(Op, IntIdxTy, true, Op->getName().str()+".c");
83-
if (Size != 1) {
84-
// We'll let instcombine(mul) convert this to a shl if possible.
85-
Op = Builder->CreateMul(Op, ConstantInt::get(IntIdxTy, Size),
86-
GEP->getName().str() + ".idx", false /*NUW*/,
87-
isInBounds /*NSW*/);
88-
}
89-
Offset = Op;
90-
}
91-
92-
if (Result)
93-
Result = Builder->CreateAdd(Result, Offset, GEP->getName().str()+".offs",
94-
false /*NUW*/, isInBounds /*NSW*/);
95-
else
96-
Result = Offset;
97-
}
98-
return Result ? Result : Constant::getNullValue(IntIdxTy);
99-
}
29+
Value *emitGEPOffset(IRBuilderBase *Builder, const DataLayout &DL, User *GEP,
30+
bool NoAssumptions = false);
10031

101-
}
32+
} // namespace llvm
10233

10334
#endif // LLVM_ANALYSIS_UTILS_LOCAL_H

llvm/lib/Analysis/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ add_llvm_component_library(LLVMAnalysis
9191
LegacyDivergenceAnalysis.cpp
9292
Lint.cpp
9393
Loads.cpp
94+
Local.cpp
9495
LoopAccessAnalysis.cpp
9596
LoopAnalysisManager.cpp
9697
LoopCacheAnalysis.cpp

llvm/lib/Analysis/Local.cpp

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
//===- Local.cpp - Functions to perform local transformations -------------===//
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+
// This family of functions perform various local transformations to the
10+
// program.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#include "llvm/Analysis/Utils/Local.h"
15+
#include "llvm/ADT/Twine.h"
16+
#include "llvm/IR/DataLayout.h"
17+
#include "llvm/IR/GetElementPtrTypeIterator.h"
18+
#include "llvm/IR/IRBuilder.h"
19+
20+
using namespace llvm;
21+
22+
Value *llvm::emitGEPOffset(IRBuilderBase *Builder, const DataLayout &DL,
23+
User *GEP, bool NoAssumptions) {
24+
GEPOperator *GEPOp = cast<GEPOperator>(GEP);
25+
Type *IntIdxTy = DL.getIndexType(GEP->getType());
26+
Value *Result = nullptr;
27+
28+
// If the GEP is inbounds, we know that none of the addressing operations will
29+
// overflow in a signed sense.
30+
bool isInBounds = GEPOp->isInBounds() && !NoAssumptions;
31+
32+
// Build a mask for high order bits.
33+
unsigned IntPtrWidth = IntIdxTy->getScalarType()->getIntegerBitWidth();
34+
uint64_t PtrSizeMask =
35+
std::numeric_limits<uint64_t>::max() >> (64 - IntPtrWidth);
36+
37+
gep_type_iterator GTI = gep_type_begin(GEP);
38+
for (User::op_iterator i = GEP->op_begin() + 1, e = GEP->op_end(); i != e;
39+
++i, ++GTI) {
40+
Value *Op = *i;
41+
uint64_t Size = DL.getTypeAllocSize(GTI.getIndexedType()) & PtrSizeMask;
42+
Value *Offset;
43+
if (Constant *OpC = dyn_cast<Constant>(Op)) {
44+
if (OpC->isZeroValue())
45+
continue;
46+
47+
// Handle a struct index, which adds its field offset to the pointer.
48+
if (StructType *STy = GTI.getStructTypeOrNull()) {
49+
uint64_t OpValue = OpC->getUniqueInteger().getZExtValue();
50+
Size = DL.getStructLayout(STy)->getElementOffset(OpValue);
51+
if (!Size)
52+
continue;
53+
54+
Offset = ConstantInt::get(IntIdxTy, Size);
55+
} else {
56+
// Splat the constant if needed.
57+
if (IntIdxTy->isVectorTy() && !OpC->getType()->isVectorTy())
58+
OpC = ConstantVector::getSplat(
59+
cast<VectorType>(IntIdxTy)->getElementCount(), OpC);
60+
61+
Constant *Scale = ConstantInt::get(IntIdxTy, Size);
62+
Constant *OC =
63+
ConstantExpr::getIntegerCast(OpC, IntIdxTy, true /*SExt*/);
64+
Offset =
65+
ConstantExpr::getMul(OC, Scale, false /*NUW*/, isInBounds /*NSW*/);
66+
}
67+
} else {
68+
// Splat the index if needed.
69+
if (IntIdxTy->isVectorTy() && !Op->getType()->isVectorTy())
70+
Op = Builder->CreateVectorSplat(
71+
cast<FixedVectorType>(IntIdxTy)->getNumElements(), Op);
72+
73+
// Convert to correct type.
74+
if (Op->getType() != IntIdxTy)
75+
Op = Builder->CreateIntCast(Op, IntIdxTy, true, Op->getName() + ".c");
76+
if (Size != 1) {
77+
// We'll let instcombine(mul) convert this to a shl if possible.
78+
Op = Builder->CreateMul(Op, ConstantInt::get(IntIdxTy, Size),
79+
GEP->getName() + ".idx", false /*NUW*/,
80+
isInBounds /*NSW*/);
81+
}
82+
Offset = Op;
83+
}
84+
85+
if (Result)
86+
Result = Builder->CreateAdd(Result, Offset, GEP->getName() + ".offs",
87+
false /*NUW*/, isInBounds /*NSW*/);
88+
else
89+
Result = Offset;
90+
}
91+
return Result ? Result : Constant::getNullValue(IntIdxTy);
92+
}

llvm/lib/Analysis/MemoryBuiltins.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1150,7 +1150,7 @@ ObjectSizeOffsetEvaluator::visitGEPOperator(GEPOperator &GEP) {
11501150
if (!bothKnown(PtrData))
11511151
return unknown();
11521152

1153-
Value *Offset = EmitGEPOffset(&Builder, DL, &GEP, /*NoAssumptions=*/true);
1153+
Value *Offset = emitGEPOffset(&Builder, DL, &GEP, /*NoAssumptions=*/true);
11541154
Offset = Builder.CreateAdd(PtrData.second, Offset);
11551155
return std::make_pair(PtrData.first, Offset);
11561156
}

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ std::optional<Value *> InstCombiner::targetSimplifyDemandedVectorEltsIntrinsic(
204204
}
205205

206206
Value *InstCombinerImpl::EmitGEPOffset(User *GEP) {
207-
return llvm::EmitGEPOffset(&Builder, DL, GEP);
207+
return llvm::emitGEPOffset(&Builder, DL, GEP);
208208
}
209209

210210
/// Legal integers and common types are considered desirable. This is used to

llvm/utils/gn/secondary/llvm/lib/Analysis/BUILD.gn

+1
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ static_library("Analysis") {
7575
"LegacyDivergenceAnalysis.cpp",
7676
"Lint.cpp",
7777
"Loads.cpp",
78+
"Local.cpp",
7879
"LoopAccessAnalysis.cpp",
7980
"LoopAnalysisManager.cpp",
8081
"LoopCacheAnalysis.cpp",

0 commit comments

Comments
 (0)