1193323Sed//====-- llvm/Support/TargetFolder.h - Constant folding helper -*- C++ -*-====//
2193323Sed//
3193323Sed//                     The LLVM Compiler Infrastructure
4193323Sed//
5193323Sed// This file is distributed under the University of Illinois Open Source
6193323Sed// License. See LICENSE.TXT for details.
7193323Sed//
8193323Sed//===----------------------------------------------------------------------===//
9193323Sed//
10193323Sed// This file defines the TargetFolder class, a helper for IRBuilder.
11193323Sed// It provides IRBuilder with a set of methods for creating constants with
12193378Sed// target dependent folding, in addition to the same target-independent
13193378Sed// folding that the ConstantFolder class provides.  For general constant
14193378Sed// creation and folding, use ConstantExpr and the routines in
15193378Sed// llvm/Analysis/ConstantFolding.h.
16193323Sed//
17193323Sed//===----------------------------------------------------------------------===//
18193323Sed
19193323Sed#ifndef LLVM_SUPPORT_TARGETFOLDER_H
20193323Sed#define LLVM_SUPPORT_TARGETFOLDER_H
21193323Sed
22224145Sdim#include "llvm/ADT/ArrayRef.h"
23193323Sed#include "llvm/Analysis/ConstantFolding.h"
24249423Sdim#include "llvm/IR/Constants.h"
25249423Sdim#include "llvm/IR/InstrTypes.h"
26193323Sed
27193323Sednamespace llvm {
28193323Sed
29243830Sdimclass DataLayout;
30193323Sed
31193323Sed/// TargetFolder - Create constants with target dependent folding.
32193323Sedclass TargetFolder {
33243830Sdim  const DataLayout *TD;
34193323Sed
35193323Sed  /// Fold - Fold the constant using target specific information.
36193323Sed  Constant *Fold(Constant *C) const {
37193323Sed    if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C))
38199481Srdivacky      if (Constant *CF = ConstantFoldConstantExpression(CE, TD))
39193323Sed        return CF;
40193323Sed    return C;
41193323Sed  }
42193323Sed
43193323Sedpublic:
44243830Sdim  explicit TargetFolder(const DataLayout *TheTD) : TD(TheTD) {}
45193323Sed
46193323Sed  //===--------------------------------------------------------------------===//
47193323Sed  // Binary Operators
48193323Sed  //===--------------------------------------------------------------------===//
49193323Sed
50218893Sdim  Constant *CreateAdd(Constant *LHS, Constant *RHS,
51218893Sdim                      bool HasNUW = false, bool HasNSW = false) const {
52218893Sdim    return Fold(ConstantExpr::getAdd(LHS, RHS, HasNUW, HasNSW));
53193323Sed  }
54193574Sed  Constant *CreateFAdd(Constant *LHS, Constant *RHS) const {
55193574Sed    return Fold(ConstantExpr::getFAdd(LHS, RHS));
56193574Sed  }
57218893Sdim  Constant *CreateSub(Constant *LHS, Constant *RHS,
58218893Sdim                      bool HasNUW = false, bool HasNSW = false) const {
59218893Sdim    return Fold(ConstantExpr::getSub(LHS, RHS, HasNUW, HasNSW));
60193323Sed  }
61193574Sed  Constant *CreateFSub(Constant *LHS, Constant *RHS) const {
62193574Sed    return Fold(ConstantExpr::getFSub(LHS, RHS));
63193574Sed  }
64218893Sdim  Constant *CreateMul(Constant *LHS, Constant *RHS,
65218893Sdim                      bool HasNUW = false, bool HasNSW = false) const {
66218893Sdim    return Fold(ConstantExpr::getMul(LHS, RHS, HasNUW, HasNSW));
67193323Sed  }
68193574Sed  Constant *CreateFMul(Constant *LHS, Constant *RHS) const {
69193574Sed    return Fold(ConstantExpr::getFMul(LHS, RHS));
70193574Sed  }
71218893Sdim  Constant *CreateUDiv(Constant *LHS, Constant *RHS, bool isExact = false)const{
72218893Sdim    return Fold(ConstantExpr::getUDiv(LHS, RHS, isExact));
73193323Sed  }
74218893Sdim  Constant *CreateSDiv(Constant *LHS, Constant *RHS, bool isExact = false)const{
75218893Sdim    return Fold(ConstantExpr::getSDiv(LHS, RHS, isExact));
76193323Sed  }
77193323Sed  Constant *CreateFDiv(Constant *LHS, Constant *RHS) const {
78193323Sed    return Fold(ConstantExpr::getFDiv(LHS, RHS));
79193323Sed  }
80193323Sed  Constant *CreateURem(Constant *LHS, Constant *RHS) const {
81193323Sed    return Fold(ConstantExpr::getURem(LHS, RHS));
82193323Sed  }
83193323Sed  Constant *CreateSRem(Constant *LHS, Constant *RHS) const {
84193323Sed    return Fold(ConstantExpr::getSRem(LHS, RHS));
85193323Sed  }
86193323Sed  Constant *CreateFRem(Constant *LHS, Constant *RHS) const {
87193323Sed    return Fold(ConstantExpr::getFRem(LHS, RHS));
88193323Sed  }
89218893Sdim  Constant *CreateShl(Constant *LHS, Constant *RHS,
90218893Sdim                      bool HasNUW = false, bool HasNSW = false) const {
91218893Sdim    return Fold(ConstantExpr::getShl(LHS, RHS, HasNUW, HasNSW));
92193323Sed  }
93218893Sdim  Constant *CreateLShr(Constant *LHS, Constant *RHS, bool isExact = false)const{
94218893Sdim    return Fold(ConstantExpr::getLShr(LHS, RHS, isExact));
95193323Sed  }
96218893Sdim  Constant *CreateAShr(Constant *LHS, Constant *RHS, bool isExact = false)const{
97218893Sdim    return Fold(ConstantExpr::getAShr(LHS, RHS, isExact));
98193323Sed  }
99193323Sed  Constant *CreateAnd(Constant *LHS, Constant *RHS) const {
100193323Sed    return Fold(ConstantExpr::getAnd(LHS, RHS));
101193323Sed  }
102193323Sed  Constant *CreateOr(Constant *LHS, Constant *RHS) const {
103193323Sed    return Fold(ConstantExpr::getOr(LHS, RHS));
104193323Sed  }
105193323Sed  Constant *CreateXor(Constant *LHS, Constant *RHS) const {
106193323Sed    return Fold(ConstantExpr::getXor(LHS, RHS));
107193323Sed  }
108193323Sed
109193323Sed  Constant *CreateBinOp(Instruction::BinaryOps Opc,
110193323Sed                        Constant *LHS, Constant *RHS) const {
111193323Sed    return Fold(ConstantExpr::get(Opc, LHS, RHS));
112193323Sed  }
113193323Sed
114193323Sed  //===--------------------------------------------------------------------===//
115193323Sed  // Unary Operators
116193323Sed  //===--------------------------------------------------------------------===//
117193323Sed
118218893Sdim  Constant *CreateNeg(Constant *C,
119218893Sdim                      bool HasNUW = false, bool HasNSW = false) const {
120218893Sdim    return Fold(ConstantExpr::getNeg(C, HasNUW, HasNSW));
121193323Sed  }
122193574Sed  Constant *CreateFNeg(Constant *C) const {
123193574Sed    return Fold(ConstantExpr::getFNeg(C));
124193574Sed  }
125193323Sed  Constant *CreateNot(Constant *C) const {
126193323Sed    return Fold(ConstantExpr::getNot(C));
127193323Sed  }
128193323Sed
129193323Sed  //===--------------------------------------------------------------------===//
130193323Sed  // Memory Instructions
131193323Sed  //===--------------------------------------------------------------------===//
132193323Sed
133226633Sdim  Constant *CreateGetElementPtr(Constant *C,
134226633Sdim                                ArrayRef<Constant *> IdxList) const {
135226633Sdim    return Fold(ConstantExpr::getGetElementPtr(C, IdxList));
136193323Sed  }
137226633Sdim  Constant *CreateGetElementPtr(Constant *C, Constant *Idx) const {
138226633Sdim    // This form of the function only exists to avoid ambiguous overload
139226633Sdim    // warnings about whether to convert Idx to ArrayRef<Constant *> or
140226633Sdim    // ArrayRef<Value *>.
141226633Sdim    return Fold(ConstantExpr::getGetElementPtr(C, Idx));
142193323Sed  }
143226633Sdim  Constant *CreateGetElementPtr(Constant *C,
144226633Sdim                                ArrayRef<Value *> IdxList) const {
145226633Sdim    return Fold(ConstantExpr::getGetElementPtr(C, IdxList));
146226633Sdim  }
147193323Sed
148226633Sdim  Constant *CreateInBoundsGetElementPtr(Constant *C,
149226633Sdim                                        ArrayRef<Constant *> IdxList) const {
150226633Sdim    return Fold(ConstantExpr::getInBoundsGetElementPtr(C, IdxList));
151198090Srdivacky  }
152226633Sdim  Constant *CreateInBoundsGetElementPtr(Constant *C, Constant *Idx) const {
153226633Sdim    // This form of the function only exists to avoid ambiguous overload
154226633Sdim    // warnings about whether to convert Idx to ArrayRef<Constant *> or
155226633Sdim    // ArrayRef<Value *>.
156226633Sdim    return Fold(ConstantExpr::getInBoundsGetElementPtr(C, Idx));
157198090Srdivacky  }
158226633Sdim  Constant *CreateInBoundsGetElementPtr(Constant *C,
159226633Sdim                                        ArrayRef<Value *> IdxList) const {
160226633Sdim    return Fold(ConstantExpr::getInBoundsGetElementPtr(C, IdxList));
161226633Sdim  }
162198090Srdivacky
163193323Sed  //===--------------------------------------------------------------------===//
164193323Sed  // Cast/Conversion Operators
165193323Sed  //===--------------------------------------------------------------------===//
166193323Sed
167193323Sed  Constant *CreateCast(Instruction::CastOps Op, Constant *C,
168226633Sdim                       Type *DestTy) const {
169193323Sed    if (C->getType() == DestTy)
170193323Sed      return C; // avoid calling Fold
171193323Sed    return Fold(ConstantExpr::getCast(Op, C, DestTy));
172193323Sed  }
173226633Sdim  Constant *CreateIntCast(Constant *C, Type *DestTy,
174193323Sed                          bool isSigned) const {
175193323Sed    if (C->getType() == DestTy)
176193323Sed      return C; // avoid calling Fold
177193323Sed    return Fold(ConstantExpr::getIntegerCast(C, DestTy, isSigned));
178193323Sed  }
179226633Sdim  Constant *CreatePointerCast(Constant *C, Type *DestTy) const {
180243830Sdim    if (C->getType() == DestTy)
181243830Sdim      return C; // avoid calling Fold
182243830Sdim    return Fold(ConstantExpr::getPointerCast(C, DestTy));
183204642Srdivacky  }
184243830Sdim  Constant *CreateFPCast(Constant *C, Type *DestTy) const {
185243830Sdim    if (C->getType() == DestTy)
186243830Sdim      return C; // avoid calling Fold
187243830Sdim    return Fold(ConstantExpr::getFPCast(C, DestTy));
188243830Sdim  }
189226633Sdim  Constant *CreateBitCast(Constant *C, Type *DestTy) const {
190193323Sed    return CreateCast(Instruction::BitCast, C, DestTy);
191193323Sed  }
192226633Sdim  Constant *CreateIntToPtr(Constant *C, Type *DestTy) const {
193193323Sed    return CreateCast(Instruction::IntToPtr, C, DestTy);
194193323Sed  }
195226633Sdim  Constant *CreatePtrToInt(Constant *C, Type *DestTy) const {
196193323Sed    return CreateCast(Instruction::PtrToInt, C, DestTy);
197193323Sed  }
198226633Sdim  Constant *CreateZExtOrBitCast(Constant *C, Type *DestTy) const {
199198892Srdivacky    if (C->getType() == DestTy)
200198892Srdivacky      return C; // avoid calling Fold
201198892Srdivacky    return Fold(ConstantExpr::getZExtOrBitCast(C, DestTy));
202198892Srdivacky  }
203226633Sdim  Constant *CreateSExtOrBitCast(Constant *C, Type *DestTy) const {
204198892Srdivacky    if (C->getType() == DestTy)
205198892Srdivacky      return C; // avoid calling Fold
206198892Srdivacky    return Fold(ConstantExpr::getSExtOrBitCast(C, DestTy));
207198892Srdivacky  }
208226633Sdim  Constant *CreateTruncOrBitCast(Constant *C, Type *DestTy) const {
209193323Sed    if (C->getType() == DestTy)
210193323Sed      return C; // avoid calling Fold
211193323Sed    return Fold(ConstantExpr::getTruncOrBitCast(C, DestTy));
212193323Sed  }
213193323Sed
214193323Sed  //===--------------------------------------------------------------------===//
215193323Sed  // Compare Instructions
216193323Sed  //===--------------------------------------------------------------------===//
217193323Sed
218193323Sed  Constant *CreateICmp(CmpInst::Predicate P, Constant *LHS,
219193323Sed                       Constant *RHS) const {
220193323Sed    return Fold(ConstantExpr::getCompare(P, LHS, RHS));
221193323Sed  }
222193323Sed  Constant *CreateFCmp(CmpInst::Predicate P, Constant *LHS,
223193323Sed                       Constant *RHS) const {
224193323Sed    return Fold(ConstantExpr::getCompare(P, LHS, RHS));
225193323Sed  }
226193323Sed
227193323Sed  //===--------------------------------------------------------------------===//
228193323Sed  // Other Instructions
229193323Sed  //===--------------------------------------------------------------------===//
230193323Sed
231193323Sed  Constant *CreateSelect(Constant *C, Constant *True, Constant *False) const {
232193323Sed    return Fold(ConstantExpr::getSelect(C, True, False));
233193323Sed  }
234193323Sed
235193323Sed  Constant *CreateExtractElement(Constant *Vec, Constant *Idx) const {
236193323Sed    return Fold(ConstantExpr::getExtractElement(Vec, Idx));
237193323Sed  }
238193323Sed
239193323Sed  Constant *CreateInsertElement(Constant *Vec, Constant *NewElt,
240193323Sed                                Constant *Idx) const {
241193323Sed    return Fold(ConstantExpr::getInsertElement(Vec, NewElt, Idx));
242193323Sed  }
243193323Sed
244193323Sed  Constant *CreateShuffleVector(Constant *V1, Constant *V2,
245193323Sed                                Constant *Mask) const {
246193323Sed    return Fold(ConstantExpr::getShuffleVector(V1, V2, Mask));
247193323Sed  }
248193323Sed
249224145Sdim  Constant *CreateExtractValue(Constant *Agg,
250224145Sdim                               ArrayRef<unsigned> IdxList) const {
251224145Sdim    return Fold(ConstantExpr::getExtractValue(Agg, IdxList));
252193323Sed  }
253193323Sed
254193323Sed  Constant *CreateInsertValue(Constant *Agg, Constant *Val,
255224145Sdim                              ArrayRef<unsigned> IdxList) const {
256224145Sdim    return Fold(ConstantExpr::getInsertValue(Agg, Val, IdxList));
257193323Sed  }
258193323Sed};
259193323Sed
260193323Sed}
261193323Sed
262193323Sed#endif
263