1 //===- ConstantFolder.h - Constant folding helper ---------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines the ConstantFolder class, a helper for IRBuilder.
10 // It provides IRBuilder with a set of methods for creating constants
11 // with minimal folding.  For general constant creation and folding,
12 // use ConstantExpr and the routines in llvm/Analysis/ConstantFolding.h.
13 //
14 //===----------------------------------------------------------------------===//
15 
16 #ifndef LLVM_IR_CONSTANTFOLDER_H
17 #define LLVM_IR_CONSTANTFOLDER_H
18 
19 #include "llvm/ADT/ArrayRef.h"
20 #include "llvm/ADT/STLExtras.h"
21 #include "llvm/IR/Constants.h"
22 #include "llvm/IR/ConstantFold.h"
23 #include "llvm/IR/IRBuilderFolder.h"
24 #include "llvm/IR/Instruction.h"
25 #include "llvm/IR/Operator.h"
26 
27 namespace llvm {
28 
29 /// ConstantFolder - Create constants with minimum, target independent, folding.
30 class ConstantFolder final : public IRBuilderFolder {
31   virtual void anchor();
32 
33 public:
34   explicit ConstantFolder() = default;
35 
36   //===--------------------------------------------------------------------===//
37   // Value-based folders.
38   //
39   // Return an existing value or a constant if the operation can be simplified.
40   // Otherwise return nullptr.
41   //===--------------------------------------------------------------------===//
42 
43   Value *FoldBinOp(Instruction::BinaryOps Opc, Value *LHS,
44                    Value *RHS) const override {
45     auto *LC = dyn_cast<Constant>(LHS);
46     auto *RC = dyn_cast<Constant>(RHS);
47     if (LC && RC)
48       return ConstantExpr::get(Opc, LC, RC);
49     return nullptr;
50   }
51 
52   Value *FoldExactBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS,
53                         bool IsExact) const override {
54     auto *LC = dyn_cast<Constant>(LHS);
55     auto *RC = dyn_cast<Constant>(RHS);
56     if (LC && RC)
57       return ConstantExpr::get(Opc, LC, RC,
58                                IsExact ? PossiblyExactOperator::IsExact : 0);
59     return nullptr;
60   }
61 
62   Value *FoldNoWrapBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS,
63                          bool HasNUW, bool HasNSW) const override {
64     auto *LC = dyn_cast<Constant>(LHS);
65     auto *RC = dyn_cast<Constant>(RHS);
66     if (LC && RC) {
67       unsigned Flags = 0;
68       if (HasNUW)
69         Flags |= OverflowingBinaryOperator::NoUnsignedWrap;
70       if (HasNSW)
71         Flags |= OverflowingBinaryOperator::NoSignedWrap;
72       return ConstantExpr::get(Opc, LC, RC, Flags);
73     }
74     return nullptr;
75   }
76 
77   Value *FoldBinOpFMF(Instruction::BinaryOps Opc, Value *LHS, Value *RHS,
78                       FastMathFlags FMF) const override {
79     return FoldBinOp(Opc, LHS, RHS);
80   }
81 
82   Value *FoldICmp(CmpInst::Predicate P, Value *LHS, Value *RHS) const override {
83     auto *LC = dyn_cast<Constant>(LHS);
84     auto *RC = dyn_cast<Constant>(RHS);
85     if (LC && RC)
86       return ConstantExpr::getCompare(P, LC, RC);
87     return nullptr;
88   }
89 
90   Value *FoldGEP(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList,
91                  bool IsInBounds = false) const override {
92     if (auto *PC = dyn_cast<Constant>(Ptr)) {
93       // Every index must be constant.
94       if (any_of(IdxList, [](Value *V) { return !isa<Constant>(V); }))
95         return nullptr;
96 
97       if (IsInBounds)
98         return ConstantExpr::getInBoundsGetElementPtr(Ty, PC, IdxList);
99       else
100         return ConstantExpr::getGetElementPtr(Ty, PC, IdxList);
101     }
102     return nullptr;
103   }
104 
105   Value *FoldSelect(Value *C, Value *True, Value *False) const override {
106     auto *CC = dyn_cast<Constant>(C);
107     auto *TC = dyn_cast<Constant>(True);
108     auto *FC = dyn_cast<Constant>(False);
109     if (CC && TC && FC)
110       return ConstantExpr::getSelect(CC, TC, FC);
111     return nullptr;
112   }
113 
114   Value *FoldExtractValue(Value *Agg,
115                           ArrayRef<unsigned> IdxList) const override {
116     if (auto *CAgg = dyn_cast<Constant>(Agg))
117       return ConstantFoldExtractValueInstruction(CAgg, IdxList);
118     return nullptr;
119   };
120 
121   Value *FoldInsertValue(Value *Agg, Value *Val,
122                          ArrayRef<unsigned> IdxList) const override {
123     auto *CAgg = dyn_cast<Constant>(Agg);
124     auto *CVal = dyn_cast<Constant>(Val);
125     if (CAgg && CVal)
126       return ConstantFoldInsertValueInstruction(CAgg, CVal, IdxList);
127     return nullptr;
128   }
129 
130   Value *FoldExtractElement(Value *Vec, Value *Idx) const override {
131     auto *CVec = dyn_cast<Constant>(Vec);
132     auto *CIdx = dyn_cast<Constant>(Idx);
133     if (CVec && CIdx)
134       return ConstantExpr::getExtractElement(CVec, CIdx);
135     return nullptr;
136   }
137 
138   Value *FoldInsertElement(Value *Vec, Value *NewElt,
139                            Value *Idx) const override {
140     auto *CVec = dyn_cast<Constant>(Vec);
141     auto *CNewElt = dyn_cast<Constant>(NewElt);
142     auto *CIdx = dyn_cast<Constant>(Idx);
143     if (CVec && CNewElt && CIdx)
144       return ConstantExpr::getInsertElement(CVec, CNewElt, CIdx);
145     return nullptr;
146   }
147 
148   Value *FoldShuffleVector(Value *V1, Value *V2,
149                            ArrayRef<int> Mask) const override {
150     auto *C1 = dyn_cast<Constant>(V1);
151     auto *C2 = dyn_cast<Constant>(V2);
152     if (C1 && C2)
153       return ConstantExpr::getShuffleVector(C1, C2, Mask);
154     return nullptr;
155   }
156 
157   //===--------------------------------------------------------------------===//
158   // Unary Operators
159   //===--------------------------------------------------------------------===//
160 
161   Constant *CreateFNeg(Constant *C) const override {
162     return ConstantExpr::getFNeg(C);
163   }
164 
165   Constant *CreateUnOp(Instruction::UnaryOps Opc, Constant *C) const override {
166     return ConstantExpr::get(Opc, C);
167   }
168 
169   //===--------------------------------------------------------------------===//
170   // Cast/Conversion Operators
171   //===--------------------------------------------------------------------===//
172 
173   Constant *CreateCast(Instruction::CastOps Op, Constant *C,
174                        Type *DestTy) const override {
175     return ConstantExpr::getCast(Op, C, DestTy);
176   }
177 
178   Constant *CreatePointerCast(Constant *C, Type *DestTy) const override {
179     return ConstantExpr::getPointerCast(C, DestTy);
180   }
181 
182   Constant *CreatePointerBitCastOrAddrSpaceCast(Constant *C,
183                                                 Type *DestTy) const override {
184     return ConstantExpr::getPointerBitCastOrAddrSpaceCast(C, DestTy);
185   }
186 
187   Constant *CreateIntCast(Constant *C, Type *DestTy,
188                           bool isSigned) const override {
189     return ConstantExpr::getIntegerCast(C, DestTy, isSigned);
190   }
191 
192   Constant *CreateFPCast(Constant *C, Type *DestTy) const override {
193     return ConstantExpr::getFPCast(C, DestTy);
194   }
195 
196   Constant *CreateBitCast(Constant *C, Type *DestTy) const override {
197     return CreateCast(Instruction::BitCast, C, DestTy);
198   }
199 
200   Constant *CreateIntToPtr(Constant *C, Type *DestTy) const override {
201     return CreateCast(Instruction::IntToPtr, C, DestTy);
202   }
203 
204   Constant *CreatePtrToInt(Constant *C, Type *DestTy) const override {
205     return CreateCast(Instruction::PtrToInt, C, DestTy);
206   }
207 
208   Constant *CreateZExtOrBitCast(Constant *C, Type *DestTy) const override {
209     return ConstantExpr::getZExtOrBitCast(C, DestTy);
210   }
211 
212   Constant *CreateSExtOrBitCast(Constant *C, Type *DestTy) const override {
213     return ConstantExpr::getSExtOrBitCast(C, DestTy);
214   }
215 
216   Constant *CreateTruncOrBitCast(Constant *C, Type *DestTy) const override {
217     return ConstantExpr::getTruncOrBitCast(C, DestTy);
218   }
219 
220   //===--------------------------------------------------------------------===//
221   // Compare Instructions
222   //===--------------------------------------------------------------------===//
223 
224   Constant *CreateFCmp(CmpInst::Predicate P, Constant *LHS,
225                        Constant *RHS) const override {
226     return ConstantExpr::getCompare(P, LHS, RHS);
227   }
228 };
229 
230 } // end namespace llvm
231 
232 #endif // LLVM_IR_CONSTANTFOLDER_H
233