//===- ScalarReplAggregates.cpp - Scalar Replacement of Aggregates --------===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This transformation implements the well known scalar replacement of
// aggregates transformation. This xform breaks up alloca instructions of
// aggregate type (structure or array) into individual alloca instructions for
// each member (if possible). Then, if possible, it transforms the individual
// alloca instructions into nice clean scalar SSA form.
//
// This combines a simple SRoA algorithm with the Mem2Reg algorithm because
// often interact, especially for C++ programs. As such, iterating between
// SRoA, then Mem2Reg until we run out of things to promote works well.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "scalarrepl"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/GlobalVariable.h"
#include "llvm/Instructions.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/Pass.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Transforms/Utils/PromoteMemToReg.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/GetElementPtrTypeIterator.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Compiler.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
using namespace llvm;
STATISTIC(NumReplaced, "Number of allocas broken up");
STATISTIC(NumPromoted, "Number of allocas promoted");
STATISTIC(NumConverted, "Number of aggregates converted to scalar");
STATISTIC(NumGlobals, "Number of allocas copied from constant global");
namespace {
struct VISIBILITY_HIDDEN SROA : public FunctionPass {
static const int ID; // Pass identifcation, replacement for typeid
SROA() : FunctionPass((intptr_t)&ID) {}
bool runOnFunction(Function &F);
bool performScalarRepl(Function &F);
bool performPromotion(Function &F);
// getAnalysisUsage - This pass does not require any passes, but we know it
// will not alter the CFG, so say so.
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<ETForest>();
AU.addRequired<DominanceFrontier>();
AU.addRequired<TargetData>();
AU.setPreservesCFG();
}
private:
int isSafeElementUse(Value *Ptr, bool isFirstElt, AllocationInst *AI);
int isSafeUseOfAllocation(Instruction *User, AllocationInst *AI);
bool isSafeMemIntrinsicOnAllocation(MemIntrinsic *MI, AllocationInst *AI);
bool isSafeUseOfBitCastedAllocation(BitCastInst *User, AllocationInst *AI);
int isSafeAllocaToScalarRepl(AllocationInst *AI);
void DoScalarReplacement(AllocationInst *AI,
std::vector<AllocationInst*> &WorkList);
void CanonicalizeAllocaUsers(AllocationInst *AI);
AllocaInst *AddNewAlloca(Function &F, const Type *Ty, AllocationInst *Base);
void RewriteBitCastUserOfAlloca(Instruction *BCInst, AllocationInst *AI,
SmallVector<AllocaInst*, 32> &NewElts);
const Type *CanConvertToScalar(