1 //===- StaticValueUtils.cpp - Utilities for dealing with static values ----===//
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 #include "mlir/Dialect/Utils/StaticValueUtils.h"
10 #include "mlir/IR/Matchers.h"
11 #include "mlir/Support/LLVM.h"
12 #include "llvm/ADT/APSInt.h"
13 
14 namespace mlir {
15 
16 /// Helper function to dispatch an OpFoldResult into either the `dynamicVec` if
17 /// it is a Value or into `staticVec` if it is an IntegerAttr.
18 /// In the case of a Value, a copy of the `sentinel` value is also pushed to
19 /// `staticVec`. This is useful to extract mixed static and dynamic entries that
20 /// come from an AttrSizedOperandSegments trait.
21 void dispatchIndexOpFoldResult(OpFoldResult ofr,
22                                SmallVectorImpl<Value> &dynamicVec,
23                                SmallVectorImpl<int64_t> &staticVec,
24                                int64_t sentinel) {
25   if (auto v = ofr.dyn_cast<Value>()) {
26     dynamicVec.push_back(v);
27     staticVec.push_back(sentinel);
28     return;
29   }
30   APInt apInt = ofr.dyn_cast<Attribute>().cast<IntegerAttr>().getValue();
31   staticVec.push_back(apInt.getSExtValue());
32 }
33 
34 void dispatchIndexOpFoldResults(ArrayRef<OpFoldResult> ofrs,
35                                 SmallVectorImpl<Value> &dynamicVec,
36                                 SmallVectorImpl<int64_t> &staticVec,
37                                 int64_t sentinel) {
38   for (OpFoldResult ofr : ofrs)
39     dispatchIndexOpFoldResult(ofr, dynamicVec, staticVec, sentinel);
40 }
41 
42 /// Extract int64_t values from the assumed ArrayAttr of IntegerAttr.
43 SmallVector<int64_t, 4> extractFromI64ArrayAttr(Attribute attr) {
44   return llvm::to_vector<4>(
45       llvm::map_range(attr.cast<ArrayAttr>(), [](Attribute a) -> int64_t {
46         return a.cast<IntegerAttr>().getInt();
47       }));
48 }
49 
50 /// Given a value, try to extract a constant Attribute. If this fails, return
51 /// the original value.
52 OpFoldResult getAsOpFoldResult(Value val) {
53   Attribute attr;
54   if (matchPattern(val, m_Constant(&attr)))
55     return attr;
56   return val;
57 }
58 
59 /// Given an array of values, try to extract a constant Attribute from each
60 /// value. If this fails, return the original value.
61 SmallVector<OpFoldResult> getAsOpFoldResult(ArrayRef<Value> values) {
62   return llvm::to_vector<4>(
63       llvm::map_range(values, [](Value v) { return getAsOpFoldResult(v); }));
64 }
65 
66 /// If ofr is a constant integer or an IntegerAttr, return the integer.
67 Optional<int64_t> getConstantIntValue(OpFoldResult ofr) {
68   // Case 1: Check for Constant integer.
69   if (auto val = ofr.dyn_cast<Value>()) {
70     APSInt intVal;
71     if (matchPattern(val, m_ConstantInt(&intVal)))
72       return intVal.getSExtValue();
73     return llvm::None;
74   }
75   // Case 2: Check for IntegerAttr.
76   Attribute attr = ofr.dyn_cast<Attribute>();
77   if (auto intAttr = attr.dyn_cast_or_null<IntegerAttr>())
78     return intAttr.getValue().getSExtValue();
79   return llvm::None;
80 }
81 
82 /// Return true if ofr1 and ofr2 are the same integer constant attribute values
83 /// or the same SSA value.
84 /// Ignore integer bitwidth and type mismatch that come from the fact there is
85 /// no IndexAttr and that IndexType has no bitwidth.
86 bool isEqualConstantIntOrValue(OpFoldResult ofr1, OpFoldResult ofr2) {
87   auto cst1 = getConstantIntValue(ofr1), cst2 = getConstantIntValue(ofr2);
88   if (cst1 && cst2 && *cst1 == *cst2)
89     return true;
90   auto v1 = ofr1.dyn_cast<Value>(), v2 = ofr2.dyn_cast<Value>();
91   return v1 && v1 == v2;
92 }
93 } // namespace mlir
94