blob: 809ca403dd36ba4c4e2e0aa54c9c2c3e8078a893 [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 Lattner11922832003-11-21 21:52:10 +000022using namespace llvm;
Brian Gaeked0fde302003-11-11 22:41:34 +000023
Chris Lattnerbd0ef772002-02-26 21:46:54 +000024namespace {
Chris Lattner96c466b2002-04-29 14:57:45 +000025 struct SimpleStructMutation : public MutateStructTypes {
Chris Lattnere9754ef2002-07-23 18:03:11 +000026 enum Transform { SwapElements, SortElements };
Chris Lattnerbd0ef772002-02-26 21:46:54 +000027
Chris Lattnere9754ef2002-07-23 18:03:11 +000028 virtual bool run(Module &M) = 0;
29
Chris Lattnerf57b8452002-04-27 06:56:12 +000030 // getAnalysisUsage - This function needs the results of the
Chris Lattnerbd0ef772002-02-26 21:46:54 +000031 // FindUsedTypes and FindUnsafePointerTypes analysis passes...
32 //
Chris Lattnerf57b8452002-04-27 06:56:12 +000033 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
Chris Lattner3a15d702002-09-26 00:17:21 +000034 AU.addRequired<TargetData>();
Chris Lattner5f0eb8d2002-08-08 19:01:30 +000035 AU.addRequired<FindUsedTypes>();
36 AU.addRequired<FindUnsafePointerTypes>();
Chris Lattnerf57b8452002-04-27 06:56:12 +000037 MutateStructTypes::getAnalysisUsage(AU);
Chris Lattnerbd0ef772002-02-26 21:46:54 +000038 }
39
Chris Lattnere9754ef2002-07-23 18:03:11 +000040 protected:
Chris Lattner0b12b5f2002-06-25 16:13:21 +000041 TransformsType getTransforms(Module &M, enum Transform);
Chris Lattnerbd0ef772002-02-26 21:46:54 +000042 };
Chris Lattnere9754ef2002-07-23 18:03:11 +000043
44 struct SwapStructElements : public SimpleStructMutation {
Chris Lattnere9754ef2002-07-23 18:03:11 +000045 virtual bool run(Module &M) {
46 setTransforms(getTransforms(M, SwapElements));
47 bool Changed = MutateStructTypes::run(M);
48 clearTransforms();
49 return Changed;
50 }
51 };
52
53 struct SortStructElements : public SimpleStructMutation {
Chris Lattnere9754ef2002-07-23 18:03:11 +000054 virtual bool run(Module &M) {
55 setTransforms(getTransforms(M, SortElements));
56 bool Changed = MutateStructTypes::run(M);
57 clearTransforms();
58 return Changed;
59 }
60 };
Chris Lattner3a15d702002-09-26 00:17:21 +000061
62 RegisterOpt<SwapStructElements> X("swapstructs",
63 "Swap structure types around");
64 RegisterOpt<SortStructElements> Y("sortstructs",
65 "Sort structure elements by size");
Chris Lattnerbd0ef772002-02-26 21:46:54 +000066} // end anonymous namespace
67
Chris Lattner3a15d702002-09-26 00:17:21 +000068Pass *createSwapElementsPass() { return new SwapStructElements(); }
69Pass *createSortElementsPass() { return new SortStructElements(); }
Chris Lattnerbd0ef772002-02-26 21:46:54 +000070
Chris Lattner697954c2002-01-20 22:54:45 +000071
Chris Lattner7546c212001-11-10 07:28:25 +000072// PruneTypes - Given a type Ty, make sure that neither it, or one of its
73// subtypes, occur in TypesToModify.
74//
Chris Lattner11922832003-11-21 21:52:10 +000075static void PruneTypes(const Type *Ty,
76 std::set<const StructType*> &TypesToModify,
77 std::set<const Type*> &ProcessedTypes) {
Chris Lattner7546c212001-11-10 07:28:25 +000078 if (ProcessedTypes.count(Ty)) return; // Already been checked
79 ProcessedTypes.insert(Ty);
80
81 // If the element is in TypesToModify, remove it now...
Chris Lattnerd5b48ca2001-11-14 11:02:49 +000082 if (const StructType *ST = dyn_cast<StructType>(Ty)) {
Chris Lattner7546c212001-11-10 07:28:25 +000083 TypesToModify.erase(ST); // This doesn't fail if the element isn't present
Chris Lattner697954c2002-01-20 22:54:45 +000084 std::cerr << "Unable to swap type: " << ST << "\n";
Chris Lattnerd5b48ca2001-11-14 11:02:49 +000085 }
Chris Lattner7546c212001-11-10 07:28:25 +000086
Chris Lattnerd5b48ca2001-11-14 11:02:49 +000087 // Remove all types that this type contains as well... do not remove types
88 // that are referenced only through pointers, because we depend on the size of
89 // the pointer, not on what the structure points to.
Chris Lattner7546c212001-11-10 07:28:25 +000090 //
91 for (Type::subtype_iterator I = Ty->subtype_begin(), E = Ty->subtype_end();
Chris Lattnerd5b48ca2001-11-14 11:02:49 +000092 I != E; ++I) {
93 if (!isa<PointerType>(*I))
94 PruneTypes(*I, TypesToModify, ProcessedTypes);
95 }
Chris Lattner7546c212001-11-10 07:28:25 +000096}
97
Chris Lattner11922832003-11-21 21:52:10 +000098static bool FirstLess(const std::pair<unsigned, unsigned> &LHS,
99 const std::pair<unsigned, unsigned> &RHS) {
Chris Lattner12739d92001-11-26 16:59:10 +0000100 return LHS.second < RHS.second;
101}
Chris Lattner7546c212001-11-10 07:28:25 +0000102
Chris Lattner11922832003-11-21 21:52:10 +0000103static unsigned getIndex(const std::vector<std::pair<unsigned, unsigned> > &Vec,
Chris Lattner12739d92001-11-26 16:59:10 +0000104 unsigned Field) {
105 for (unsigned i = 0; ; ++i)
106 if (Vec[i].first == Field) return i;
107}
108
Chris Lattnere9754ef2002-07-23 18:03:11 +0000109static inline void GetTransformation(const TargetData &TD, const StructType *ST,
Chris Lattner11922832003-11-21 21:52:10 +0000110 std::vector<int> &Transform,
Chris Lattner497c60c2002-05-07 18:12:18 +0000111 enum SimpleStructMutation::Transform XForm) {
Chris Lattner12739d92001-11-26 16:59:10 +0000112 unsigned NumElements = ST->getElementTypes().size();
113 Transform.reserve(NumElements);
114
115 switch (XForm) {
Chris Lattnerf4de63f2002-01-21 07:31:50 +0000116 case SimpleStructMutation::SwapElements:
Chris Lattner12739d92001-11-26 16:59:10 +0000117 // The transformation to do is: just simply swap the elements
118 for (unsigned i = 0; i < NumElements; ++i)
119 Transform.push_back(NumElements-i-1);
120 break;
121
Chris Lattnerf4de63f2002-01-21 07:31:50 +0000122 case SimpleStructMutation::SortElements: {
Chris Lattner11922832003-11-21 21:52:10 +0000123 std::vector<std::pair<unsigned, unsigned> > ElList;
Chris Lattner12739d92001-11-26 16:59:10 +0000124
125 // Build mapping from index to size
126 for (unsigned i = 0; i < NumElements; ++i)
Chris Lattner697954c2002-01-20 22:54:45 +0000127 ElList.push_back(
128 std::make_pair(i, TD.getTypeSize(ST->getElementTypes()[i])));
Chris Lattner12739d92001-11-26 16:59:10 +0000129
130 sort(ElList.begin(), ElList.end(), ptr_fun(FirstLess));
131
132 for (unsigned i = 0; i < NumElements; ++i)
133 Transform.push_back(getIndex(ElList, i));
134
135 break;
136 }
137 }
138}
Chris Lattner7546c212001-11-10 07:28:25 +0000139
Chris Lattnerbd0ef772002-02-26 21:46:54 +0000140
Chris Lattnerf4de63f2002-01-21 07:31:50 +0000141SimpleStructMutation::TransformsType
Chris Lattner0b12b5f2002-06-25 16:13:21 +0000142 SimpleStructMutation::getTransforms(Module &, enum Transform XForm) {
Chris Lattner7546c212001-11-10 07:28:25 +0000143 // We need to know which types to modify, and which types we CAN'T modify
Chris Lattner793c6b82002-01-31 00:45:11 +0000144 // TODO: Do symbol tables as well
Chris Lattner7546c212001-11-10 07:28:25 +0000145
146 // Get the results out of the analyzers...
Chris Lattner793c6b82002-01-31 00:45:11 +0000147 FindUsedTypes &FUT = getAnalysis<FindUsedTypes>();
Chris Lattner11922832003-11-21 21:52:10 +0000148 const std::set<const Type *> &UsedTypes = FUT.getTypes();
Chris Lattner793c6b82002-01-31 00:45:11 +0000149
150 FindUnsafePointerTypes &FUPT = getAnalysis<FindUnsafePointerTypes>();
Chris Lattner11922832003-11-21 21:52:10 +0000151 const std::set<PointerType*> &UnsafePTys = FUPT.getUnsafeTypes();
Chris Lattner7546c212001-11-10 07:28:25 +0000152
153
Chris Lattnerd5b48ca2001-11-14 11:02:49 +0000154 // Combine the two sets, weeding out non structure types. Closures in C++
155 // sure would be nice.
Chris Lattner11922832003-11-21 21:52:10 +0000156 std::set<const StructType*> TypesToModify;
157 for (std::set<const Type *>::const_iterator I = UsedTypes.begin(),
Chris Lattner7546c212001-11-10 07:28:25 +0000158 E = UsedTypes.end(); I != E; ++I)
159 if (const StructType *ST = dyn_cast<StructType>(*I))
160 TypesToModify.insert(ST);
161
162
163 // Go through the Unsafe types and remove all types from TypesToModify that we
164 // are not allowed to modify, because that would be unsafe.
165 //
Chris Lattner11922832003-11-21 21:52:10 +0000166 std::set<const Type*> ProcessedTypes;
167 for (std::set<PointerType*>::const_iterator I = UnsafePTys.begin(),
Chris Lattnerd5b48ca2001-11-14 11:02:49 +0000168 E = UnsafePTys.end(); I != E; ++I) {
Chris Lattner697954c2002-01-20 22:54:45 +0000169 //cerr << "Pruning type: " << *I << "\n";
Chris Lattner7546c212001-11-10 07:28:25 +0000170 PruneTypes(*I, TypesToModify, ProcessedTypes);
Chris Lattnerd5b48ca2001-11-14 11:02:49 +0000171 }
Chris Lattner7546c212001-11-10 07:28:25 +0000172
173
174 // Build up a set of structure types that we are going to modify, and
175 // information describing how to modify them.
Chris Lattner11922832003-11-21 21:52:10 +0000176 std::map<const StructType*, std::vector<int> > Transforms;
Chris Lattner3a15d702002-09-26 00:17:21 +0000177 TargetData &TD = getAnalysis<TargetData>();
Chris Lattner7546c212001-11-10 07:28:25 +0000178
Chris Lattner11922832003-11-21 21:52:10 +0000179 for (std::set<const StructType*>::iterator I = TypesToModify.begin(),
Chris Lattner7546c212001-11-10 07:28:25 +0000180 E = TypesToModify.end(); I != E; ++I) {
181 const StructType *ST = *I;
Chris Lattner7546c212001-11-10 07:28:25 +0000182
Chris Lattner11922832003-11-21 21:52:10 +0000183 std::vector<int> &Transform = Transforms[ST]; // Fill in the map directly
Chris Lattnere9754ef2002-07-23 18:03:11 +0000184 GetTransformation(TD, ST, Transform, XForm);
Chris Lattner7546c212001-11-10 07:28:25 +0000185 }
186
Chris Lattner12739d92001-11-26 16:59:10 +0000187 return Transforms;
Chris Lattner7546c212001-11-10 07:28:25 +0000188}
Brian Gaeked0fde302003-11-11 22:41:34 +0000189