Initial revision
[oota-llvm.git] / lib / VMCore / ConstantFold.cpp
1 //===- ConstantHandling.cpp - Implement ConstantHandling.h ----------------===//
2 //
3 // This file implements the various intrinsic operations, on constant values.
4 //
5 //===----------------------------------------------------------------------===//
6
7 #include "llvm/Opt/ConstantHandling.h"
8
9 //===----------------------------------------------------------------------===//
10 //                             TemplateRules Class
11 //===----------------------------------------------------------------------===//
12 //
13 // TemplateRules - Implement a subclass of ConstRules that provides all 
14 // operations as noops.  All other rules classes inherit from this class so 
15 // that if functionality is needed in the future, it can simply be added here 
16 // and to ConstRules without changing anything else...
17 // 
18 // This class also provides subclasses with typesafe implementations of methods
19 // so that don't have to do type casting.
20 //
21 template<class ArgType, class SubClassName>
22 class TemplateRules : public ConstRules {
23
24   //===--------------------------------------------------------------------===//
25   // Redirecting functions that cast to the appropriate types
26   //===--------------------------------------------------------------------===//
27
28   virtual ConstPoolVal *neg(const ConstPoolVal *V) const {
29     return SubClassName::Neg((const ArgType *)V);
30   }
31
32   virtual ConstPoolVal *not(const ConstPoolVal *V) const {
33     return SubClassName::Not((const ArgType *)V);
34   }
35
36   
37   virtual ConstPoolVal *add(const ConstPoolVal *V1, 
38                             const ConstPoolVal *V2) const { 
39     return SubClassName::Add((const ArgType *)V1, (const ArgType *)V2);  
40   }
41
42   virtual ConstPoolVal *sub(const ConstPoolVal *V1, 
43                             const ConstPoolVal *V2) const { 
44     return SubClassName::Sub((const ArgType *)V1, (const ArgType *)V2);  
45   }
46
47   virtual ConstPoolBool *lessthan(const ConstPoolVal *V1, 
48                                   const ConstPoolVal *V2) const { 
49     return SubClassName::LessThan((const ArgType *)V1, (const ArgType *)V2);
50   }
51
52   //===--------------------------------------------------------------------===//
53   // Default "noop" implementations
54   //===--------------------------------------------------------------------===//
55
56   inline static ConstPoolVal *Neg(const ArgType *V) { return 0; }
57   inline static ConstPoolVal *Not(const ArgType *V) { return 0; }
58
59   inline static ConstPoolVal *Add(const ArgType *V1, const ArgType *V2) {
60     return 0;
61   }
62
63   inline static ConstPoolVal *Sub(const ArgType *V1, const ArgType *V2) {
64     return 0;
65   }
66
67   inline static ConstPoolBool *LessThan(const ArgType *V1, const ArgType *V2) {
68     return 0;
69   }
70 };
71
72
73
74 //===----------------------------------------------------------------------===//
75 //                             EmptyRules Class
76 //===----------------------------------------------------------------------===//
77 //
78 // EmptyRules provides a concrete base class of ConstRules that does nothing
79 //
80 static    // EmptyInst is static
81 struct EmptyRules : public TemplateRules<ConstPoolVal, EmptyRules> {
82 } EmptyInst;
83
84
85
86 //===----------------------------------------------------------------------===//
87 //                              BoolRules Class
88 //===----------------------------------------------------------------------===//
89 //
90 // BoolRules provides a concrete base class of ConstRules for the 'bool' type.
91 //
92 static   // BoolTyInst is static...
93 struct BoolRules : public TemplateRules<ConstPoolBool, BoolRules> {
94
95   inline static ConstPoolVal *Not(const ConstPoolBool *V) { 
96     return new ConstPoolBool(!V->getValue());
97   }
98
99   inline static ConstPoolVal *Or(const ConstPoolBool *V1, 
100                                  const ConstPoolBool *V2) {
101     bool Result = V1->getValue() | V2->getValue();
102     return new ConstPoolBool(Result);
103   }
104
105   inline static ConstPoolVal *And(const ConstPoolBool *V1, 
106                                   const ConstPoolBool *V2) {
107     bool Result = V1->getValue() & V2->getValue();
108     return new ConstPoolBool(Result);
109   }
110 } BoolTyInst;
111
112
113 //===----------------------------------------------------------------------===//
114 //                             DirectRules Class
115 //===----------------------------------------------------------------------===//
116 //
117 // DirectRules provides a concrete base classes of ConstRules for a variety of
118 // different types.  This allows the C++ compiler to automatically generate our
119 // constant handling operations in a typesafe and accurate manner.
120 //
121 template<class ConstPoolClass, class BuiltinType, const Type **Ty>
122 struct DirectRules 
123   : public TemplateRules<ConstPoolClass, 
124                          DirectRules<ConstPoolClass, BuiltinType, Ty> > {
125
126   inline static ConstPoolVal *Neg(const ConstPoolClass *V) { 
127     return new ConstPoolClass(*Ty, -(BuiltinType)V->getValue());;
128   }
129   inline static ConstPoolVal *Not(const ConstPoolClass *V) { 
130     return new ConstPoolClass(*Ty, !(BuiltinType)V->getValue());;
131   }
132
133   inline static ConstPoolVal *Add(const ConstPoolClass *V1, 
134                                   const ConstPoolClass *V2) {
135     BuiltinType Result = (BuiltinType)V1->getValue() + 
136                          (BuiltinType)V2->getValue();
137     return new ConstPoolClass(*Ty, Result);
138   }
139
140   inline static ConstPoolVal *Sub(const ConstPoolClass *V1, 
141                                   const ConstPoolClass *V2) {
142     BuiltinType Result = (BuiltinType)V1->getValue() -
143                          (BuiltinType)V2->getValue();
144     return new ConstPoolClass(*Ty, Result);
145   }
146
147   inline static ConstPoolBool *LessThan(const ConstPoolClass *V1, 
148                                         const ConstPoolClass *V2) {
149     bool Result = (BuiltinType)V1->getValue() < (BuiltinType)V2->getValue();
150     return new ConstPoolBool(Result);
151   } 
152 };
153
154 //===----------------------------------------------------------------------===//
155 //                            DirectRules Subclasses
156 //===----------------------------------------------------------------------===//
157 //
158 // Given the DirectRules class we can now implement lots of types with little
159 // code.  Thank goodness C++ compilers are great at stomping out layers of 
160 // templates... can you imagine having to do this all by hand? (/me is lazy :)
161 //
162 static DirectRules<ConstPoolSInt,   signed char , &Type::SByteTy>  SByteTyInst;
163 static DirectRules<ConstPoolUInt, unsigned char , &Type::UByteTy>  UByteTyInst;
164 static DirectRules<ConstPoolSInt,   signed short, &Type::ShortTy>  ShortTyInst;
165 static DirectRules<ConstPoolUInt, unsigned short, &Type::UShortTy> UShortTyInst;
166 static DirectRules<ConstPoolSInt,   signed int  , &Type::IntTy>    IntTyInst;
167 static DirectRules<ConstPoolUInt, unsigned int  , &Type::UIntTy>   UIntTyInst;
168 static DirectRules<ConstPoolSInt,  int64_t      , &Type::LongTy>   LongTyInst;
169 static DirectRules<ConstPoolUInt, uint64_t      , &Type::ULongTy>  ULongTyInst;
170 static DirectRules<ConstPoolFP  , float         , &Type::FloatTy>  FloatTyInst;
171 static DirectRules<ConstPoolFP  , double        , &Type::DoubleTy> DoubleTyInst;
172
173
174 // ConstRules::find - Return the constant rules that take care of the specified
175 // type.  Note that this is cached in the Type value itself, so switch statement
176 // is only hit at most once per type.
177 //
178 const ConstRules *ConstRules::find(const Type *Ty) {
179   const ConstRules *Result;
180   switch (Ty->getPrimitiveID()) {
181   case Type::BoolTyID:   Result = &BoolTyInst;   break;
182   case Type::SByteTyID:  Result = &SByteTyInst;  break;
183   case Type::UByteTyID:  Result = &UByteTyInst;  break;
184   case Type::ShortTyID:  Result = &ShortTyInst;  break;
185   case Type::UShortTyID: Result = &UShortTyInst; break;
186   case Type::IntTyID:    Result = &IntTyInst;    break;
187   case Type::UIntTyID:   Result = &UIntTyInst;   break;
188   case Type::LongTyID:   Result = &LongTyInst;   break;
189   case Type::ULongTyID:  Result = &ULongTyInst;  break;
190   case Type::FloatTyID:  Result = &FloatTyInst;  break;
191   case Type::DoubleTyID: Result = &DoubleTyInst; break;
192   default:               Result = &EmptyInst;    break;
193   }
194
195   Ty->setConstRules(Result);   // Cache the value for future short circuiting!
196   return Result;
197 }