blob: 8fe0152ab78e695f8fc08b796862e921702c039f [file] [log] [blame]
Chris Lattnerfc1a4332002-04-29 01:22:55 +00001//===- llvm/Transforms/DecomposeMultiDimRefs.cpp - Lower array refs to 1D -===//
John Criswell482202a2003-10-20 19:43:21 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by the LLVM research group and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
Vikram S. Adve5d218df2002-03-23 20:43:39 +00009//
Chris Lattner8d843f62002-04-29 01:58:47 +000010// DecomposeMultiDimRefs - Convert multi-dimensional references consisting of
11// any combination of 2 or more array and structure indices into a sequence of
12// instructions (using getelementpr and cast) so that each instruction has at
13// most one index (except structure references, which need an extra leading
14// index of [0]).
Vikram S. Adve5d218df2002-03-23 20:43:39 +000015//
Chris Lattnerc8e66542002-04-27 06:56:12 +000016//===----------------------------------------------------------------------===//
Vikram S. Adve5d218df2002-03-23 20:43:39 +000017
Chris Lattnerb4cfa7f2002-05-07 20:03:00 +000018#include "llvm/Transforms/Scalar.h"
Chris Lattner15e8f4c2002-04-29 18:48:30 +000019#include "llvm/DerivedTypes.h"
Vikram S. Adve4737dd72002-08-03 13:21:15 +000020#include "llvm/Constants.h"
Chris Lattner37104aa2002-04-29 14:57:45 +000021#include "llvm/Constant.h"
Vikram S. Adve5d218df2002-03-23 20:43:39 +000022#include "llvm/iMemory.h"
23#include "llvm/iOther.h"
24#include "llvm/BasicBlock.h"
Vikram S. Adve5d218df2002-03-23 20:43:39 +000025#include "llvm/Pass.h"
Chris Lattnerbf3a0992002-10-01 22:38:41 +000026#include "Support/Statistic.h"
Chris Lattner49525f82004-01-09 06:02:20 +000027using namespace llvm;
Brian Gaeke960707c2003-11-11 22:41:34 +000028
Chris Lattnerfc1a4332002-04-29 01:22:55 +000029namespace {
Chris Lattnerbf3a0992002-10-01 22:38:41 +000030 Statistic<> NumAdded("lowerrefs", "# of getelementptr instructions added");
Chris Lattnerfc1a4332002-04-29 01:22:55 +000031
Vikram S. Advedba59922002-09-16 16:40:07 +000032 struct DecomposePass : public BasicBlockPass {
Chris Lattner28a8d242002-09-10 17:04:02 +000033 virtual bool runOnBasicBlock(BasicBlock &BB);
Chris Lattnerfc1a4332002-04-29 01:22:55 +000034 };
Chris Lattner49525f82004-01-09 06:02:20 +000035 RegisterOpt<DecomposePass> X("lowerrefs", "Decompose multi-dimensional "
36 "structure/array references");
Chris Lattnerfc1a4332002-04-29 01:22:55 +000037}
38
Chris Lattnerfc1a4332002-04-29 01:22:55 +000039// runOnBasicBlock - Entry point for array or structure references with multiple
40// indices.
41//
Chris Lattner49525f82004-01-09 06:02:20 +000042bool DecomposePass::runOnBasicBlock(BasicBlock &BB) {
Vikram S. Advedba59922002-09-16 16:40:07 +000043 bool changed = false;
44 for (BasicBlock::iterator II = BB.begin(); II != BB.end(); )
Chris Lattner889f6202003-04-23 16:37:45 +000045 if (GetElementPtrInst *gep = dyn_cast<GetElementPtrInst>(II++)) // pre-inc
Vikram S. Advedba59922002-09-16 16:40:07 +000046 if (gep->getNumIndices() >= 2)
47 changed |= DecomposeArrayRef(gep); // always modifies II
48 return changed;
Chris Lattnerfc1a4332002-04-29 01:22:55 +000049}
Vikram S. Adve5d218df2002-03-23 20:43:39 +000050
Chris Lattner49525f82004-01-09 06:02:20 +000051FunctionPass *llvm::createDecomposeMultiDimRefsPass() {
Brian Gaeke960707c2003-11-11 22:41:34 +000052 return new DecomposePass();
53}
Vikram S. Advedba59922002-09-16 16:40:07 +000054
55// Function: DecomposeArrayRef()
56//
Chris Lattnerdfb3a2c2002-08-22 23:37:20 +000057// For any GetElementPtrInst with 2 or more array and structure indices:
Vikram S. Adve4737dd72002-08-03 13:21:15 +000058//
59// opCode CompositeType* P, [uint|ubyte] idx1, ..., [uint|ubyte] idxN
60//
61// this function generates the foll sequence:
62//
63// ptr1 = getElementPtr P, idx1
64// ptr2 = getElementPtr ptr1, 0, idx2
65// ...
66// ptrN-1 = getElementPtr ptrN-2, 0, idxN-1
67// opCode ptrN-1, 0, idxN // New-MAI
68//
69// Then it replaces the original instruction with this sequence,
70// and replaces all uses of the original instruction with New-MAI.
71// If idx1 is 0, we simply omit the first getElementPtr instruction.
72//
73// On return: BBI points to the instruction after the current one
74// (whether or not *BBI was replaced).
75//
76// Return value: true if the instruction was replaced; false otherwise.
77//
Chris Lattner49525f82004-01-09 06:02:20 +000078bool llvm::DecomposeArrayRef(GetElementPtrInst* GEP) {
Vikram S. Advedba59922002-09-16 16:40:07 +000079 if (GEP->getNumIndices() < 2)
80 return false;
81
82 BasicBlock *BB = GEP->getParent();
83 Value *LastPtr = GEP->getPointerOperand();
84 Instruction *InsertPoint = GEP->getNext(); // Insert before the next insn
85
86 // The vector of new instructions to be created
87 std::vector<Instruction*> NewInsts;
Anand Shukla2bc64192002-06-25 21:07:58 +000088
Vikram S. Adve4737dd72002-08-03 13:21:15 +000089 // Process each index except the last one.
Vikram S. Advedba59922002-09-16 16:40:07 +000090 User::const_op_iterator OI = GEP->idx_begin(), OE = GEP->idx_end();
Chris Lattner8d843f62002-04-29 01:58:47 +000091 for (; OI+1 != OE; ++OI) {
Anand Shukla2bc64192002-06-25 21:07:58 +000092 std::vector<Value*> Indices;
Vikram S. Adve4737dd72002-08-03 13:21:15 +000093
94 // If this is the first index and is 0, skip it and move on!
Vikram S. Advedba59922002-09-16 16:40:07 +000095 if (OI == GEP->idx_begin()) {
Chris Lattner28a8d242002-09-10 17:04:02 +000096 if (*OI == ConstantInt::getNullValue((*OI)->getType()))
97 continue;
Chris Lattner28a8d242002-09-10 17:04:02 +000098 }
Vikram S. Advedba59922002-09-16 16:40:07 +000099 else // Not the first index: include initial [0] to deref the last ptr
100 Indices.push_back(Constant::getNullValue(Type::LongTy));
Vikram S. Adve4737dd72002-08-03 13:21:15 +0000101
Chris Lattner8d843f62002-04-29 01:58:47 +0000102 Indices.push_back(*OI);
103
Vikram S. Adve4737dd72002-08-03 13:21:15 +0000104 // New Instruction: nextPtr1 = GetElementPtr LastPtr, Indices
Chris Lattner28a8d242002-09-10 17:04:02 +0000105 LastPtr = new GetElementPtrInst(LastPtr, Indices, "ptr1", InsertPoint);
Vikram S. Adve4737dd72002-08-03 13:21:15 +0000106 ++NumAdded;
Chris Lattnerfc1a4332002-04-29 01:22:55 +0000107 }
Vikram S. Adve4737dd72002-08-03 13:21:15 +0000108
Vikram S. Adve5d218df2002-03-23 20:43:39 +0000109 // Now create a new instruction to replace the original one
Vikram S. Adve1ee06582002-03-24 03:21:18 +0000110 //
Chris Lattner113f4f42002-06-25 16:13:24 +0000111 const PointerType *PtrTy = cast<PointerType>(LastPtr->getType());
Vikram S. Adve1ee06582002-03-24 03:21:18 +0000112
Vikram S. Adve4737dd72002-08-03 13:21:15 +0000113 // Get the final index vector, including an initial [0] as before.
Anand Shukla2bc64192002-06-25 21:07:58 +0000114 std::vector<Value*> Indices;
Chris Lattner136dab72002-09-11 01:21:33 +0000115 Indices.push_back(Constant::getNullValue(Type::LongTy));
Chris Lattner8d843f62002-04-29 01:58:47 +0000116 Indices.push_back(*OI);
117
Vikram S. Advedba59922002-09-16 16:40:07 +0000118 Value *NewVal = new GetElementPtrInst(LastPtr, Indices, GEP->getName(),
Chris Lattner28a8d242002-09-10 17:04:02 +0000119 InsertPoint);
Anand Shukla2bc64192002-06-25 21:07:58 +0000120
Vikram S. Adve5d218df2002-03-23 20:43:39 +0000121 // Replace all uses of the old instruction with the new
Vikram S. Advedba59922002-09-16 16:40:07 +0000122 GEP->replaceAllUsesWith(NewVal);
Chris Lattnerfc1a4332002-04-29 01:22:55 +0000123
Chris Lattner28a8d242002-09-10 17:04:02 +0000124 // Now remove and delete the old instruction...
Vikram S. Advedba59922002-09-16 16:40:07 +0000125 BB->getInstList().erase(GEP);
126
Vikram S. Adve4737dd72002-08-03 13:21:15 +0000127 return true;
Chris Lattnerc8e66542002-04-27 06:56:12 +0000128}
Brian Gaeke960707c2003-11-11 22:41:34 +0000129