xref: /freebsd/contrib/llvm-project/llvm/include/llvm/Analysis/TargetFolder.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //====- TargetFolder.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 TargetFolder class, a helper for IRBuilder.
10 // It provides IRBuilder with a set of methods for creating constants with
11 // target dependent folding, in addition to the same target-independent
12 // folding that the ConstantFolder class provides.  For general constant
13 // creation and folding, use ConstantExpr and the routines in
14 // llvm/Analysis/ConstantFolding.h.
15 //
16 //===----------------------------------------------------------------------===//
17 
18 #ifndef LLVM_ANALYSIS_TARGETFOLDER_H
19 #define LLVM_ANALYSIS_TARGETFOLDER_H
20 
21 #include "llvm/ADT/ArrayRef.h"
22 #include "llvm/Analysis/ConstantFolding.h"
23 #include "llvm/IR/Constants.h"
24 #include "llvm/IR/IRBuilderFolder.h"
25 #include "llvm/IR/Operator.h"
26 #include "llvm/Support/Compiler.h"
27 
28 namespace llvm {
29 
30 class Constant;
31 class DataLayout;
32 class Type;
33 
34 /// TargetFolder - Create constants with target dependent folding.
35 class LLVM_ABI TargetFolder final : public IRBuilderFolder {
36   const DataLayout &DL;
37 
38   /// Fold - Fold the constant using target specific information.
Fold(Constant * C)39   Constant *Fold(Constant *C) const {
40     return ConstantFoldConstant(C, DL);
41   }
42 
43   LLVM_DECLARE_VIRTUAL_ANCHOR_FUNCTION();
44 
45 public:
TargetFolder(const DataLayout & DL)46   explicit TargetFolder(const DataLayout &DL) : DL(DL) {}
47 
48   //===--------------------------------------------------------------------===//
49   // Value-based folders.
50   //
51   // Return an existing value or a constant if the operation can be simplified.
52   // Otherwise return nullptr.
53   //===--------------------------------------------------------------------===//
54 
FoldBinOp(Instruction::BinaryOps Opc,Value * LHS,Value * RHS)55   Value *FoldBinOp(Instruction::BinaryOps Opc, Value *LHS,
56                    Value *RHS) const override {
57     auto *LC = dyn_cast<Constant>(LHS);
58     auto *RC = dyn_cast<Constant>(RHS);
59     if (LC && RC) {
60       if (ConstantExpr::isDesirableBinOp(Opc))
61         return Fold(ConstantExpr::get(Opc, LC, RC));
62       return ConstantFoldBinaryOpOperands(Opc, LC, RC, DL);
63     }
64     return nullptr;
65   }
66 
FoldExactBinOp(Instruction::BinaryOps Opc,Value * LHS,Value * RHS,bool IsExact)67   Value *FoldExactBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS,
68                         bool IsExact) const override {
69     auto *LC = dyn_cast<Constant>(LHS);
70     auto *RC = dyn_cast<Constant>(RHS);
71     if (LC && RC) {
72       if (ConstantExpr::isDesirableBinOp(Opc))
73         return Fold(ConstantExpr::get(
74             Opc, LC, RC, IsExact ? PossiblyExactOperator::IsExact : 0));
75       return ConstantFoldBinaryOpOperands(Opc, LC, RC, DL);
76     }
77     return nullptr;
78   }
79 
FoldNoWrapBinOp(Instruction::BinaryOps Opc,Value * LHS,Value * RHS,bool HasNUW,bool HasNSW)80   Value *FoldNoWrapBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS,
81                          bool HasNUW, bool HasNSW) const override {
82     auto *LC = dyn_cast<Constant>(LHS);
83     auto *RC = dyn_cast<Constant>(RHS);
84     if (LC && RC) {
85       if (ConstantExpr::isDesirableBinOp(Opc)) {
86         unsigned Flags = 0;
87         if (HasNUW)
88           Flags |= OverflowingBinaryOperator::NoUnsignedWrap;
89         if (HasNSW)
90           Flags |= OverflowingBinaryOperator::NoSignedWrap;
91         return Fold(ConstantExpr::get(Opc, LC, RC, Flags));
92       }
93       return ConstantFoldBinaryOpOperands(Opc, LC, RC, DL);
94     }
95     return nullptr;
96   }
97 
FoldBinOpFMF(Instruction::BinaryOps Opc,Value * LHS,Value * RHS,FastMathFlags FMF)98   Value *FoldBinOpFMF(Instruction::BinaryOps Opc, Value *LHS, Value *RHS,
99                       FastMathFlags FMF) const override {
100     return FoldBinOp(Opc, LHS, RHS);
101   }
102 
FoldCmp(CmpInst::Predicate P,Value * LHS,Value * RHS)103   Value *FoldCmp(CmpInst::Predicate P, Value *LHS, Value *RHS) const override {
104     auto *LC = dyn_cast<Constant>(LHS);
105     auto *RC = dyn_cast<Constant>(RHS);
106     if (LC && RC)
107       return ConstantFoldCompareInstOperands(P, LC, RC, DL);
108     return nullptr;
109   }
110 
FoldUnOpFMF(Instruction::UnaryOps Opc,Value * V,FastMathFlags FMF)111   Value *FoldUnOpFMF(Instruction::UnaryOps Opc, Value *V,
112                       FastMathFlags FMF) const override {
113     if (Constant *C = dyn_cast<Constant>(V))
114       return ConstantFoldUnaryOpOperand(Opc, C, DL);
115     return nullptr;
116   }
117 
FoldGEP(Type * Ty,Value * Ptr,ArrayRef<Value * > IdxList,GEPNoWrapFlags NW)118   Value *FoldGEP(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList,
119                  GEPNoWrapFlags NW) const override {
120     if (!ConstantExpr::isSupportedGetElementPtr(Ty))
121       return nullptr;
122 
123     if (auto *PC = dyn_cast<Constant>(Ptr)) {
124       // Every index must be constant.
125       if (any_of(IdxList, [](Value *V) { return !isa<Constant>(V); }))
126         return nullptr;
127       return Fold(ConstantExpr::getGetElementPtr(Ty, PC, IdxList, NW));
128     }
129     return nullptr;
130   }
131 
FoldSelect(Value * C,Value * True,Value * False)132   Value *FoldSelect(Value *C, Value *True, Value *False) const override {
133     auto *CC = dyn_cast<Constant>(C);
134     auto *TC = dyn_cast<Constant>(True);
135     auto *FC = dyn_cast<Constant>(False);
136     if (CC && TC && FC)
137       return ConstantFoldSelectInstruction(CC, TC, FC);
138 
139     return nullptr;
140   }
141 
FoldExtractValue(Value * Agg,ArrayRef<unsigned> IdxList)142   Value *FoldExtractValue(Value *Agg,
143                           ArrayRef<unsigned> IdxList) const override {
144     if (auto *CAgg = dyn_cast<Constant>(Agg))
145       return ConstantFoldExtractValueInstruction(CAgg, IdxList);
146     return nullptr;
147   };
148 
FoldInsertValue(Value * Agg,Value * Val,ArrayRef<unsigned> IdxList)149   Value *FoldInsertValue(Value *Agg, Value *Val,
150                          ArrayRef<unsigned> IdxList) const override {
151     auto *CAgg = dyn_cast<Constant>(Agg);
152     auto *CVal = dyn_cast<Constant>(Val);
153     if (CAgg && CVal)
154       return ConstantFoldInsertValueInstruction(CAgg, CVal, IdxList);
155     return nullptr;
156   }
157 
FoldExtractElement(Value * Vec,Value * Idx)158   Value *FoldExtractElement(Value *Vec, Value *Idx) const override {
159     auto *CVec = dyn_cast<Constant>(Vec);
160     auto *CIdx = dyn_cast<Constant>(Idx);
161     if (CVec && CIdx)
162       return Fold(ConstantExpr::getExtractElement(CVec, CIdx));
163     return nullptr;
164   }
165 
FoldInsertElement(Value * Vec,Value * NewElt,Value * Idx)166   Value *FoldInsertElement(Value *Vec, Value *NewElt,
167                            Value *Idx) const override {
168     auto *CVec = dyn_cast<Constant>(Vec);
169     auto *CNewElt = dyn_cast<Constant>(NewElt);
170     auto *CIdx = dyn_cast<Constant>(Idx);
171     if (CVec && CNewElt && CIdx)
172       return Fold(ConstantExpr::getInsertElement(CVec, CNewElt, CIdx));
173     return nullptr;
174   }
175 
FoldShuffleVector(Value * V1,Value * V2,ArrayRef<int> Mask)176   Value *FoldShuffleVector(Value *V1, Value *V2,
177                            ArrayRef<int> Mask) const override {
178     auto *C1 = dyn_cast<Constant>(V1);
179     auto *C2 = dyn_cast<Constant>(V2);
180     if (C1 && C2)
181       return Fold(ConstantExpr::getShuffleVector(C1, C2, Mask));
182     return nullptr;
183   }
184 
FoldCast(Instruction::CastOps Op,Value * V,Type * DestTy)185   Value *FoldCast(Instruction::CastOps Op, Value *V,
186                   Type *DestTy) const override {
187     if (auto *C = dyn_cast<Constant>(V))
188       return ConstantFoldCastOperand(Op, C, DestTy, DL);
189     return nullptr;
190   }
191 
FoldBinaryIntrinsic(Intrinsic::ID ID,Value * LHS,Value * RHS,Type * Ty,Instruction * FMFSource)192   Value *FoldBinaryIntrinsic(Intrinsic::ID ID, Value *LHS, Value *RHS, Type *Ty,
193                              Instruction *FMFSource) const override {
194     auto *C1 = dyn_cast<Constant>(LHS);
195     auto *C2 = dyn_cast<Constant>(RHS);
196     if (C1 && C2)
197       return ConstantFoldBinaryIntrinsic(ID, C1, C2, Ty, FMFSource);
198     return nullptr;
199   }
200 
201   //===--------------------------------------------------------------------===//
202   // Cast/Conversion Operators
203   //===--------------------------------------------------------------------===//
204 
CreatePointerCast(Constant * C,Type * DestTy)205   Constant *CreatePointerCast(Constant *C, Type *DestTy) const override {
206     if (C->getType() == DestTy)
207       return C; // avoid calling Fold
208     return Fold(ConstantExpr::getPointerCast(C, DestTy));
209   }
210 
CreatePointerBitCastOrAddrSpaceCast(Constant * C,Type * DestTy)211   Constant *CreatePointerBitCastOrAddrSpaceCast(Constant *C,
212                                                 Type *DestTy) const override {
213     if (C->getType() == DestTy)
214       return C; // avoid calling Fold
215     return Fold(ConstantExpr::getPointerBitCastOrAddrSpaceCast(C, DestTy));
216   }
217 };
218 }
219 
220 #endif
221