llvm.org GIT mirror llvm / baa325e
[Analysis] add isSplatValue() for vectors in IR We have the related getSplatValue() already in IR (see code just above the proposed addition). But sometimes we only need to know that the value is a splat rather than capture the splatted scalar value. Also, we have an isSplatValue() function already in SDAG. Motivation - recent bugs that would potentially benefit from improved splat analysis in IR: https://bugs.llvm.org/show_bug.cgi?id=37428 https://bugs.llvm.org/show_bug.cgi?id=42174 Differential Revision: https://reviews.llvm.org/D63138 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@363106 91177308-0d34-0410-b5e6-96231b3b80d8 Sanjay Patel a month ago
3 changed file(s) with 235 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
7676 /// The value may be extracted from a splat constants vector or from
7777 /// a sequence of instructions that broadcast a single value into a vector.
7878 const Value *getSplatValue(const Value *V);
79
80 /// Return true if the input value is known to be a vector with all identical
81 /// elements (potentially including undefined elements).
82 /// This may be more powerful than the related getSplatValue() because it is
83 /// not limited by finding a scalar source value to a splatted vector.
84 bool isSplatValue(const Value *V, unsigned Depth = 0);
7985
8086 /// Compute a map of integer instructions to their minimum legal type
8187 /// size.
320320 return nullptr;
321321 }
322322
323 // This setting is based on its counterpart in value tracking, but it could be
324 // adjusted if needed.
325 const unsigned MaxDepth = 6;
326
327 bool llvm::isSplatValue(const Value *V, unsigned Depth) {
328 assert(Depth <= MaxDepth && "Limit Search Depth");
329
330 if (isa(V->getType())) {
331 if (isa(V))
332 return true;
333 // FIXME: Constant splat analysis does not allow undef elements.
334 if (auto *C = dyn_cast(V))
335 return C->getSplatValue() != nullptr;
336 }
337
338 // FIXME: Constant splat analysis does not allow undef elements.
339 Constant *Mask;
340 if (match(V, m_ShuffleVector(m_Value(), m_Value(), m_Constant(Mask))))
341 return Mask->getSplatValue() != nullptr;
342
343 // The remaining tests are all recursive, so bail out if we hit the limit.
344 if (Depth++ == MaxDepth)
345 return false;
346
347 // If both operands of a binop are splats, the result is a splat.
348 Value *X, *Y, *Z;
349 if (match(V, m_BinOp(m_Value(X), m_Value(Y))))
350 return isSplatValue(X, Depth) && isSplatValue(Y, Depth);
351
352 // If all operands of a select are splats, the result is a splat.
353 if (match(V, m_Select(m_Value(X), m_Value(Y), m_Value(Z))))
354 return isSplatValue(X, Depth) && isSplatValue(Y, Depth) &&
355 isSplatValue(Z, Depth);
356
357 // TODO: Add support for unary ops (fneg), casts, intrinsics (overflow ops).
358
359 return false;
360 }
361
323362 MapVector
324363 llvm::computeMinimumValueSizes(ArrayRef Blocks, DemandedBits &DB,
325364 const TargetTransformInfo *TTI) {
1010 #include "llvm/AsmParser/Parser.h"
1111 #include "llvm/IR/Function.h"
1212 #include "llvm/IR/InstIterator.h"
13 #include "llvm/IR/IRBuilder.h"
1314 #include "llvm/IR/LLVMContext.h"
1415 #include "llvm/IR/Module.h"
16 #include "llvm/IR/NoFolder.h"
1517 #include "llvm/Support/ErrorHandling.h"
1618 #include "llvm/Support/SourceMgr.h"
1719 #include "llvm/Support/KnownBits.h"
5557 Instruction *A;
5658 };
5759
60 struct BasicTest : public testing::Test {
61 LLVMContext Ctx;
62 std::unique_ptr M;
63 Function *F;
64 BasicBlock *BB;
65 IRBuilder IRB;
66
67 BasicTest()
68 : M(new Module("VectorUtils", Ctx)),
69 F(Function::Create(
70 FunctionType::get(Type::getVoidTy(Ctx), /* IsVarArg */ false),
71 Function::ExternalLinkage, "f", M.get())),
72 BB(BasicBlock::Create(Ctx, "entry", F)), IRB(BB) {}
73 };
74
75
5876 } // namespace
77
78 TEST_F(BasicTest, isSplat) {
79 Value *UndefVec = UndefValue::get(VectorType::get(IRB.getInt8Ty(), 4));
80 EXPECT_TRUE(isSplatValue(UndefVec));
81
82 Constant *UndefScalar = UndefValue::get(IRB.getInt8Ty());
83 EXPECT_FALSE(isSplatValue(UndefScalar));
84
85 Constant *ScalarC = IRB.getInt8(42);
86 EXPECT_FALSE(isSplatValue(ScalarC));
87
88 Constant *OtherScalarC = IRB.getInt8(-42);
89 Constant *NonSplatC = ConstantVector::get({ScalarC, OtherScalarC});
90 EXPECT_FALSE(isSplatValue(NonSplatC));
91
92 Value *SplatC = IRB.CreateVectorSplat(5, ScalarC);
93 EXPECT_TRUE(isSplatValue(SplatC));
94
95 // FIXME: Constant splat analysis does not allow undef elements.
96 Constant *SplatWithUndefC = ConstantVector::get({ScalarC, UndefScalar});
97 EXPECT_FALSE(isSplatValue(SplatWithUndefC));
98 }
99
100 TEST_F(VectorUtilsTest, isSplatValue_00) {
101 parseAssembly(
102 "define <2 x i8> @test(<2 x i8> %x) {\n"
103 " %A = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> zeroinitializer\n"
104 " ret <2 x i8> %A\n"
105 "}\n");
106 EXPECT_TRUE(isSplatValue(A));
107 }
108
109 TEST_F(VectorUtilsTest, isSplatValue_11) {
110 parseAssembly(
111 "define <2 x i8> @test(<2 x i8> %x) {\n"
112 " %A = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> \n"
113 " ret <2 x i8> %A\n"
114 "}\n");
115 EXPECT_TRUE(isSplatValue(A));
116 }
117
118 TEST_F(VectorUtilsTest, isSplatValue_01) {
119 parseAssembly(
120 "define <2 x i8> @test(<2 x i8> %x) {\n"
121 " %A = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> \n"
122 " ret <2 x i8> %A\n"
123 "}\n");
124 EXPECT_FALSE(isSplatValue(A));
125 }
126
127 // FIXME: Constant (mask) splat analysis does not allow undef elements.
128
129 TEST_F(VectorUtilsTest, isSplatValue_0u) {
130 parseAssembly(
131 "define <2 x i8> @test(<2 x i8> %x) {\n"
132 " %A = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> \n"
133 " ret <2 x i8> %A\n"
134 "}\n");
135 EXPECT_FALSE(isSplatValue(A));
136 }
137
138 TEST_F(VectorUtilsTest, isSplatValue_Binop) {
139 parseAssembly(
140 "define <2 x i8> @test(<2 x i8> %x) {\n"
141 " %v0 = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> \n"
142 " %v1 = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> \n"
143 " %A = udiv <2 x i8> %v0, %v1\n"
144 " ret <2 x i8> %A\n"
145 "}\n");
146 EXPECT_TRUE(isSplatValue(A));
147 }
148
149 TEST_F(VectorUtilsTest, isSplatValue_Binop_ConstantOp0) {
150 parseAssembly(
151 "define <2 x i8> @test(<2 x i8> %x) {\n"
152 " %v1 = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> \n"
153 " %A = ashr <2 x i8> , %v1\n"
154 " ret <2 x i8> %A\n"
155 "}\n");
156 EXPECT_TRUE(isSplatValue(A));
157 }
158
159 TEST_F(VectorUtilsTest, isSplatValue_Binop_Not_Op0) {
160 parseAssembly(
161 "define <2 x i8> @test(<2 x i8> %x) {\n"
162 " %v0 = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> \n"
163 " %v1 = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> \n"
164 " %A = add <2 x i8> %v0, %v1\n"
165 " ret <2 x i8> %A\n"
166 "}\n");
167 EXPECT_FALSE(isSplatValue(A));
168 }
169
170 TEST_F(VectorUtilsTest, isSplatValue_Binop_Not_Op1) {
171 parseAssembly(
172 "define <2 x i8> @test(<2 x i8> %x) {\n"
173 " %v0 = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> \n"
174 " %v1 = shufflevector <2 x i8> %x, <2 x i8> undef, <2 x i32> \n"
175 " %A = shl <2 x i8> %v0, %v1\n"
176 " ret <2 x i8> %A\n"
177 "}\n");
178 EXPECT_FALSE(isSplatValue(A));
179 }
180
181 TEST_F(VectorUtilsTest, isSplatValue_Select) {
182 parseAssembly(
183 "define <2 x i8> @test(<2 x i1> %x, <2 x i8> %y, <2 x i8> %z) {\n"
184 " %v0 = shufflevector <2 x i1> %x, <2 x i1> undef, <2 x i32> \n"
185 " %v1 = shufflevector <2 x i8> %y, <2 x i8> undef, <2 x i32> \n"
186 " %v2 = shufflevector <2 x i8> %z, <2 x i8> undef, <2 x i32> \n"
187 " %A = select <2 x i1> %v0, <2 x i8> %v1, <2 x i8> %v2\n"
188 " ret <2 x i8> %A\n"
189 "}\n");
190 EXPECT_TRUE(isSplatValue(A));
191 }
192
193 TEST_F(VectorUtilsTest, isSplatValue_Select_ConstantOp) {
194 parseAssembly(
195 "define <2 x i8> @test(<2 x i1> %x, <2 x i8> %y, <2 x i8> %z) {\n"
196 " %v0 = shufflevector <2 x i1> %x, <2 x i1> undef, <2 x i32> \n"
197 " %v2 = shufflevector <2 x i8> %z, <2 x i8> undef, <2 x i32> \n"
198 " %A = select <2 x i1> %v0, <2 x i8> , <2 x i8> %v2\n"
199 " ret <2 x i8> %A\n"
200 "}\n");
201 EXPECT_TRUE(isSplatValue(A));
202 }
203
204 TEST_F(VectorUtilsTest, isSplatValue_Select_NotCond) {
205 parseAssembly(
206 "define <2 x i8> @test(<2 x i1> %x, <2 x i8> %y, <2 x i8> %z) {\n"
207 " %v1 = shufflevector <2 x i8> %y, <2 x i8> undef, <2 x i32> \n"
208 " %v2 = shufflevector <2 x i8> %z, <2 x i8> undef, <2 x i32> \n"
209 " %A = select <2 x i1> %x, <2 x i8> %v1, <2 x i8> %v2\n"
210 " ret <2 x i8> %A\n"
211 "}\n");
212 EXPECT_FALSE(isSplatValue(A));
213 }
214
215 TEST_F(VectorUtilsTest, isSplatValue_Select_NotOp1) {
216 parseAssembly(
217 "define <2 x i8> @test(<2 x i1> %x, <2 x i8> %y, <2 x i8> %z) {\n"
218 " %v0 = shufflevector <2 x i1> %x, <2 x i1> undef, <2 x i32> \n"
219 " %v2 = shufflevector <2 x i8> %z, <2 x i8> undef, <2 x i32> \n"
220 " %A = select <2 x i1> %v0, <2 x i8> %y, <2 x i8> %v2\n"
221 " ret <2 x i8> %A\n"
222 "}\n");
223 EXPECT_FALSE(isSplatValue(A));
224 }
225
226 TEST_F(VectorUtilsTest, isSplatValue_Select_NotOp2) {
227 parseAssembly(
228 "define <2 x i8> @test(<2 x i1> %x, <2 x i8> %y, <2 x i8> %z) {\n"
229 " %v0 = shufflevector <2 x i1> %x, <2 x i1> undef, <2 x i32> \n"
230 " %v1 = shufflevector <2 x i8> %y, <2 x i8> undef, <2 x i32> \n"
231 " %A = select <2 x i1> %v0, <2 x i8> %v1, <2 x i8> %z\n"
232 " ret <2 x i8> %A\n"
233 "}\n");
234 EXPECT_FALSE(isSplatValue(A));
235 }
236
237 TEST_F(VectorUtilsTest, isSplatValue_SelectBinop) {
238 parseAssembly(
239 "define <2 x i8> @test(<2 x i1> %x, <2 x i8> %y, <2 x i8> %z) {\n"
240 " %v0 = shufflevector <2 x i1> %x, <2 x i1> undef, <2 x i32> \n"
241 " %v1 = shufflevector <2 x i8> %y, <2 x i8> undef, <2 x i32> \n"
242 " %v2 = shufflevector <2 x i8> %z, <2 x i8> undef, <2 x i32> \n"
243 " %bo = xor <2 x i8> %v1, %v2\n"
244 " %A = select <2 x i1> %v0, <2 x i8> %bo, <2 x i8> %v2\n"
245 " ret <2 x i8> %A\n"
246 "}\n");
247 EXPECT_TRUE(isSplatValue(A));
248 }
59249
60250 TEST_F(VectorUtilsTest, getSplatValueElt0) {
61251 parseAssembly(