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