TargetFolder.h 9.1 KB

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