// Copyright 2017 The Clspv Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h"

#include <tuple>

#include "BitcastUtils.h"
#include "SimplifyPointerBitcastPass.h"
#include "Types.h"

#include "clspv/AddressSpace.h"
#include "clspv/Option.h"

using namespace llvm;
using namespace BitcastUtils;

#define DEBUG_TYPE "SimplifyPointerBitcast"

PreservedAnalyses
clspv::SimplifyPointerBitcastPass::run(Module &M, ModuleAnalysisManager &) {
  PreservedAnalyses PA;

  // Start by removing all Constant Expressions. Do it only once as all the
  // functions below will not generate new Constant Expression.
  runOnInstFromCstExpr(M);

  // Loop through our individual simplification passes until they stop changing
  // things.
  bool changed = true;
  while (changed) {
    changed = false;

    changed |= runOnTrivialBitcast(M);
    changed |= runOnBitcastFromBitcast(M);
    changed |= runOnImplicitGEP(M);
    while (runOnUpgradeableConstantCasts(M)) {
      changed = true;
    }
    changed |= runOnUnneededIndices(M);
    changed |= runOnImplicitCasts(M);
    changed |= runOnAllocaNotAliasing(M);
    changed |= runOnPHIFromGEP(M);
    changed |= runOnGEPFromGEP(M);
  }

  return PA;
}

void clspv::SimplifyPointerBitcastPass::runOnInstFromCstExpr(Module &M) const {
  for (Function &F : M) {
    BitcastUtils::RemoveCstExprFromFunction(&F);
  }
}

bool clspv::SimplifyPointerBitcastPass::runOnTrivialBitcast(Module &M) const {
  // Remove things like:
  //  bitcast i32 addrspace(1)* %ptr to i32 addrspace(1)*

  SmallVector<BitCastInst *, 16> WorkList;
  for (Function &F : M) {
    for (BasicBlock &BB : F) {
      for (Instruction &I : BB) {
        // If we have a bitcast instruction...
        if (auto Bitcast = dyn_cast<BitCastInst>(&I)) {
          // ... whose source type is the same as the destination type.
          auto Source = Bitcast->getOperand(0);
          if (Source->getType() == Bitcast->getType()) {
            // ... record the bitcast as something we need to process.
            WorkList.push_back(Bitcast);
          }
        }
      }
    }
  }

  const bool Changed = !WorkList.empty();

  for (auto Bitcast : WorkList) {
    auto Source = Bitcast->getOperand(0);
    LLVM_DEBUG(dbgs() << "\n##runOnTrivialBitcast:\nreplaceAllUses of :";
               Bitcast->dump(); dbgs() << "by: "; Source->dump());
    Bitcast->replaceAllUsesWith(Source);

    // Remove the bitcast as it has no users now.
    Bitcast->eraseFromParent();

    // Check if the source value is an instruction and had no other users...
    if (auto SourceInst = dyn_cast<Instruction>(Source)) {
      if (0 == SourceInst->getNumUses()) {
        // ... and remove it if we were its only user.
        SourceInst->eraseFromParent();
      }
    }
  }

  return Changed;
}

bool clspv::SimplifyPointerBitcastPass::runOnBitcastFromBitcast(
    Module &M) const {
  SmallVector<BitCastInst *, 16> WorkList;
  for (Function &F : M) {
    for (BasicBlock &BB : F) {
      for (Instruction &I : BB) {
        // If we have a bitcast instruction...
        if (auto Bitcast = dyn_cast<BitCastInst>(&I)) {
          // ... whose source is a bitcast instruction...
          if (isa<BitCastInst>(Bitcast->getOperand(0))) {
            // ... record the bitcast as something we need to process.
            WorkList.push_back(Bitcast);
          }
          // ... whose source is a bitcast constant expression
          if (const auto CE = dyn_cast<ConstantExpr>(Bitcast->getOperand(0))) {
            if (CE->getOpcode() == Instruction::BitCast) {
              // ... record the bitcast as something we need to process.
              WorkList.push_back(Bitcast);
            }
          }
        }
      }
    }
  }

  const bool Changed = !WorkList.empty();

  for (auto Bitcast : WorkList) {
    Instruction *OtherBitcast = dyn_cast<BitCastInst>(Bitcast->getOperand(0));
    if (!OtherBitcast) {
      auto CE = dyn_cast<ConstantExpr>(Bitcast->getOperand(0));
      assert(CE && CE->getOpcode() == Instruction::BitCast);
      OtherBitcast = CE->getAsInstruction();
      OtherBitcast->insertBefore(Bitcast->getIterator());
    }
    LLVM_DEBUG(dbgs() << "\n##runOnBitcastFromBitcast:\nremove:";
               Bitcast->dump());

    if (OtherBitcast->getType() == Bitcast->getType()) {
      Bitcast->replaceAllUsesWith(OtherBitcast);
      LLVM_DEBUG(dbgs() << "in favor of: "; OtherBitcast->dump());
    } else {
      // Create a new bitcast from the other bitcasts argument to our type.
      auto NewBitcast =
          CastInst::Create(Instruction::BitCast, OtherBitcast->getOperand(0),
                           Bitcast->getType(), "", Bitcast->getIterator());

      // And replace the original bitcast with our replacement bitcast.
      Bitcast->replaceAllUsesWith(NewBitcast);
      LLVM_DEBUG(dbgs() << "in favor of: "; NewBitcast->dump());
    }

    // Remove the bitcast as it has no users now.
    Bitcast->eraseFromParent();

    // Check if the other bitcast had no other users...
    if (0 == OtherBitcast->getNumUses()) {
      // ... and remove it if we were its only user.
      OtherBitcast->eraseFromParent();
    }
  }

  return Changed;
}

bool clspv::SimplifyPointerBitcastPass::runOnGEPFromGEP(Module &M) const {
  SmallVector<GetElementPtrInst *, 16> WorkList;
  for (Function &F : M) {
    for (BasicBlock &BB : F) {
      for (Instruction &I : BB) {
        // If we have a GEP instruction...
        if (auto GEP = dyn_cast<GetElementPtrInst>(&I)) {
          if (Option::UntypedPointerAddressSpace(
                  GEP->getType()->getPointerAddressSpace())) {
            continue;
          }

          // ... whose operand is also a GEP instruction...
          if (auto OtherGEP =
                  dyn_cast<GetElementPtrInst>(GEP->getPointerOperand())) {
            // ... with no implicit cast between them...
            if (OtherGEP->getResultElementType() ==
                GEP->getSourceElementType()) {

              auto LastTypeStruct = [](Type *Ty, SmallVector<Value *> Idxs) {
                Idxs.pop_back();
                return dyn_cast<StructType>(
                    GetElementPtrInst::getIndexedType(Ty, Idxs));
              };
              auto ConstantValue = [](Value *V) {
                if (auto CstVal = dyn_cast<ConstantInt>(V)) {
                  return CstVal->getZExtValue();
                }
                return UINT64_MAX;
              };
              auto LastTypeStructTy =
                  LastTypeStruct(OtherGEP->getSourceElementType(),
                                 SmallVector<Value *>(OtherGEP->indices()));
              if (GEP->getNumOperands() > 1 && LastTypeStructTy != nullptr &&
                  ((ConstantValue(GEP->getOperand(1)) >=
                        LastTypeStructTy->getStructNumElements() &&
                    IsArrayLike(LastTypeStructTy)) ||
                   (ConstantValue(GEP->getOperand(1)) != 0 &&
                    !IsArrayLike(LastTypeStructTy))) &&
                  !(GEP->hasAllConstantIndices() &&
                    OtherGEP->hasAllConstantIndices())) {
                LLVM_DEBUG(dbgs() << "\n##runOnGEPFromGEP:\nskip (out-of-bound "
                                     "struct access): ";
                           OtherGEP->dump(); GEP->dump());
                continue;
              }
              // ... record the GEP as something we need to process.
              WorkList.push_back(GEP);
            }
          }
        }
      }
    }
  }

  const bool Changed = !WorkList.empty();

  for (GetElementPtrInst *GEP : WorkList) {
    IRBuilder<> Builder(GEP);

    auto OtherGEP = cast<GetElementPtrInst>(GEP->getPointerOperand());
    LLVM_DEBUG(dbgs() << "\n##runOnGEPFromGEP:\nreplace: "; OtherGEP->dump();
               GEP->dump());

    Value *SrcLastIdxOp = OtherGEP->getOperand(OtherGEP->getNumOperands() - 1);
    Value *GEPIdxOp = GEP->getOperand(1);

    // Add the indices together, if the last one from before is not zero.
    auto *CstSrcLastIdxOp = dyn_cast<ConstantInt>(SrcLastIdxOp);
    auto CstGEPIdxOp = dyn_cast<ConstantInt>(GEPIdxOp);

    // We need to know the number of element of the commun type between GEP and
    // OtherGEP to avoid generating a constant index greater than this size for
    // private pointer
    uint32_t VecOrArraySize = UINT32_MAX;
    if (OtherGEP->getNumOperands() > 2) {
      SmallVector<Value *, 8> Idxs;
      Idxs.append(OtherGEP->op_begin() + 1, OtherGEP->op_end() - 1);
      unsigned numEle =
          BitcastUtils::GetNumEle(GetElementPtrInst::getIndexedType(
              OtherGEP->getSourceElementType(), Idxs));
      if (numEle > 1 || numEle == 0) {
        VecOrArraySize = numEle;
      }
    } else if (OtherGEP->getNumOperands() == 2) {
      VecOrArraySize =
          BitcastUtils::GetNumEle(OtherGEP->getSourceElementType());
    }
    bool OtherGEPPrevIsCstToStruct = false;
    ConstantInt *OtherGEPLastIdx = nullptr;
    Type *OtherGEPPrevTy = nullptr;
    SmallVector<Value *, 4> OtherGEPIdxs;
    if (OtherGEP->getNumIndices() > 1) {
      OtherGEPIdxs.append(SmallVector<Value *, 4>(OtherGEP->indices()));
      OtherGEPLastIdx =
          dyn_cast<ConstantInt>(OtherGEPIdxs[OtherGEP->getNumIndices() - 1]);
      OtherGEPIdxs.pop_back();
      OtherGEPPrevTy = GetElementPtrInst::getIndexedType(
          OtherGEP->getSourceElementType(), OtherGEPIdxs);
      OtherGEPPrevIsCstToStruct =
          GEP->hasAllConstantIndices() && OtherGEPPrevTy &&
          OtherGEPPrevTy->isStructTy() && OtherGEPLastIdx &&
          !GEP->getSourceElementType()->isAggregateType();
    }

    SmallVector<Value *, 8> Idxs;
    if (OtherGEPPrevIsCstToStruct) {
      int64_t cstVal;
      Value *dynVal;
      size_t smallerBitWidths;
      ExtractOffsetFromGEP(M.getDataLayout(), Builder, GEP, cstVal, dynVal,
                           smallerBitWidths);
      assert(dynVal == nullptr);
      cstVal *= smallerBitWidths;
      int64_t cstVal2 = 0;
      size_t smallerBitWidths2 =
          SizeInBits(M.getDataLayout(), OtherGEP->getResultElementType());
      ExtractOffsetFromStruct(M.getDataLayout(), OtherGEPLastIdx,
                              dyn_cast<StructType>(OtherGEPPrevTy), cstVal2,
                              smallerBitWidths2);
      cstVal += smallerBitWidths2 * cstVal2;
      smallerBitWidths = std::min(smallerBitWidths, smallerBitWidths2);
      cstVal /= smallerBitWidths;
      auto newGEPIdxs = GetIdxsForTyFromOffset(
          M.getDataLayout(), Builder, OtherGEPPrevTy,
          GEP->getResultElementType(), cstVal, dynVal, smallerBitWidths,
          OtherGEP->getPointerOperand());

      Idxs.append(OtherGEPIdxs);
      Idxs.append(
          SmallVector<Value *, 4>(newGEPIdxs.begin() + 1, newGEPIdxs.end()));
    } else if (GEP->hasAllConstantIndices() &&
               OtherGEP->hasAllConstantIndices() &&
               (GEP->getPointerAddressSpace() == clspv::AddressSpace::Private ||
                GEP->getPointerAddressSpace() == clspv::AddressSpace::Local)) {
      int64_t cstVal;
      Value *dynVal;
      size_t smallerBitWidths;
      ExtractOffsetFromGEP(M.getDataLayout(), Builder, OtherGEP, cstVal, dynVal,
                           smallerBitWidths);
      assert(dynVal == nullptr);
      int64_t cstVal2;
      size_t smallerBitWidths2;
      ExtractOffsetFromGEP(M.getDataLayout(), Builder, GEP, cstVal2, dynVal,
                           smallerBitWidths2);
      assert(dynVal == nullptr);
      cstVal = cstVal * smallerBitWidths + cstVal2 * smallerBitWidths2;
      smallerBitWidths = std::min(smallerBitWidths, smallerBitWidths2);
      cstVal /= smallerBitWidths;
      auto NewGEPIdxs = GetIdxsForTyFromOffset(
          M.getDataLayout(), Builder, OtherGEP->getSourceElementType(),
          GEP->getResultElementType(), cstVal, dynVal, smallerBitWidths,
          OtherGEP->getPointerOperand());
      Idxs.append(NewGEPIdxs);
    } else {
      if (CstSrcLastIdxOp && CstGEPIdxOp &&
          (CstSrcLastIdxOp->getZExtValue() + CstGEPIdxOp->getZExtValue() <
           VecOrArraySize)) {
        Idxs.append(OtherGEP->op_begin() + 1, OtherGEP->op_end() - 1);
        if (CstGEPIdxOp->isZero()) {
          Idxs.push_back(SrcLastIdxOp);
        } else if (CstSrcLastIdxOp->isZero()) {
          Idxs.push_back(GEPIdxOp);
        } else {
          Idxs.push_back(ConstantInt::get(
              IntegerType::get(M.getContext(),
                               clspv::PointersAre64Bit(M) &&
                                       !OtherGEP->getType()->isStructTy()
                                   ? 64
                                   : 32),
              CstGEPIdxOp->getZExtValue() + CstSrcLastIdxOp->getZExtValue()));
        }
      } else if (CstGEPIdxOp && CstGEPIdxOp->isZero()) {
        Idxs.append(OtherGEP->op_begin() + 1, OtherGEP->op_end());
      } else if (VecOrArraySize == 0) {
        Idxs.append(OtherGEP->op_begin() + 1, OtherGEP->op_end() - 1);
        if (CstSrcLastIdxOp && CstGEPIdxOp) {
          Idxs.push_back(ConstantInt::get(
              IntegerType::get(M.getContext(),
                               clspv::PointersAre64Bit(M) &&
                                       !OtherGEP->getType()->isStructTy()
                                   ? 64
                                   : 32),
              CstGEPIdxOp->getZExtValue() + CstSrcLastIdxOp->getZExtValue()));
        } else if (CstSrcLastIdxOp && CstSrcLastIdxOp->isZero()) {
          Idxs.push_back(*(GEP->op_begin() + 1));
        } else if (CstGEPIdxOp && CstGEPIdxOp->isZero()) {
          Idxs.push_back(*(OtherGEP->op_end() - 1));
        } else {
          Idxs.push_back(CreateAdd(Builder, *(GEP->op_begin() + 1),
                                   *(OtherGEP->op_end() - 1)));
        }
      } else {
        uint32_t startIndex = 0;
        SmallVector<Value *, 8> TyIdxs;
        SmallVector<Type *, 8> Types;
        for (uint32_t i = 0; i < OtherGEP->getNumOperands() - 1; i++) {
          Value *op = OtherGEP->getOperand(i + 1);
          TyIdxs.push_back(op);
          Type *idxTy = GetElementPtrInst::getIndexedType(
              OtherGEP->getSourceElementType(), TyIdxs);
          Types.push_back(idxTy);
          if (i > 0 && isa<StructType>(Types[i - 1])) {
            startIndex = i + 1;
          }
          // If an unsized type appears due to a representation of a descriptor,
          // skip the outer struct.
          if (SizeInBits(M.getDataLayout(), idxTy) == 0) {
            startIndex = 0;
          }
        }

        if (startIndex != 0) {
          // We have to assume that these geps were simply split since we
          // traversed a struct. We would not calculate an appropriate offset
          // into a particular struct.
          Idxs.append(OtherGEP->op_begin() + 1, OtherGEP->op_end() - 1);
          if (CstSrcLastIdxOp && CstSrcLastIdxOp->isZero()) {
            Idxs.push_back(GEP->getOperand(1));
          } else {
            Idxs.push_back(
                Builder.CreateAdd(GEPIdxOp, *(OtherGEP->op_end() - 1)));
          }
        } else {
          int64_t cstVal;
          Value *dynVal;
          size_t smallerBitWidths;
          ExtractOffsetFromGEP(M.getDataLayout(), Builder, OtherGEP, cstVal,
                               dynVal, smallerBitWidths);
          if (CstGEPIdxOp) {
            cstVal += CstGEPIdxOp->getZExtValue();
          } else if (dynVal) {
            dynVal = CreateAdd(Builder, dynVal, GEPIdxOp);
          } else {
            dynVal = GEPIdxOp;
          }
          auto NewGEPIdxs = GetIdxsForTyFromOffset(
              M.getDataLayout(), Builder, OtherGEP->getSourceElementType(),
              OtherGEP->getResultElementType(), cstVal, dynVal,
              smallerBitWidths, OtherGEP->getPointerOperand());
          Idxs.append(NewGEPIdxs);
        }
      }

      Idxs.append(GEP->op_begin() + 2, GEP->op_end());
    }

    // Struct types require i32 indexes, so fix up any constant i64s
    // that are safe to change
    if (clspv::PointersAre64Bit(M) &&
        OtherGEP->getSourceElementType()->isStructTy()) {
      SmallVector<Value *, 8> NewIdxs;
      for (auto *Idx : Idxs) {
        if (auto ConstIdx = dyn_cast<ConstantInt>(Idx)) {
          uint64_t C = ConstIdx->getZExtValue();
          if (C < std::numeric_limits<uint32_t>::max()) {
            NewIdxs.push_back(
                ConstantInt::get(IntegerType::get(M.getContext(), 32), C));
          } else {
            NewIdxs.push_back(Idx);
          }
        } else {
          NewIdxs.push_back(Idx);
        }
      }

      Idxs = NewIdxs;
    }

    Value *NewGEP = nullptr;
    // Create the new GEP.  If we used the Builder it will do some folding
    // that we don't want.  In particular, if the first GEP is to an LLVM
    // constant then the combined GEP will become a ConstantExpr and it
    // will hide the pointer from subsequent passes.  So bypass the Builder
    // and create the GEP instruction directly.
    if (GEP->isInBounds() && OtherGEP->isInBounds()) {
      NewGEP = GetElementPtrInst::CreateInBounds(
          OtherGEP->getSourceElementType(), OtherGEP->getPointerOperand(), Idxs,
          "", GEP->getIterator());
    } else {
      NewGEP = GetElementPtrInst::Create(OtherGEP->getSourceElementType(),
                                         OtherGEP->getPointerOperand(), Idxs,
                                         "", GEP->getIterator());
    }
    LLVM_DEBUG(dbgs() << "by: "; NewGEP->dump());

    // And replace the original GEP with our replacement GEP.
    GEP->replaceAllUsesWith(NewGEP);

    // Remove the GEP as it has no users now.
    GEP->eraseFromParent();

    // Check if the other GEP had no other users...
    if (0 == OtherGEP->getNumUses()) {
      // ... and remove it if we were its only user.
      OtherGEP->eraseFromParent();
    }
  }

  return Changed;
}

bool clspv::SimplifyPointerBitcastPass::runOnImplicitGEP(Module &M) const {
  const DataLayout &DL = M.getDataLayout();
  bool changed = false;
  DenseMap<Value *, Type *> type_cache;

  struct ImplicitGEPAliasing {
    Instruction *inst;
    int steps;
    GetElementPtrInst *gep;
  };
  struct ImplicitGEPBeforeStore {
    Instruction *inst;
    Type *ty;
  };

  SmallVector<ImplicitGEPAliasing> GEPAliasingList;
  SmallVector<ImplicitGEPBeforeStore> GEPBeforeStoreList;
  SmallVector<LoadInst *> GEPBeforeLoadList;
  SmallVector<GetElementPtrInst *> GEPCastList;
  SmallVector<GetElementPtrInst *> GEPGVList;
  for (auto &F : M) {
    for (auto &BB : F) {
      for (auto &I : BB) {
        Value *source = nullptr;
        Type *source_ty = nullptr;
        Type *dest_ty = nullptr;
        if (!IsImplicitCasts(M, type_cache, I, source, source_ty, dest_ty, true,
                             false /* do not rework unsized types */)) {
          continue;
        }

        int Steps = 0;
        bool PerfectMatch;
        if (FindAliasingContainedType(source_ty, dest_ty, Steps, PerfectMatch,
                                      DL)) {
          // PHI Node are handle in runOnPHIFromGEP if it is really needed
          if (isa<PHINode>(&I)) {
            continue;
          }

          // Single level GEP is ok to transform, but beyond
          // that the address math must be divided among other
          // entries.
          auto *gep = dyn_cast<GetElementPtrInst>(&I);
          auto *call = dyn_cast_or_null<CallInst>(&I);
          bool userCall = call && !call->getCalledFunction()->isDeclaration();
          if (!userCall && (gep || PerfectMatch)) {
            GEPAliasingList.push_back(
                {&I, Steps, PerfectMatch ? nullptr : gep});
          }
        } else if (isa<StoreInst>(&I) && !isa<GetElementPtrInst>(source)) {
          GEPBeforeStoreList.push_back({&I, dest_ty});
        } else if (isa<LoadInst>(&I) && isa<GetElementPtrInst>(source) &&
                   SizeInBits(DL, dest_ty) < SizeInBits(DL, source_ty)) {
          GEPBeforeLoadList.push_back(dyn_cast<LoadInst>(&I));
        } else if (auto gep = dyn_cast<GetElementPtrInst>(&I)) {
          if (IsClspvResourceOrLocal(gep->getPointerOperand()) ||
              gep->getResultElementType() == source_ty) {
            GEPCastList.push_back(dyn_cast<GetElementPtrInst>(&I));
          } else if (IsGVConstantGEP(gep)) {
            GEPGVList.push_back(dyn_cast<GetElementPtrInst>(&I));
          }
        }
      }
    }
  }

  // Implicit GEPs (i.e. GEPs that are elided because all indices are zero) are
  // handled by explcitly inserting the GEP.
  for (auto GEPInfo : GEPAliasingList) {
    auto *I = GEPInfo.inst;
    auto Steps = GEPInfo.steps;
    auto *gep = GEPInfo.gep;
    IRBuilder<> Builder{I};
    SmallVector<Value *, 8> GEPIndices{};
    unsigned PointerOperandNum = BitcastUtils::PointerOperandNum(I);

    for (int i = 0; i < Steps + 1; i++) {
      GEPIndices.push_back(Builder.getInt32(0));
    }

    Value *PointerOp = I->getOperand(PointerOperandNum);
    auto *PointerOpType =
        clspv::InferType(PointerOp, M.getContext(), &type_cache);
    auto *NewGEP = GetElementPtrInst::Create(PointerOpType, PointerOp,
                                             GEPIndices, "", I->getIterator());
    LLVM_DEBUG(dbgs() << "\n##runOnImplicitGEP (aliasing):\nadding: ";
               NewGEP->dump());

    if (gep) {
      // Typical usecase here is a GEP on a struct of float, followed by a GEP
      // on a int. Replace the last GEP by a GEP on a float.
      auto *NewCastGEP = GetElementPtrInst::Create(
          NewGEP->getResultElementType(), NewGEP,
          SmallVector<Value *, 1>(gep->indices()), "", I->getIterator());
      LLVM_DEBUG(dbgs() << "instead of: "; I->dump());
      I->replaceAllUsesWith(NewCastGEP);
      I->eraseFromParent();
    } else {
      LLVM_DEBUG(dbgs() << "instead of operand " << PointerOperandNum
                        << " of: ";
                 I->dump());
      I->setOperand(PointerOperandNum, NewGEP);
    }
    changed = true;
  }

  for (auto GEPInfo : GEPBeforeStoreList) {
    auto *I = GEPInfo.inst;
    auto *Ty = GEPInfo.ty;
    IRBuilder<> Builder{I};
    unsigned PointerOperandNum = BitcastUtils::PointerOperandNum(I);
    Value *PointerOp = I->getOperand(PointerOperandNum);
    auto gep = GetElementPtrInst::Create(Ty, PointerOp, {Builder.getInt32(0)},
                                         "", I->getIterator());
    LLVM_DEBUG(dbgs() << "\n##runOnImplicitGEP (before store):\nadding: ";
               gep->dump());
    LLVM_DEBUG(dbgs() << "instead of operand " << PointerOperandNum << " of: ";
               I->dump());
    I->setOperand(PointerOperandNum, gep);
    changed = true;
  }

  for (auto *LoadInst : GEPBeforeLoadList) {
    IRBuilder<> Builder{LoadInst};
    auto *Ty = LoadInst->getType();
    auto initial_gep =
        dyn_cast<GetElementPtrInst>(LoadInst->getPointerOperand());
    auto Ptr = initial_gep->getPointerOperand();

    int64_t cstVal;
    Value *dynVal;
    size_t smallerBitWidths;
    ExtractOffsetFromGEP(M.getDataLayout(), Builder, initial_gep, cstVal,
                         dynVal, smallerBitWidths);
    int64_t newBitWidths = SizeInBits(DL, Ty);

    cstVal *= smallerBitWidths;
    if (cstVal < newBitWidths) {
      continue;
    }
    cstVal /= newBitWidths;
    if (dynVal) {
      dynVal = CreateMul(Builder, smallerBitWidths / newBitWidths, dynVal);
    }
    auto NewGEPIdxs =
        GetIdxsForTyFromOffset(M.getDataLayout(), Builder, Ty, Ty, cstVal,
                               dynVal, SizeInBits(DL, Ty), Ptr);

    auto gep = GetElementPtrInst::Create(Ty, Ptr, NewGEPIdxs, "",
                                         LoadInst->getIterator());
    unsigned PointerOperandNum = BitcastUtils::PointerOperandNum(LoadInst);
    LLVM_DEBUG(dbgs() << "\n##runOnImplicitGEP (before load):\nadding: ";
               gep->dump());
    LLVM_DEBUG(dbgs() << "instead of operand " << PointerOperandNum << ": ";
               LoadInst->getPointerOperand()->dump(););
    LLVM_DEBUG(dbgs() << "of: "; LoadInst->dump(););
    LoadInst->setOperand(PointerOperandNum, gep);

    if (initial_gep->getNumUses() == 0) {
      initial_gep->eraseFromParent();
    }

    changed = true;
  }

  for (auto gep : GEPCastList) {
    auto ptr = gep->getPointerOperand();
    auto ty = InferType(ptr, M.getContext(), &type_cache);
    IRBuilder<> Builder{gep};
    int64_t cstVal;
    Value *dynVal;
    size_t smallerBitWidths;
    ExtractOffsetFromGEP(DL, Builder, gep, cstVal, dynVal, smallerBitWidths);
    auto new_gep_idxs =
        GetIdxsForTyFromOffset(DL, Builder, ty, reworkUnsizedType(DL, ty),
                               cstVal, dynVal, smallerBitWidths, ptr);
    auto new_gep = GetElementPtrInst::Create(ty, ptr, new_gep_idxs, "",
                                             gep->getIterator());
    LLVM_DEBUG(dbgs() << "\n##runOnImplicitGEP (gep cast):\nreplacing: ";
               gep->dump());
    LLVM_DEBUG(dbgs() << "by: "; new_gep->dump(););
    gep->replaceAllUsesWith(new_gep);
    gep->eraseFromParent();
    changed = true;
  }
  for (auto gep : GEPGVList) {
    auto ptr = gep->getPointerOperand();
    auto ty = InferType(ptr, M.getContext(), &type_cache);
    IRBuilder<> Builder{gep};
    int64_t cstVal;
    Value *dynVal;
    size_t smallerBitWidths;
    ExtractOffsetFromGEP(DL, Builder, gep, cstVal, dynVal, smallerBitWidths);
    auto new_gep_idxs = GetIdxsForTyFromOffset(DL, Builder, ty, nullptr, cstVal,
                                               dynVal, smallerBitWidths, ptr);
    auto new_gep = GetElementPtrInst::Create(ty, ptr, new_gep_idxs, "",
                                             gep->getIterator());
    LLVM_DEBUG(dbgs() << "\n##runOnImplicitGEP (from GV):\nreplacing: ";
               gep->dump());
    LLVM_DEBUG(dbgs() << "by: "; new_gep->dump(););
    gep->replaceAllUsesWith(new_gep);
    gep->eraseFromParent();
    changed = true;
  }

  return changed;
}

bool clspv::SimplifyPointerBitcastPass::runOnImplicitCasts(Module &M) const {
  const DataLayout &DL = M.getDataLayout();
  bool changed = false;
  DenseMap<Value *, Type *> type_cache;

  SmallVector<GetElementPtrInst *, 8> Worklist;
  for (auto &F : M) {
    for (auto &BB : F) {
      for (auto &I : BB) {
        Value *source = nullptr;
        Type *source_ty = nullptr;
        Type *dest_ty = nullptr;

        if (!IsImplicitCasts(M, type_cache, I, source, source_ty, dest_ty,
                             true)) {
          continue;
        }

        if (isa<GetElementPtrInst>(source)) {
          if (auto *inst_gep = dyn_cast<GetElementPtrInst>(&I)) {
            auto VecSrcTy = dyn_cast<FixedVectorType>(source_ty);
            auto VecDstTy = dyn_cast<FixedVectorType>(dest_ty);

            // Do not lower implicit cast containing vec3, this would revert
            // ThreeElementVectorLoweringPass and ReplacePointerBitcastPass
            // should be able to deal with it without issues.
            if (!(VecSrcTy && VecDstTy &&
                  (VecSrcTy->getNumElements() == 3 ||
                   VecDstTy->getNumElements() == 3))) {
              Worklist.emplace_back(inst_gep);
            }
          }
        }
      }
    }
  }

  for (auto inst_gep : Worklist) {
    GetElementPtrInst *src_gep =
        cast<GetElementPtrInst>(inst_gep->getPointerOperand());

    IRBuilder<> Builder{inst_gep};
    SmallVector<Value *> Idxs;
    Value *src;
    Type *src_ty;
    if (src_gep->hasAllZeroIndices()) {
      src_ty = inst_gep->getSourceElementType();
      src = src_gep->getPointerOperand();
      Idxs = SmallVector<Value *>(inst_gep->indices());
    } else {
      src_ty = src_gep->getResultElementType();
      src = src_gep;
      int64_t CstVal;
      Value *DynVal;
      size_t SmallerBitWidths;
      ExtractOffsetFromGEP(DL, Builder, inst_gep, CstVal, DynVal,
                           SmallerBitWidths);

      if (DynVal == nullptr &&
          GoThroughTypeAtOffset(DL, Builder, src_ty, src_ty, nullptr,
                                CstVal * SmallerBitWidths, nullptr) != 0) {
        src = src_gep->getPointerOperand();
        src_ty = inst_gep->getSourceElementType();
        int64_t srcCstVal;
        Value *srcDynVal;
        size_t srcSmallerBitWidths;
        ExtractOffsetFromGEP(DL, Builder, src_gep, srcCstVal, srcDynVal,
                             srcSmallerBitWidths);
        if (SmallerBitWidths < srcSmallerBitWidths) {
          srcCstVal *= srcSmallerBitWidths / SmallerBitWidths;
          if (srcDynVal) {
            srcDynVal = CreateMul(
                Builder, srcSmallerBitWidths / SmallerBitWidths, srcDynVal);
          }
        } else if (SmallerBitWidths > srcSmallerBitWidths) {
          CstVal *= SmallerBitWidths / srcSmallerBitWidths;
          if (DynVal) {
            DynVal = CreateMul(Builder, SmallerBitWidths / srcSmallerBitWidths,
                               DynVal);
          }
        }
        CstVal += srcCstVal;
        if (DynVal && srcDynVal) {
          DynVal = Builder.CreateAdd(DynVal, srcDynVal);
        } else if (srcDynVal) {
          DynVal = srcDynVal;
        }
      }
      Idxs = GetIdxsForTyFromOffset(
          DL, Builder, src_ty, inst_gep->getResultElementType(), CstVal, DynVal,
          SmallerBitWidths, src_gep->getPointerOperand());
    }
    auto new_gep = GetElementPtrInst::Create(src_ty, src, Idxs, "",
                                             inst_gep->getIterator());
    LLVM_DEBUG(dbgs() << "\n##runOnImplicitCasts:\nreplace: "; inst_gep->dump();
               dbgs() << "by: "; new_gep->dump());
    inst_gep->replaceAllUsesWith(new_gep);
    inst_gep->eraseFromParent();
    changed = true;
  }

  return changed;
}

bool clspv::SimplifyPointerBitcastPass::runOnUpgradeableConstantCasts(
    Module &M) const {
  const DataLayout &DL = M.getDataLayout();
  bool changed = false;
  DenseMap<Value *, Type *> type_cache;

  struct UpgradeInfo {
    Instruction *inst;
    int64_t cst;
    Value *val;
    size_t smallerBitWidth;
    Type *dest_ty;
    GetElementPtrInst *gep;
  };
  auto gepIndicesCanBeUpgradedTo = [&DL, &M](Type *ty, GetElementPtrInst *gep,
                                             int64_t &cstVal, Value *&dynVal,
                                             size_t &smallerBitWidths) {
    if (gep->hasAllConstantIndices()) {
      // should not be used as all indices are constant
      IRBuilder<> Builder{gep};

      ExtractOffsetFromGEP(DL, Builder, gep, cstVal, dynVal, smallerBitWidths);
      assert(dynVal == nullptr);
      if (((cstVal * smallerBitWidths) % SizeInBits(DL, ty)) != 0) {
        return false;
      }
    } else {
      // if gep contains dynamic indices, only consider i8 gep width and look
      // for mul and shl composing the single indice.
      if (gep->getSourceElementType() != Type::getInt8Ty(M.getContext()) ||
          gep->getNumIndices() != 1) {
        return false;
      }
      cstVal = 0;
      smallerBitWidths = CHAR_BIT;
      dynVal = gep->getOperand(gep->getNumOperands() - 1);

      SmallVector<Value *> vector;
      vector.push_back(dynVal);
      uint32_t coef = CHAR_BIT;
      uint32_t coef_target = SizeInBits(DL, ty);
      while (!vector.empty()) {
        auto val = vector.back();
        vector.pop_back();
        if (auto cst = dyn_cast<ConstantInt>(val)) {
          coef *= cst->getZExtValue();
          continue;
        }
        auto binary_op = dyn_cast<BinaryOperator>(val);
        if (!binary_op) {
          continue;
        }
        switch (binary_op->getOpcode()) {
        case Instruction::BinaryOps::Mul:
          vector.push_back(binary_op->getOperand(0));
          vector.push_back(binary_op->getOperand(1));
          break;
        case Instruction::BinaryOps::Shl:
          vector.push_back(binary_op->getOperand(0));
          if (auto cst = dyn_cast<ConstantInt>(binary_op->getOperand(1))) {
            coef <<= cst->getZExtValue();
          }
          break;
        default:
          continue;
        }
      }
      if ((coef % coef_target) != 0) {
        return false;
      }
    }
    return true;
  };
  SmallVector<UpgradeInfo, 8> Worklist;
  SmallVector<UpgradeInfo, 8> GEPsDefiningPHIsWorklist;
  DenseSet<GetElementPtrInst *> GEPsDefiningPHISeen;
  for (auto &F : M) {
    for (auto &BB : F) {
      for (auto &I : BB) {
        Value *source = nullptr;
        Type *source_ty = nullptr;
        Type *dest_ty = nullptr;

        auto isMemcpy = [](Instruction *I) {
          auto memcpy = dyn_cast<CallInst>(I);
          if (memcpy == nullptr)
            return false;
          return memcpy->getCalledFunction()->getIntrinsicID() ==
                 Intrinsic::memcpy;
        };
        // memcpy cannot be simplify by this function, skip them to avoid having
        // to support them in function like `BitcastUtils::PointerOperandNum`.
        if (!IsImplicitCasts(M, type_cache, I, source, source_ty, dest_ty,
                             true) ||
            isMemcpy(&I)) {
          continue;
        }

        if (auto *gep = dyn_cast<GetElementPtrInst>(source)) {
          if (SizeInBits(DL, source_ty) >= SizeInBits(DL, dest_ty) ||
              IsClspvResourceOrLocal(gep->getPointerOperand())) {
            continue;
          }
          if (IsGVConstantGEP(gep))
            continue;

          int64_t cstVal;
          Value *dynVal;
          size_t smallerBitWidths;

          auto &context = M.getContext();
          auto findBiggerTyToUpdate = [DL, &context, gepIndicesCanBeUpgradedTo,
                                       source_ty, gep, &cstVal, &dynVal,
                                       &smallerBitWidths](Type *dest_ty) {
            if (gepIndicesCanBeUpgradedTo(dest_ty, gep, cstVal, dynVal,
                                          smallerBitWidths)) {
              return dest_ty;
            }
            if (!dest_ty->isIntegerTy()) {
              return source_ty;
            }
            size_t dest_ty_size = SizeInBits(DL, dest_ty);
            dest_ty_size /= 2;

            while (dest_ty_size > SizeInBits(DL, source_ty)) {
              dest_ty = Type::getIntNTy(context, dest_ty_size);
              if (gepIndicesCanBeUpgradedTo(dest_ty, gep, cstVal, dynVal,
                                            smallerBitWidths)) {
                return dest_ty;
              }
              dest_ty_size /= 2;
            }

            return source_ty;
          };
          dest_ty = findBiggerTyToUpdate(dest_ty);
          if (dest_ty != source_ty) {

            Worklist.push_back(
                {&I, cstVal, dynVal, smallerBitWidths, dest_ty, gep});
          }
        } else if (auto *phi = dyn_cast<PHINode>(source)) {
          auto &context = M.getContext();
          auto get_geps_defining_phis_type = [phi, source_ty, dest_ty, &context,
                                              &type_cache, &GEPsDefiningPHISeen,
                                              gepIndicesCanBeUpgradedTo]() {
            SmallVector<UpgradeInfo> geps;
            SmallVector<Value *> values;
            SmallVector<PHINode *> phis;
            DenseSet<PHINode *> phis_seen;
            phis.push_back(phi);
            // phi can depend on other phis recursively, go through them to find
            // all the values that needing to be upgraded to change the phi
            // type.
            while (!phis.empty()) {
              auto current_phi = phis.back();
              phis.pop_back();
              if (phis_seen.count(current_phi) != 0) {
                continue;
              }
              phis_seen.insert(current_phi);
              for (auto &incoming_value : current_phi->incoming_values()) {
                auto val = incoming_value.get();
                if (auto phi_node = dyn_cast<PHINode>(val)) {
                  phis.push_back(phi_node);
                } else {
                  values.push_back(val);
                }
              }
              for (auto user : current_phi->users()) {
                if (auto phi_node = dyn_cast<PHINode>(user)) {
                  phis.push_back(phi_node);
                } else {
                  values.push_back(user);
                }
              }
            }
            for (auto value : values) {
              auto user_ty = clspv::InferType(value, context, &type_cache);
              if (user_ty != source_ty) {
                continue;
              }
              auto gep = dyn_cast<GetElementPtrInst>(value);
              int64_t cstVal;
              Value *dynVal;
              size_t smallerBitWidths;
              if (gep == nullptr ||
                  !gepIndicesCanBeUpgradedTo(dest_ty, gep, cstVal, dynVal,
                                             smallerBitWidths)) {
                geps.clear();
                return geps;
              }
              if (GEPsDefiningPHISeen.count(gep) == 0) {
                GEPsDefiningPHISeen.insert(gep);
                geps.push_back(
                    {gep, cstVal, dynVal, smallerBitWidths, dest_ty, gep});
              }
            }
            return geps;
          };
          GEPsDefiningPHIsWorklist.append(get_geps_defining_phis_type());
        }
      }
    }
  }

  for (auto GEPInfo : GEPsDefiningPHIsWorklist) {
    auto gep = dyn_cast<GetElementPtrInst>(GEPInfo.inst);
    int64_t cst = GEPInfo.cst;
    Value *val = GEPInfo.val;
    size_t smallerBitWidths = GEPInfo.smallerBitWidth;
    Type *dest_ty = GEPInfo.dest_ty;
    Value *ptr = GEPInfo.gep->getPointerOperand();
    IRBuilder Builder{gep};

    auto NewGEPIdxs =
        GetIdxsForTyFromOffset(M.getDataLayout(), Builder, dest_ty, dest_ty,
                               cst, val, smallerBitWidths, ptr);

    auto new_gep = GetElementPtrInst::Create(dest_ty, ptr, NewGEPIdxs, "",
                                             gep->getIterator());
    LLVM_DEBUG(dbgs() << "\n##runOnUpgradeableConstantCasts:\nreplace gep "
                         "defining phi type: ";
               gep->dump(); dbgs() << "by: "; new_gep->dump());

    gep->replaceAllUsesWith(new_gep);
    gep->eraseFromParent();

    changed = true;
  }
  if (changed) {
    return changed;
  }

  DenseSet<Instruction *> ToBeRemoved;
  for (auto GEPInfo : Worklist) {
    Instruction *I = GEPInfo.inst;
    int64_t cst = GEPInfo.cst;
    Value *val = GEPInfo.val;
    size_t smallerBitWidths = GEPInfo.smallerBitWidth;
    Type *dest_ty = GEPInfo.dest_ty;
    Value *ptr = GEPInfo.gep->getPointerOperand();
    IRBuilder Builder{GEPInfo.gep};

    auto NewGEPIdxs =
        GetIdxsForTyFromOffset(M.getDataLayout(), Builder, dest_ty, dest_ty,
                               cst, val, smallerBitWidths, ptr);

    auto new_gep = GetElementPtrInst::Create(dest_ty, ptr, NewGEPIdxs, "",
                                             GEPInfo.gep->getIterator());

    unsigned PointerOperandNum = BitcastUtils::PointerOperandNum(I);
    if (auto phi = dyn_cast<PHINode>(I)) {
      for (uint32_t iOp = 0; iOp < phi->getNumOperands(); iOp++) {
        if (I->getOperand(iOp) == GEPInfo.gep) {
          PointerOperandNum = iOp;
        }
      }
    }

    LLVM_DEBUG(dbgs() << "\n##runOnUpgradeableConstantCasts:\nreplace operand "
                      << PointerOperandNum << " of: ";
               I->dump(); dbgs() << "by: "; new_gep->dump());
    auto initial_inst = dyn_cast<Instruction>(I->getOperand(PointerOperandNum));
    I->setOperand(PointerOperandNum, new_gep);

    if (initial_inst != nullptr) {
      ToBeRemoved.insert(initial_inst);
      if (initial_inst->getNumUses() > 0) {
        initial_inst->replaceAllUsesWith(new_gep);
      }
    }

    changed = true;
  }

  for (auto *I : ToBeRemoved) {
    I->eraseFromParent();
  }

  return changed;
}

bool clspv::SimplifyPointerBitcastPass::runOnUnneededIndices(Module &M) const {
  const DataLayout &DL = M.getDataLayout();
  bool changed = false;
  DenseMap<Value *, Type *> type_cache;

  SmallVector<std::pair<GetElementPtrInst *, Instruction *>> Worklist;
  for (auto &F : M) {
    for (auto &BB : F) {
      for (auto &I : BB) {
        Value *source = nullptr;
        Type *source_ty = nullptr;
        Type *dest_ty = nullptr;
        if (!IsImplicitCasts(M, type_cache, I, source, source_ty, dest_ty,
                             true)) {
          continue;
        }
        if (auto gep = dyn_cast<GetElementPtrInst>(source)) {
          if (gep->getNumIndices() <= 1)
            continue;
          if (IsGVConstantGEP(gep))
            continue;
          if (SizeInBits(DL, source_ty) < SizeInBits(DL, dest_ty)) {
            if (auto cst = dyn_cast<ConstantInt>(
                    gep->getOperand(gep->getNumOperands() - 1))) {
              if (cst->getZExtValue() == 0) {
                Worklist.push_back(std::make_pair(gep, &I));
              }
            }
          }
        }
      }
    }
  }

  for (auto pair : Worklist) {
    GetElementPtrInst *gep = pair.first;
    Instruction *I = pair.second;
    SmallVector<Value *> Indices(gep->indices());
    while (Indices.size() > 1) {
      auto lastIndice = Indices.back();
      if (auto cst = dyn_cast<ConstantInt>(lastIndice)) {
        if (cst->getZExtValue() == 0) {
          Indices.pop_back();
        } else {
          break;
        }
      } else {
        break;
      }
    }
    IRBuilder<> Builder{gep};
    auto new_gep = GetElementPtrInst::Create(gep->getSourceElementType(),
                                             gep->getPointerOperand(), Indices,
                                             "", gep->getIterator());
    LLVM_DEBUG(dbgs() << "\nrunOnUnneededIndices:\nreplace: "; gep->dump();
               dbgs() << "by: "; new_gep->dump(); dbgs() << "in: "; I->dump());
    I->replaceUsesOfWith(gep, new_gep);
    if (gep->getNumUses() == 0) {
      gep->eraseFromParent();
    }
    changed = true;
  }

  return changed;
}

bool clspv::SimplifyPointerBitcastPass::runOnPHIFromGEP(Module &M) const {
  const DataLayout &DL = M.getDataLayout();
  bool changed = false;
  DenseMap<Value *, Type *> type_cache;

  struct ImplicitGEPAliasing {
    PHINode *phi;
    int steps;
    GetElementPtrInst *gep;
  };

  DenseSet<GetElementPtrInst *> Seen;
  SmallVector<ImplicitGEPAliasing> GEPAliasingList;
  SmallVector<std::pair<GetElementPtrInst *, Type *>> Worklist;
  for (auto &F : M) {
    for (auto &BB : F) {
      for (auto &I : BB) {
        Value *source = nullptr;
        Type *source_ty = nullptr;
        Type *dest_ty = nullptr;

        if (!IsImplicitCasts(M, type_cache, I, source, source_ty, dest_ty,
                             true)) {
          continue;
        }

        if (auto gep = dyn_cast<GetElementPtrInst>(source)) {
          if (Seen.contains(gep)) {
            continue;
          }
          if (auto phi = dyn_cast<PHINode>(&I)) {

            int Steps;
            bool PerfectMatch;
            if (FindAliasingContainedType(source_ty, dest_ty, Steps,
                                          PerfectMatch, DL) &&
                PerfectMatch) {
              GEPAliasingList.push_back({phi, Steps, gep});
            } else if (!FindAliasingContainedType(dest_ty, source_ty, Steps,
                                                  PerfectMatch, DL)) {

              Worklist.emplace_back(std::make_pair(gep, dest_ty));
            }
            Seen.insert(gep);
          }
        }
      }
    }
  }

  for (auto pair : Worklist) {
    GetElementPtrInst *gep = pair.first;
    Type *Ty = pair.second;

    IRBuilder<> Builder{gep};
    int64_t CstVal;
    Value *DynVal;
    size_t SmallerBitWidths;
    ExtractOffsetFromGEP(DL, Builder, gep, CstVal, DynVal, SmallerBitWidths);
    auto Idxs =
        GetIdxsForTyFromOffset(DL, Builder, Ty, nullptr, CstVal, DynVal,
                               SmallerBitWidths, gep->getPointerOperand());
    auto new_gep = GetElementPtrInst::Create(Ty, gep->getPointerOperand(), Idxs,
                                             "", gep->getIterator());
    LLVM_DEBUG(dbgs() << "\n##runOnPHIFromGEP:\nreplace: "; gep->dump();
               dbgs() << "by: "; new_gep->dump());
    gep->replaceAllUsesWith(new_gep);
    gep->eraseFromParent();
    changed = true;
  }

  for (auto GEPInfo : GEPAliasingList) {
    auto *phi = GEPInfo.phi;
    auto Steps = GEPInfo.steps;
    auto *gep = GEPInfo.gep;
    IRBuilder<> B(gep);
    SmallVector<Value *> Idxs;
    for (int i = 0; i < Steps + 1; i++) {
      Idxs.push_back(B.getInt32(0));
    }
    auto new_gep =
        GetElementPtrInst::Create(gep->getResultElementType(), gep, Idxs, "",
                                  gep->getNextNode()->getIterator());
    for (unsigned i = 0; i < phi->getNumIncomingValues(); i++) {
      if (phi->getIncomingValue(i) != gep) {
        continue;
      }
      changed = true;
      LLVM_DEBUG(dbgs() << "\n##runOnPHIFromGEPAliasing:\nreplace: ";
                 gep->dump(); dbgs() << "by: "; new_gep->dump();
                 dbgs() << "in: "; phi->dump());

      phi->setIncomingValue(i, new_gep);
    }
  }
  return changed;
}

bool clspv::SimplifyPointerBitcastPass::runOnAllocaNotAliasing(
    Module &M) const {
  const DataLayout &DL = M.getDataLayout();
  DenseMap<Value *, Type *> type_cache;

  DenseMap<AllocaInst *, Type *> Allocas;
  for (auto &F : M) {
    for (auto &BB : F) {
      for (auto &I : BB) {
        Value *source = nullptr;
        Type *source_ty = nullptr;
        Type *dest_ty = nullptr;

        if (!IsImplicitCasts(M, type_cache, I, source, source_ty, dest_ty,
                             true)) {
          continue;
        }

        auto alloca = dyn_cast<AllocaInst>(source);
        auto gep = dyn_cast<GetElementPtrInst>(&I);
        if (!alloca || !gep || (gep && gep->getNumUses() == 0)) {
          continue;
        }
        int Steps;
        bool PerfectMatch;
        dest_ty = gep->getResultElementType();
        Type *source_ele_ty = GetEleType(source_ty);
        while (source_ele_ty != source_ty) {
          source_ty = source_ele_ty;
          source_ele_ty = GetEleType(source_ty);
        }
        if (FindAliasingContainedType(source_ty, dest_ty, Steps, PerfectMatch,
                                      DL) ||
            SizeInBits(DL, dest_ty) >= SizeInBits(DL, source_ty)) {
          continue;
        }
        if (Allocas.count(alloca) == 0) {
          Allocas.insert(std::make_pair(cast<AllocaInst>(source), dest_ty));
        } else if (SizeInBits(DL, dest_ty) < SizeInBits(DL, Allocas[alloca])) {
          Allocas[alloca] = dest_ty;
        }
      }
    }
  }

  for (auto &pair : Allocas) {
    auto *alloca = pair.first;
    auto *Ty = pair.second;

    IRBuilder<> B(alloca);
    auto nb_elem =
        alloca->getAllocationSizeInBits(DL).value() / SizeInBits(DL, Ty);
    if (nb_elem > 1) {
      Ty = ArrayType::get(Ty, nb_elem);
    }
    auto new_alloca = B.CreateAlloca(Ty, alloca->getAddressSpace());

    LLVM_DEBUG(dbgs() << "\n##runOnAllocaNotAliasing:\nreplace: ";
               alloca->dump(); dbgs() << "by: "; new_alloca->dump());

    alloca->replaceAllUsesWith(new_alloca);
    alloca->eraseFromParent();
  }

  return Allocas.size() != 0;
}
