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