1a3d58bbaSBenjamin Kramer //===- Local.cpp - Functions to perform local transformations -------------===//
2a3d58bbaSBenjamin Kramer //
3a3d58bbaSBenjamin Kramer // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4a3d58bbaSBenjamin Kramer // See https://llvm.org/LICENSE.txt for license information.
5a3d58bbaSBenjamin Kramer // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a3d58bbaSBenjamin Kramer //
7a3d58bbaSBenjamin Kramer //===----------------------------------------------------------------------===//
8a3d58bbaSBenjamin Kramer //
9a3d58bbaSBenjamin Kramer // This family of functions perform various local transformations to the
10a3d58bbaSBenjamin Kramer // program.
11a3d58bbaSBenjamin Kramer //
12a3d58bbaSBenjamin Kramer //===----------------------------------------------------------------------===//
13a3d58bbaSBenjamin Kramer
14a3d58bbaSBenjamin Kramer #include "llvm/Analysis/Utils/Local.h"
15a3d58bbaSBenjamin Kramer #include "llvm/ADT/Twine.h"
16a3d58bbaSBenjamin Kramer #include "llvm/IR/DataLayout.h"
17a3d58bbaSBenjamin Kramer #include "llvm/IR/GetElementPtrTypeIterator.h"
18a3d58bbaSBenjamin Kramer #include "llvm/IR/IRBuilder.h"
19a3d58bbaSBenjamin Kramer
20a3d58bbaSBenjamin Kramer using namespace llvm;
21a3d58bbaSBenjamin Kramer
emitGEPOffset(IRBuilderBase * Builder,const DataLayout & DL,User * GEP,bool NoAssumptions)22a3d58bbaSBenjamin Kramer Value *llvm::emitGEPOffset(IRBuilderBase *Builder, const DataLayout &DL,
23a3d58bbaSBenjamin Kramer User *GEP, bool NoAssumptions) {
24a3d58bbaSBenjamin Kramer GEPOperator *GEPOp = cast<GEPOperator>(GEP);
25a3d58bbaSBenjamin Kramer Type *IntIdxTy = DL.getIndexType(GEP->getType());
26a3d58bbaSBenjamin Kramer Value *Result = nullptr;
27a3d58bbaSBenjamin Kramer
28*fe56f19cSNikita Popov // nusw implies nsw for the offset arithmetic.
29*fe56f19cSNikita Popov bool NSW = GEPOp->hasNoUnsignedSignedWrap() && !NoAssumptions;
30*fe56f19cSNikita Popov bool NUW = GEPOp->hasNoUnsignedWrap() && !NoAssumptions;
3102678bc9SNikita Popov auto AddOffset = [&](Value *Offset) {
3202678bc9SNikita Popov if (Result)
3302678bc9SNikita Popov Result = Builder->CreateAdd(Result, Offset, GEP->getName() + ".offs",
34*fe56f19cSNikita Popov NUW, NSW);
3502678bc9SNikita Popov else
3602678bc9SNikita Popov Result = Offset;
3702678bc9SNikita Popov };
38a3d58bbaSBenjamin Kramer
39a3d58bbaSBenjamin Kramer gep_type_iterator GTI = gep_type_begin(GEP);
40a3d58bbaSBenjamin Kramer for (User::op_iterator i = GEP->op_begin() + 1, e = GEP->op_end(); i != e;
41a3d58bbaSBenjamin Kramer ++i, ++GTI) {
42a3d58bbaSBenjamin Kramer Value *Op = *i;
43a3d58bbaSBenjamin Kramer if (Constant *OpC = dyn_cast<Constant>(Op)) {
44a3d58bbaSBenjamin Kramer if (OpC->isZeroValue())
45a3d58bbaSBenjamin Kramer continue;
46a3d58bbaSBenjamin Kramer
47a3d58bbaSBenjamin Kramer // Handle a struct index, which adds its field offset to the pointer.
48a3d58bbaSBenjamin Kramer if (StructType *STy = GTI.getStructTypeOrNull()) {
49a3d58bbaSBenjamin Kramer uint64_t OpValue = OpC->getUniqueInteger().getZExtValue();
5073af455fSDavid Green uint64_t Size = DL.getStructLayout(STy)->getElementOffset(OpValue);
51a3d58bbaSBenjamin Kramer if (!Size)
52a3d58bbaSBenjamin Kramer continue;
53a3d58bbaSBenjamin Kramer
5402678bc9SNikita Popov AddOffset(ConstantInt::get(IntIdxTy, Size));
5502678bc9SNikita Popov continue;
56a3d58bbaSBenjamin Kramer }
5702678bc9SNikita Popov }
5802678bc9SNikita Popov
59a3d58bbaSBenjamin Kramer // Splat the index if needed.
60a3d58bbaSBenjamin Kramer if (IntIdxTy->isVectorTy() && !Op->getType()->isVectorTy())
61a3d58bbaSBenjamin Kramer Op = Builder->CreateVectorSplat(
6273af455fSDavid Green cast<VectorType>(IntIdxTy)->getElementCount(), Op);
63a3d58bbaSBenjamin Kramer
64a3d58bbaSBenjamin Kramer // Convert to correct type.
65a3d58bbaSBenjamin Kramer if (Op->getType() != IntIdxTy)
66a3d58bbaSBenjamin Kramer Op = Builder->CreateIntCast(Op, IntIdxTy, true, Op->getName() + ".c");
677954c571SJannik Silvanus TypeSize TSize = GTI.getSequentialElementStride(DL);
6881b7f115SSander de Smalen if (TSize != TypeSize::getFixed(1)) {
6973af455fSDavid Green Value *Scale = Builder->CreateTypeSize(IntIdxTy->getScalarType(), TSize);
7073af455fSDavid Green if (IntIdxTy->isVectorTy())
7173af455fSDavid Green Scale = Builder->CreateVectorSplat(
7273af455fSDavid Green cast<VectorType>(IntIdxTy)->getElementCount(), Scale);
73a3d58bbaSBenjamin Kramer // We'll let instcombine(mul) convert this to a shl if possible.
74*fe56f19cSNikita Popov Op = Builder->CreateMul(Op, Scale, GEP->getName() + ".idx", NUW, NSW);
75a3d58bbaSBenjamin Kramer }
7602678bc9SNikita Popov AddOffset(Op);
77a3d58bbaSBenjamin Kramer }
78a3d58bbaSBenjamin Kramer return Result ? Result : Constant::getNullValue(IntIdxTy);
79a3d58bbaSBenjamin Kramer }
80