blob: 012fa22770224c17b8e543eef96b4c5d43969bef [file] [log] [blame]
Chris Lattnercf3056d2003-10-13 03:32:08 +00001//===- SimpleStructMutation.cpp - Swap structure elements around ----------===//
John Criswellb576c942003-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//===----------------------------------------------------------------------===//
Chris Lattner7546c212001-11-10 07:28:25 +00009//
10// This pass does a simple transformation that swaps all of the elements of the
11// struct types in the program around.
12//
13//===----------------------------------------------------------------------===//
14
Chris Lattner568ddab2002-07-24 17:12:05 +000015#include "llvm/Transforms/IPO.h"
Chris Lattnere6aa3732002-11-19 20:49:40 +000016#include "llvm/Transforms/MutateStructTypes.h"
Chris Lattner7546c212001-11-10 07:28:25 +000017#include "llvm/Analysis/FindUsedTypes.h"
18#include "llvm/Analysis/FindUnsafePointerTypes.h"
Chris Lattner497c60c2002-05-07 18:12:18 +000019#include "llvm/Target/TargetData.h"
20#include "llvm/DerivedTypes.h"
Chris Lattner12739d92001-11-26 16:59:10 +000021#include <algorithm>
Chris Lattner697954c2002-01-20 22:54:45 +000022using std::vector;
23using std::set;
24using std::pair;
Chris Lattner7546c212001-11-10 07:28:25 +000025
Chris Lattnerbd0ef772002-02-26 21:46:54 +000026namespace {
Chris Lattner96c466b2002-04-29 14:57:45 +000027 struct SimpleStructMutation : public MutateStructTypes {
Chris Lattnere9754ef2002-07-23 18:03:11 +000028 enum Transform { SwapElements, SortElements };
Chris Lattnerbd0ef772002-02-26 21:46:54 +000029
Chris Lattnere9754ef2002-07-23 18:03:11 +000030 virtual bool run(Module &M) = 0;
31
Chris Lattnerf57b8452002-04-27 06:56:12 +000032 // getAnalysisUsage - This function needs the results of the
Chris Lattnerbd0ef772002-02-26 21:46:54 +000033 // FindUsedTypes and FindUnsafePointerTypes analysis passes...
34 //
Chris Lattnerf57b8452002-04-27 06:56:12 +000035 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
Chris Lattner3a15d702002-09-26 00:17:21 +000036 AU.addRequired<TargetData>();
Chris Lattner5f0eb8d2002-08-08 19:01:30 +000037 AU.addRequired<FindUsedTypes>();
38 AU.addRequired<FindUnsafePointerTypes>();
Chris Lattnerf57b8452002-04-27 06:56:12 +000039 MutateStructTypes::getAnalysisUsage(AU);
Chris Lattnerbd0ef772002-02-26 21:46:54 +000040 }
41
Chris Lattnere9754ef2002-07-23 18:03:11 +000042 protected:
Chris Lattner0b12b5f2002-06-25 16:13:21 +000043 TransformsType getTransforms(Module &M, enum Transform);
Chris Lattnerbd0ef772002-02-26 21:46:54 +000044 };
Chris Lattnere9754ef2002-07-23 18:03:11 +000045
46 struct SwapStructElements : public SimpleStructMutation {
Chris Lattnere9754ef2002-07-23 18:03:11 +000047 virtual bool run(Module &M) {
48 setTransforms(getTransforms(M, SwapElements));
49 bool Changed = MutateStructTypes::run(M);
50 clearTransforms();
51 return Changed;
52 }
53 };
54
55 struct SortStructElements : public SimpleStructMutation {
Chris Lattnere9754ef2002-07-23 18:03:11 +000056 virtual bool run(Module &M) {
57 setTransforms(getTransforms(M, SortElements));
58 bool Changed = MutateStructTypes::run(M);
59 clearTransforms();
60 return Changed;
61 }
62 };
Chris Lattner3a15d702002-09-26 00:17:21 +000063
64 RegisterOpt<SwapStructElements> X("swapstructs",
65 "Swap structure types around");
66 RegisterOpt<SortStructElements> Y("sortstructs",
67 "Sort structure elements by size");
Chris Lattnerbd0ef772002-02-26 21:46:54 +000068} // end anonymous namespace
69
Chris Lattner3a15d702002-09-26 00:17:21 +000070Pass *createSwapElementsPass() { return new SwapStructElements(); }
71Pass *createSortElementsPass() { return new SortStructElements(); }
Chris Lattnerbd0ef772002-02-26 21:46:54 +000072
Chris Lattner697954c2002-01-20 22:54:45 +000073
Chris Lattner7546c212001-11-10 07:28:25 +000074// PruneTypes - Given a type Ty, make sure that neither it, or one of its
75// subtypes, occur in TypesToModify.
76//
77static void PruneTypes(const Type *Ty, set<const StructType*> &TypesToModify,
78 set<const Type*> &ProcessedTypes) {
79 if (ProcessedTypes.count(Ty)) return; // Already been checked
80 ProcessedTypes.insert(Ty);
81
82 // If the element is in TypesToModify, remove it now...
Chris Lattnerd5b48ca2001-11-14 11:02:49 +000083 if (const StructType *ST = dyn_cast<StructType>(Ty)) {
Chris Lattner7546c212001-11-10 07:28:25 +000084 TypesToModify.erase(ST); // This doesn't fail if the element isn't present
Chris Lattner697954c2002-01-20 22:54:45 +000085 std::cerr << "Unable to swap type: " << ST << "\n";
Chris Lattnerd5b48ca2001-11-14 11:02:49 +000086 }
Chris Lattner7546c212001-11-10 07:28:25 +000087
Chris Lattnerd5b48ca2001-11-14 11:02:49 +000088 // Remove all types that this type contains as well... do not remove types
89 // that are referenced only through pointers, because we depend on the size of
90 // the pointer, not on what the structure points to.
Chris Lattner7546c212001-11-10 07:28:25 +000091 //
92 for (Type::subtype_iterator I = Ty->subtype_begin(), E = Ty->subtype_end();
Chris Lattnerd5b48ca2001-11-14 11:02:49 +000093 I != E; ++I) {
94 if (!isa<PointerType>(*I))
95 PruneTypes(*I, TypesToModify, ProcessedTypes);
96 }
Chris Lattner7546c212001-11-10 07:28:25 +000097}
98
Chris Lattner12739d92001-11-26 16:59:10 +000099static bool FirstLess(const pair<unsigned, unsigned> &LHS,
100 const pair<unsigned, unsigned> &RHS) {
101 return LHS.second < RHS.second;
102}
Chris Lattner7546c212001-11-10 07:28:25 +0000103
Chris Lattner12739d92001-11-26 16:59:10 +0000104static unsigned getIndex(const vector<pair<unsigned, unsigned> > &Vec,
105 unsigned Field) {
106 for (unsigned i = 0; ; ++i)
107 if (Vec[i].first == Field) return i;
108}
109
Chris Lattnere9754ef2002-07-23 18:03:11 +0000110static inline void GetTransformation(const TargetData &TD, const StructType *ST,
Chris Lattner12739d92001-11-26 16:59:10 +0000111 vector<int> &Transform,
Chris Lattner497c60c2002-05-07 18:12:18 +0000112 enum SimpleStructMutation::Transform XForm) {
Chris Lattner12739d92001-11-26 16:59:10 +0000113 unsigned NumElements = ST->getElementTypes().size();
114 Transform.reserve(NumElements);
115
116 switch (XForm) {
Chris Lattnerf4de63f2002-01-21 07:31:50 +0000117 case SimpleStructMutation::SwapElements:
Chris Lattner12739d92001-11-26 16:59:10 +0000118 // The transformation to do is: just simply swap the elements
119 for (unsigned i = 0; i < NumElements; ++i)
120 Transform.push_back(NumElements-i-1);
121 break;
122
Chris Lattnerf4de63f2002-01-21 07:31:50 +0000123 case SimpleStructMutation::SortElements: {
Chris Lattner12739d92001-11-26 16:59:10 +0000124 vector<pair<unsigned, unsigned> > ElList;
125
126 // Build mapping from index to size
127 for (unsigned i = 0; i < NumElements; ++i)
Chris Lattner697954c2002-01-20 22:54:45 +0000128 ElList.push_back(
129 std::make_pair(i, TD.getTypeSize(ST->getElementTypes()[i])));
Chris Lattner12739d92001-11-26 16:59:10 +0000130
131 sort(ElList.begin(), ElList.end(), ptr_fun(FirstLess));
132
133 for (unsigned i = 0; i < NumElements; ++i)
134 Transform.push_back(getIndex(ElList, i));
135
136 break;
137 }
138 }
139}
Chris Lattner7546c212001-11-10 07:28:25 +0000140
Chris Lattnerbd0ef772002-02-26 21:46:54 +0000141
Chris Lattnerf4de63f2002-01-21 07:31:50 +0000142SimpleStructMutation::TransformsType
Chris Lattner0b12b5f2002-06-25 16:13:21 +0000143 SimpleStructMutation::getTransforms(Module &, enum Transform XForm) {
Chris Lattner7546c212001-11-10 07:28:25 +0000144 // We need to know which types to modify, and which types we CAN'T modify
Chris Lattner793c6b82002-01-31 00:45:11 +0000145 // TODO: Do symbol tables as well
Chris Lattner7546c212001-11-10 07:28:25 +0000146
147 // Get the results out of the analyzers...
Chris Lattner793c6b82002-01-31 00:45:11 +0000148 FindUsedTypes &FUT = getAnalysis<FindUsedTypes>();
149 const set<const Type *> &UsedTypes = FUT.getTypes();
150
151 FindUnsafePointerTypes &FUPT = getAnalysis<FindUnsafePointerTypes>();
152 const set<PointerType*> &UnsafePTys = FUPT.getUnsafeTypes();
153
Chris Lattner7546c212001-11-10 07:28:25 +0000154
155
Chris Lattnerd5b48ca2001-11-14 11:02:49 +0000156 // Combine the two sets, weeding out non structure types. Closures in C++
157 // sure would be nice.
Chris Lattner7546c212001-11-10 07:28:25 +0000158 set<const StructType*> TypesToModify;
159 for (set<const Type *>::const_iterator I = UsedTypes.begin(),
160 E = UsedTypes.end(); I != E; ++I)
161 if (const StructType *ST = dyn_cast<StructType>(*I))
162 TypesToModify.insert(ST);
163
164
165 // Go through the Unsafe types and remove all types from TypesToModify that we
166 // are not allowed to modify, because that would be unsafe.
167 //
168 set<const Type*> ProcessedTypes;
169 for (set<PointerType*>::const_iterator I = UnsafePTys.begin(),
Chris Lattnerd5b48ca2001-11-14 11:02:49 +0000170 E = UnsafePTys.end(); I != E; ++I) {
Chris Lattner697954c2002-01-20 22:54:45 +0000171 //cerr << "Pruning type: " << *I << "\n";
Chris Lattner7546c212001-11-10 07:28:25 +0000172 PruneTypes(*I, TypesToModify, ProcessedTypes);
Chris Lattnerd5b48ca2001-11-14 11:02:49 +0000173 }
Chris Lattner7546c212001-11-10 07:28:25 +0000174
175
176 // Build up a set of structure types that we are going to modify, and
177 // information describing how to modify them.
Chris Lattner697954c2002-01-20 22:54:45 +0000178 std::map<const StructType*, vector<int> > Transforms;
Chris Lattner3a15d702002-09-26 00:17:21 +0000179 TargetData &TD = getAnalysis<TargetData>();
Chris Lattner7546c212001-11-10 07:28:25 +0000180
181 for (set<const StructType*>::iterator I = TypesToModify.begin(),
182 E = TypesToModify.end(); I != E; ++I) {
183 const StructType *ST = *I;
Chris Lattner7546c212001-11-10 07:28:25 +0000184
185 vector<int> &Transform = Transforms[ST]; // Fill in the map directly
Chris Lattnere9754ef2002-07-23 18:03:11 +0000186 GetTransformation(TD, ST, Transform, XForm);
Chris Lattner7546c212001-11-10 07:28:25 +0000187 }
188
Chris Lattner12739d92001-11-26 16:59:10 +0000189 return Transforms;
Chris Lattner7546c212001-11-10 07:28:25 +0000190}