1 //===- llvm/unittest/CodeGen/AArch64SelectionDAGTest.cpp -------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/Analysis/OptimizationRemarkEmitter.h"
10 #include "llvm/AsmParser/Parser.h"
11 #include "llvm/CodeGen/MachineModuleInfo.h"
12 #include "llvm/CodeGen/SelectionDAG.h"
13 #include "llvm/CodeGen/TargetLowering.h"
14 #include "llvm/MC/TargetRegistry.h"
15 #include "llvm/Support/KnownBits.h"
16 #include "llvm/Support/SourceMgr.h"
17 #include "llvm/Support/TargetSelect.h"
18 #include "llvm/Target/TargetMachine.h"
19 #include "gtest/gtest.h"
23 class AArch64SelectionDAGTest
: public testing::Test
{
25 static void SetUpTestCase() {
26 InitializeAllTargets();
27 InitializeAllTargetMCs();
30 void SetUp() override
{
31 StringRef Assembly
= "define void @f() { ret void }";
33 Triple
TargetTriple("aarch64--");
35 const Target
*T
= TargetRegistry::lookupTarget("", TargetTriple
, Error
);
36 // FIXME: These tests do not depend on AArch64 specifically, but we have to
37 // initialize a target. A skeleton Target for unittests would allow us to
38 // always run these tests.
42 TargetOptions Options
;
43 TM
= std::unique_ptr
<LLVMTargetMachine
>(static_cast<LLVMTargetMachine
*>(
44 T
->createTargetMachine("AArch64", "", "+sve", Options
, std::nullopt
,
45 std::nullopt
, CodeGenOptLevel::Aggressive
)));
50 M
= parseAssemblyString(Assembly
, SMError
, Context
);
52 report_fatal_error(SMError
.getMessage());
53 M
->setDataLayout(TM
->createDataLayout());
55 F
= M
->getFunction("f");
57 report_fatal_error("F?");
59 MachineModuleInfo
MMI(TM
.get());
61 MF
= std::make_unique
<MachineFunction
>(*F
, *TM
, *TM
->getSubtargetImpl(*F
), 0,
64 DAG
= std::make_unique
<SelectionDAG
>(*TM
, CodeGenOptLevel::None
);
66 report_fatal_error("DAG?");
67 OptimizationRemarkEmitter
ORE(F
);
68 DAG
->init(*MF
, ORE
, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
71 TargetLoweringBase::LegalizeTypeAction
getTypeAction(EVT VT
) {
72 return DAG
->getTargetLoweringInfo().getTypeAction(Context
, VT
);
75 EVT
getTypeToTransformTo(EVT VT
) {
76 return DAG
->getTargetLoweringInfo().getTypeToTransformTo(Context
, VT
);
80 std::unique_ptr
<LLVMTargetMachine
> TM
;
81 std::unique_ptr
<Module
> M
;
83 std::unique_ptr
<MachineFunction
> MF
;
84 std::unique_ptr
<SelectionDAG
> DAG
;
87 TEST_F(AArch64SelectionDAGTest
, computeKnownBits_ZERO_EXTEND_VECTOR_INREG
) {
89 auto Int8VT
= EVT::getIntegerVT(Context
, 8);
90 auto Int16VT
= EVT::getIntegerVT(Context
, 16);
91 auto InVecVT
= EVT::getVectorVT(Context
, Int8VT
, 4);
92 auto OutVecVT
= EVT::getVectorVT(Context
, Int16VT
, 2);
93 auto InVec
= DAG
->getConstant(0, Loc
, InVecVT
);
94 auto Op
= DAG
->getNode(ISD::ZERO_EXTEND_VECTOR_INREG
, Loc
, OutVecVT
, InVec
);
95 auto DemandedElts
= APInt(2, 3);
96 KnownBits Known
= DAG
->computeKnownBits(Op
, DemandedElts
);
97 EXPECT_TRUE(Known
.isZero());
100 TEST_F(AArch64SelectionDAGTest
, computeKnownBitsSVE_ZERO_EXTEND_VECTOR_INREG
) {
102 auto Int8VT
= EVT::getIntegerVT(Context
, 8);
103 auto Int16VT
= EVT::getIntegerVT(Context
, 16);
104 auto InVecVT
= EVT::getVectorVT(Context
, Int8VT
, 4, true);
105 auto OutVecVT
= EVT::getVectorVT(Context
, Int16VT
, 2, true);
106 auto InVec
= DAG
->getConstant(0, Loc
, InVecVT
);
107 auto Op
= DAG
->getNode(ISD::ZERO_EXTEND_VECTOR_INREG
, Loc
, OutVecVT
, InVec
);
108 auto DemandedElts
= APInt(2, 3);
109 KnownBits Known
= DAG
->computeKnownBits(Op
, DemandedElts
);
111 // We don't know anything for SVE at the moment.
112 EXPECT_EQ(Known
.Zero
, APInt(16, 0u));
113 EXPECT_EQ(Known
.One
, APInt(16, 0u));
114 EXPECT_FALSE(Known
.isZero());
117 TEST_F(AArch64SelectionDAGTest
, computeKnownBits_EXTRACT_SUBVECTOR
) {
119 auto IntVT
= EVT::getIntegerVT(Context
, 8);
120 auto VecVT
= EVT::getVectorVT(Context
, IntVT
, 3);
121 auto IdxVT
= EVT::getIntegerVT(Context
, 64);
122 auto Vec
= DAG
->getConstant(0, Loc
, VecVT
);
123 auto ZeroIdx
= DAG
->getConstant(0, Loc
, IdxVT
);
124 auto Op
= DAG
->getNode(ISD::EXTRACT_SUBVECTOR
, Loc
, VecVT
, Vec
, ZeroIdx
);
125 auto DemandedElts
= APInt(3, 7);
126 KnownBits Known
= DAG
->computeKnownBits(Op
, DemandedElts
);
127 EXPECT_TRUE(Known
.isZero());
130 TEST_F(AArch64SelectionDAGTest
, ComputeNumSignBits_SIGN_EXTEND_VECTOR_INREG
) {
132 auto Int8VT
= EVT::getIntegerVT(Context
, 8);
133 auto Int16VT
= EVT::getIntegerVT(Context
, 16);
134 auto InVecVT
= EVT::getVectorVT(Context
, Int8VT
, 4);
135 auto OutVecVT
= EVT::getVectorVT(Context
, Int16VT
, 2);
136 auto InVec
= DAG
->getConstant(1, Loc
, InVecVT
);
137 auto Op
= DAG
->getNode(ISD::SIGN_EXTEND_VECTOR_INREG
, Loc
, OutVecVT
, InVec
);
138 auto DemandedElts
= APInt(2, 3);
139 EXPECT_EQ(DAG
->ComputeNumSignBits(Op
, DemandedElts
), 15u);
142 TEST_F(AArch64SelectionDAGTest
, ComputeNumSignBitsSVE_SIGN_EXTEND_VECTOR_INREG
) {
144 auto Int8VT
= EVT::getIntegerVT(Context
, 8);
145 auto Int16VT
= EVT::getIntegerVT(Context
, 16);
146 auto InVecVT
= EVT::getVectorVT(Context
, Int8VT
, 4, /*IsScalable=*/true);
147 auto OutVecVT
= EVT::getVectorVT(Context
, Int16VT
, 2, /*IsScalable=*/true);
148 auto InVec
= DAG
->getConstant(1, Loc
, InVecVT
);
149 auto Op
= DAG
->getNode(ISD::SIGN_EXTEND_VECTOR_INREG
, Loc
, OutVecVT
, InVec
);
150 auto DemandedElts
= APInt(2, 3);
151 EXPECT_EQ(DAG
->ComputeNumSignBits(Op
, DemandedElts
), 1u);
154 TEST_F(AArch64SelectionDAGTest
, ComputeNumSignBits_EXTRACT_SUBVECTOR
) {
156 auto IntVT
= EVT::getIntegerVT(Context
, 8);
157 auto VecVT
= EVT::getVectorVT(Context
, IntVT
, 3);
158 auto IdxVT
= EVT::getIntegerVT(Context
, 64);
159 auto Vec
= DAG
->getConstant(1, Loc
, VecVT
);
160 auto ZeroIdx
= DAG
->getConstant(0, Loc
, IdxVT
);
161 auto Op
= DAG
->getNode(ISD::EXTRACT_SUBVECTOR
, Loc
, VecVT
, Vec
, ZeroIdx
);
162 auto DemandedElts
= APInt(3, 7);
163 EXPECT_EQ(DAG
->ComputeNumSignBits(Op
, DemandedElts
), 7u);
166 TEST_F(AArch64SelectionDAGTest
, SimplifyDemandedVectorElts_EXTRACT_SUBVECTOR
) {
167 TargetLowering
TL(*TM
);
170 auto IntVT
= EVT::getIntegerVT(Context
, 8);
171 auto VecVT
= EVT::getVectorVT(Context
, IntVT
, 3);
172 auto IdxVT
= EVT::getIntegerVT(Context
, 64);
173 auto Vec
= DAG
->getConstant(1, Loc
, VecVT
);
174 auto ZeroIdx
= DAG
->getConstant(0, Loc
, IdxVT
);
175 auto Op
= DAG
->getNode(ISD::EXTRACT_SUBVECTOR
, Loc
, VecVT
, Vec
, ZeroIdx
);
176 auto DemandedElts
= APInt(3, 7);
177 auto KnownUndef
= APInt(3, 0);
178 auto KnownZero
= APInt(3, 0);
179 TargetLowering::TargetLoweringOpt
TLO(*DAG
, false, false);
180 EXPECT_EQ(TL
.SimplifyDemandedVectorElts(Op
, DemandedElts
, KnownUndef
,
185 TEST_F(AArch64SelectionDAGTest
, SimplifyDemandedBitsNEON
) {
186 TargetLowering
TL(*TM
);
189 auto Int8VT
= EVT::getIntegerVT(Context
, 8);
190 auto InVecVT
= EVT::getVectorVT(Context
, Int8VT
, 16);
191 SDValue UnknownOp
= DAG
->getRegister(0, InVecVT
);
192 SDValue Mask1S
= DAG
->getConstant(0x8A, Loc
, Int8VT
);
193 SDValue Mask1V
= DAG
->getSplatBuildVector(InVecVT
, Loc
, Mask1S
);
194 SDValue N0
= DAG
->getNode(ISD::AND
, Loc
, InVecVT
, Mask1V
, UnknownOp
);
196 SDValue Mask2S
= DAG
->getConstant(0x55, Loc
, Int8VT
);
197 SDValue Mask2V
= DAG
->getSplatBuildVector(InVecVT
, Loc
, Mask2S
);
199 SDValue Op
= DAG
->getNode(ISD::AND
, Loc
, InVecVT
, N0
, Mask2V
);
203 // Known.Zero = 00100000 (0xAA)
205 APInt DemandedBits
= APInt(8, 0xFF);
206 TargetLowering::TargetLoweringOpt
TLO(*DAG
, false, false);
207 EXPECT_TRUE(TL
.SimplifyDemandedBits(Op
, DemandedBits
, Known
, TLO
));
208 EXPECT_EQ(Known
.Zero
, APInt(8, 0xAA));
211 TEST_F(AArch64SelectionDAGTest
, SimplifyDemandedBitsSVE
) {
212 TargetLowering
TL(*TM
);
215 auto Int8VT
= EVT::getIntegerVT(Context
, 8);
216 auto InVecVT
= EVT::getVectorVT(Context
, Int8VT
, 16, /*IsScalable=*/true);
217 SDValue UnknownOp
= DAG
->getRegister(0, InVecVT
);
218 SDValue Mask1S
= DAG
->getConstant(0x8A, Loc
, Int8VT
);
219 SDValue Mask1V
= DAG
->getSplatVector(InVecVT
, Loc
, Mask1S
);
220 SDValue N0
= DAG
->getNode(ISD::AND
, Loc
, InVecVT
, Mask1V
, UnknownOp
);
222 SDValue Mask2S
= DAG
->getConstant(0x55, Loc
, Int8VT
);
223 SDValue Mask2V
= DAG
->getSplatVector(InVecVT
, Loc
, Mask2S
);
225 SDValue Op
= DAG
->getNode(ISD::AND
, Loc
, InVecVT
, N0
, Mask2V
);
230 // Known.Zero = 00100000 (0xAA)
232 APInt DemandedBits
= APInt(8, 0xFF);
233 TargetLowering::TargetLoweringOpt
TLO(*DAG
, false, false);
234 EXPECT_TRUE(TL
.SimplifyDemandedBits(Op
, DemandedBits
, Known
, TLO
));
235 EXPECT_EQ(Known
.Zero
, APInt(8, 0xAA));
238 // Piggy-backing on the AArch64 tests to verify SelectionDAG::computeKnownBits.
239 TEST_F(AArch64SelectionDAGTest
, ComputeKnownBits_ADD
) {
241 auto IntVT
= EVT::getIntegerVT(Context
, 8);
242 auto UnknownOp
= DAG
->getRegister(0, IntVT
);
243 auto Mask
= DAG
->getConstant(0x8A, Loc
, IntVT
);
244 auto N0
= DAG
->getNode(ISD::AND
, Loc
, IntVT
, Mask
, UnknownOp
);
245 auto N1
= DAG
->getConstant(0x55, Loc
, IntVT
);
246 auto Op
= DAG
->getNode(ISD::ADD
, Loc
, IntVT
, N0
, N1
);
250 // Known.One = 01010101 (0x55)
251 // Known.Zero = 00100000 (0x20)
252 KnownBits Known
= DAG
->computeKnownBits(Op
);
253 EXPECT_EQ(Known
.Zero
, APInt(8, 0x20));
254 EXPECT_EQ(Known
.One
, APInt(8, 0x55));
257 // Piggy-backing on the AArch64 tests to verify SelectionDAG::computeKnownBits.
258 TEST_F(AArch64SelectionDAGTest
, ComputeKnownBits_UADDO_CARRY
) {
260 auto IntVT
= EVT::getIntegerVT(Context
, 8);
261 auto UnknownOp
= DAG
->getRegister(0, IntVT
);
262 auto Mask_Zero
= DAG
->getConstant(0x28, Loc
, IntVT
);
263 auto Mask_One
= DAG
->getConstant(0x20, Loc
, IntVT
);
264 auto N0
= DAG
->getNode(ISD::AND
, Loc
, IntVT
, Mask_Zero
, UnknownOp
);
265 N0
= DAG
->getNode(ISD::OR
, Loc
, IntVT
, Mask_One
, N0
);
266 auto N1
= DAG
->getConstant(0x65, Loc
, IntVT
);
270 auto UnknownBorrow
= DAG
->getRegister(1, IntVT
);
271 auto OpUnknownBorrow
=
272 DAG
->getNode(ISD::UADDO_CARRY
, Loc
, IntVT
, N0
, N1
, UnknownBorrow
);
277 // Known.Zero = 01110000 (0x70)
278 // Known.One = 10000100 (0x84)
279 Known
= DAG
->computeKnownBits(OpUnknownBorrow
);
280 EXPECT_EQ(Known
.Zero
, APInt(8, 0x70));
281 EXPECT_EQ(Known
.One
, APInt(8, 0x84));
283 auto ZeroBorrow
= DAG
->getConstant(0x0, Loc
, IntVT
);
285 DAG
->getNode(ISD::UADDO_CARRY
, Loc
, IntVT
, N0
, N1
, ZeroBorrow
);
290 // Known.Zero = 01110010 (0x72)
291 // Known.One = 10000101 (0x85)
292 Known
= DAG
->computeKnownBits(OpZeroBorrow
);
293 EXPECT_EQ(Known
.Zero
, APInt(8, 0x72));
294 EXPECT_EQ(Known
.One
, APInt(8, 0x85));
296 auto OneBorrow
= DAG
->getConstant(0x1, Loc
, IntVT
);
298 DAG
->getNode(ISD::UADDO_CARRY
, Loc
, IntVT
, N0
, N1
, OneBorrow
);
303 // Known.Zero = 01110001 (0x71)
304 // Known.One = 10000110 (0x86)
305 Known
= DAG
->computeKnownBits(OpOneBorrow
);
306 EXPECT_EQ(Known
.Zero
, APInt(8, 0x71));
307 EXPECT_EQ(Known
.One
, APInt(8, 0x86));
310 // Piggy-backing on the AArch64 tests to verify SelectionDAG::computeKnownBits.
311 TEST_F(AArch64SelectionDAGTest
, ComputeKnownBits_SUB
) {
313 auto IntVT
= EVT::getIntegerVT(Context
, 8);
314 auto N0
= DAG
->getConstant(0x55, Loc
, IntVT
);
315 auto UnknownOp
= DAG
->getRegister(0, IntVT
);
316 auto Mask
= DAG
->getConstant(0x2e, Loc
, IntVT
);
317 auto N1
= DAG
->getNode(ISD::AND
, Loc
, IntVT
, Mask
, UnknownOp
);
318 auto Op
= DAG
->getNode(ISD::SUB
, Loc
, IntVT
, N0
, N1
);
322 // Known.One = 00000001 (0x1)
323 // Known.Zero = 10000000 (0x80)
324 KnownBits Known
= DAG
->computeKnownBits(Op
);
325 EXPECT_EQ(Known
.Zero
, APInt(8, 0x80));
326 EXPECT_EQ(Known
.One
, APInt(8, 0x1));
329 // Piggy-backing on the AArch64 tests to verify SelectionDAG::computeKnownBits.
330 TEST_F(AArch64SelectionDAGTest
, ComputeKnownBits_USUBO_CARRY
) {
332 auto IntVT
= EVT::getIntegerVT(Context
, 8);
333 auto N0
= DAG
->getConstant(0x5a, Loc
, IntVT
);
334 auto UnknownOp
= DAG
->getRegister(0, IntVT
); // ????????
335 auto Mask1_Zero
= DAG
->getConstant(0x8, Loc
, IntVT
); // 00001000
336 auto Mask1_One
= DAG
->getConstant(0x20, Loc
, IntVT
); // 00100000
337 // N1 = (???????? & 00001000) | 00100000 = 0010?000
338 auto N1
= DAG
->getNode(ISD::AND
, Loc
, IntVT
, Mask1_Zero
, UnknownOp
);
339 N1
= DAG
->getNode(ISD::OR
, Loc
, IntVT
, Mask1_One
, N1
);
343 auto UnknownBorrow
= DAG
->getRegister(1, IntVT
);
344 auto OpUnknownBorrow
=
345 DAG
->getNode(ISD::USUBO_CARRY
, Loc
, IntVT
, N0
, N1
, UnknownBorrow
);
350 // Known.Zero = 11000100 (0xc4)
351 // Known.One = 00110000 (0x30)
352 Known
= DAG
->computeKnownBits(OpUnknownBorrow
);
353 EXPECT_EQ(Known
.Zero
, APInt(8, 0xc4));
354 EXPECT_EQ(Known
.One
, APInt(8, 0x30));
356 auto ZeroBorrow
= DAG
->getConstant(0x0, Loc
, IntVT
);
358 DAG
->getNode(ISD::USUBO_CARRY
, Loc
, IntVT
, N0
, N1
, ZeroBorrow
);
363 // Known.Zero = 11000101 (0xc5)
364 // Known.One = 00110010 (0x32)
365 Known
= DAG
->computeKnownBits(OpZeroBorrow
);
366 EXPECT_EQ(Known
.Zero
, APInt(8, 0xc5));
367 EXPECT_EQ(Known
.One
, APInt(8, 0x32));
369 auto OneBorrow
= DAG
->getConstant(0x1, Loc
, IntVT
);
371 DAG
->getNode(ISD::USUBO_CARRY
, Loc
, IntVT
, N0
, N1
, OneBorrow
);
376 // Known.Zero = 11000110 (0xc6)
377 // Known.One = 00110001 (0x31)
378 Known
= DAG
->computeKnownBits(OpOneBorrow
);
379 EXPECT_EQ(Known
.Zero
, APInt(8, 0xc6));
380 EXPECT_EQ(Known
.One
, APInt(8, 0x31));
383 TEST_F(AArch64SelectionDAGTest
, isSplatValue_Fixed_BUILD_VECTOR
) {
384 TargetLowering
TL(*TM
);
387 auto IntVT
= EVT::getIntegerVT(Context
, 8);
388 auto VecVT
= EVT::getVectorVT(Context
, IntVT
, 16, false);
389 // Create a BUILD_VECTOR
390 SDValue Op
= DAG
->getConstant(1, Loc
, VecVT
);
391 EXPECT_EQ(Op
->getOpcode(), ISD::BUILD_VECTOR
);
392 EXPECT_TRUE(DAG
->isSplatValue(Op
, /*AllowUndefs=*/false));
396 EXPECT_FALSE(DAG
->isSplatValue(Op
, DemandedElts
, UndefElts
));
399 DemandedElts
= APInt(16, 3);
400 EXPECT_TRUE(DAG
->isSplatValue(Op
, DemandedElts
, UndefElts
));
403 TEST_F(AArch64SelectionDAGTest
, isSplatValue_Fixed_ADD_of_BUILD_VECTOR
) {
404 TargetLowering
TL(*TM
);
407 auto IntVT
= EVT::getIntegerVT(Context
, 8);
408 auto VecVT
= EVT::getVectorVT(Context
, IntVT
, 16, false);
410 // Should create BUILD_VECTORs
411 SDValue Val1
= DAG
->getConstant(1, Loc
, VecVT
);
412 SDValue Val2
= DAG
->getConstant(3, Loc
, VecVT
);
413 EXPECT_EQ(Val1
->getOpcode(), ISD::BUILD_VECTOR
);
414 SDValue Op
= DAG
->getNode(ISD::ADD
, Loc
, VecVT
, Val1
, Val2
);
416 EXPECT_TRUE(DAG
->isSplatValue(Op
, /*AllowUndefs=*/false));
420 EXPECT_FALSE(DAG
->isSplatValue(Op
, DemandedElts
, UndefElts
));
423 DemandedElts
= APInt(16, 3);
424 EXPECT_TRUE(DAG
->isSplatValue(Op
, DemandedElts
, UndefElts
));
427 TEST_F(AArch64SelectionDAGTest
, isSplatValue_Scalable_SPLAT_VECTOR
) {
428 TargetLowering
TL(*TM
);
431 auto IntVT
= EVT::getIntegerVT(Context
, 8);
432 auto VecVT
= EVT::getVectorVT(Context
, IntVT
, 16, true);
433 // Create a SPLAT_VECTOR
434 SDValue Op
= DAG
->getConstant(1, Loc
, VecVT
);
435 EXPECT_EQ(Op
->getOpcode(), ISD::SPLAT_VECTOR
);
436 EXPECT_TRUE(DAG
->isSplatValue(Op
, /*AllowUndefs=*/false));
439 APInt
DemandedElts(1,1);
440 EXPECT_TRUE(DAG
->isSplatValue(Op
, DemandedElts
, UndefElts
));
443 TEST_F(AArch64SelectionDAGTest
, isSplatValue_Scalable_ADD_of_SPLAT_VECTOR
) {
444 TargetLowering
TL(*TM
);
447 auto IntVT
= EVT::getIntegerVT(Context
, 8);
448 auto VecVT
= EVT::getVectorVT(Context
, IntVT
, 16, true);
450 // Should create SPLAT_VECTORS
451 SDValue Val1
= DAG
->getConstant(1, Loc
, VecVT
);
452 SDValue Val2
= DAG
->getConstant(3, Loc
, VecVT
);
453 EXPECT_EQ(Val1
->getOpcode(), ISD::SPLAT_VECTOR
);
454 SDValue Op
= DAG
->getNode(ISD::ADD
, Loc
, VecVT
, Val1
, Val2
);
456 EXPECT_TRUE(DAG
->isSplatValue(Op
, /*AllowUndefs=*/false));
459 APInt
DemandedElts(1, 1);
460 EXPECT_TRUE(DAG
->isSplatValue(Op
, DemandedElts
, UndefElts
));
463 TEST_F(AArch64SelectionDAGTest
, getSplatSourceVector_Fixed_BUILD_VECTOR
) {
464 TargetLowering
TL(*TM
);
467 auto IntVT
= EVT::getIntegerVT(Context
, 8);
468 auto VecVT
= EVT::getVectorVT(Context
, IntVT
, 16, false);
469 // Create a BUILD_VECTOR
470 SDValue Op
= DAG
->getConstant(1, Loc
, VecVT
);
471 EXPECT_EQ(Op
->getOpcode(), ISD::BUILD_VECTOR
);
474 EXPECT_EQ(DAG
->getSplatSourceVector(Op
, SplatIdx
), Op
);
475 EXPECT_EQ(SplatIdx
, 0);
478 TEST_F(AArch64SelectionDAGTest
, getSplatSourceVector_Fixed_ADD_of_BUILD_VECTOR
) {
479 TargetLowering
TL(*TM
);
482 auto IntVT
= EVT::getIntegerVT(Context
, 8);
483 auto VecVT
= EVT::getVectorVT(Context
, IntVT
, 16, false);
485 // Should create BUILD_VECTORs
486 SDValue Val1
= DAG
->getConstant(1, Loc
, VecVT
);
487 SDValue Val2
= DAG
->getConstant(3, Loc
, VecVT
);
488 EXPECT_EQ(Val1
->getOpcode(), ISD::BUILD_VECTOR
);
489 SDValue Op
= DAG
->getNode(ISD::ADD
, Loc
, VecVT
, Val1
, Val2
);
492 EXPECT_EQ(DAG
->getSplatSourceVector(Op
, SplatIdx
), Op
);
493 EXPECT_EQ(SplatIdx
, 0);
496 TEST_F(AArch64SelectionDAGTest
, getSplatSourceVector_Scalable_SPLAT_VECTOR
) {
497 TargetLowering
TL(*TM
);
500 auto IntVT
= EVT::getIntegerVT(Context
, 8);
501 auto VecVT
= EVT::getVectorVT(Context
, IntVT
, 16, true);
502 // Create a SPLAT_VECTOR
503 SDValue Op
= DAG
->getConstant(1, Loc
, VecVT
);
504 EXPECT_EQ(Op
->getOpcode(), ISD::SPLAT_VECTOR
);
507 EXPECT_EQ(DAG
->getSplatSourceVector(Op
, SplatIdx
), Op
);
508 EXPECT_EQ(SplatIdx
, 0);
511 TEST_F(AArch64SelectionDAGTest
, getSplatSourceVector_Scalable_ADD_of_SPLAT_VECTOR
) {
512 TargetLowering
TL(*TM
);
515 auto IntVT
= EVT::getIntegerVT(Context
, 8);
516 auto VecVT
= EVT::getVectorVT(Context
, IntVT
, 16, true);
518 // Should create SPLAT_VECTORS
519 SDValue Val1
= DAG
->getConstant(1, Loc
, VecVT
);
520 SDValue Val2
= DAG
->getConstant(3, Loc
, VecVT
);
521 EXPECT_EQ(Val1
->getOpcode(), ISD::SPLAT_VECTOR
);
522 SDValue Op
= DAG
->getNode(ISD::ADD
, Loc
, VecVT
, Val1
, Val2
);
525 EXPECT_EQ(DAG
->getSplatSourceVector(Op
, SplatIdx
), Op
);
526 EXPECT_EQ(SplatIdx
, 0);
529 TEST_F(AArch64SelectionDAGTest
, getRepeatedSequence_Patterns
) {
530 TargetLowering
TL(*TM
);
533 unsigned NumElts
= 16;
535 MVT VecVT
= MVT::getVectorVT(IntVT
, NumElts
);
537 // Base scalar constants.
538 SDValue Val0
= DAG
->getConstant(0, Loc
, IntVT
);
539 SDValue Val1
= DAG
->getConstant(1, Loc
, IntVT
);
540 SDValue Val2
= DAG
->getConstant(2, Loc
, IntVT
);
541 SDValue Val3
= DAG
->getConstant(3, Loc
, IntVT
);
542 SDValue UndefVal
= DAG
->getUNDEF(IntVT
);
544 // Build some repeating sequences.
545 SmallVector
<SDValue
, 16> Pattern1111
, Pattern1133
, Pattern0123
;
546 for(int I
= 0; I
!= 4; ++I
) {
547 Pattern1111
.append(4, Val1
);
548 Pattern1133
.append(2, Val1
);
549 Pattern1133
.append(2, Val3
);
550 Pattern0123
.push_back(Val0
);
551 Pattern0123
.push_back(Val1
);
552 Pattern0123
.push_back(Val2
);
553 Pattern0123
.push_back(Val3
);
556 // Build a non-pow2 repeating sequence.
557 SmallVector
<SDValue
, 16> Pattern022
;
558 Pattern022
.push_back(Val0
);
559 Pattern022
.append(2, Val2
);
560 Pattern022
.push_back(Val0
);
561 Pattern022
.append(2, Val2
);
562 Pattern022
.push_back(Val0
);
563 Pattern022
.append(2, Val2
);
564 Pattern022
.push_back(Val0
);
565 Pattern022
.append(2, Val2
);
566 Pattern022
.push_back(Val0
);
567 Pattern022
.append(2, Val2
);
568 Pattern022
.push_back(Val0
);
570 // Build a non-repeating sequence.
571 SmallVector
<SDValue
, 16> Pattern1_3
;
572 Pattern1_3
.append(8, Val1
);
573 Pattern1_3
.append(8, Val3
);
575 // Add some undefs to make it trickier.
576 Pattern1111
[1] = Pattern1111
[2] = Pattern1111
[15] = UndefVal
;
577 Pattern1133
[0] = Pattern1133
[2] = UndefVal
;
580 cast
<BuildVectorSDNode
>(DAG
->getBuildVector(VecVT
, Loc
, Pattern1111
));
582 cast
<BuildVectorSDNode
>(DAG
->getBuildVector(VecVT
, Loc
, Pattern1133
));
584 cast
<BuildVectorSDNode
>(DAG
->getBuildVector(VecVT
, Loc
, Pattern0123
));
586 cast
<BuildVectorSDNode
>(DAG
->getBuildVector(VecVT
, Loc
, Pattern022
));
588 cast
<BuildVectorSDNode
>(DAG
->getBuildVector(VecVT
, Loc
, Pattern1_3
));
590 // Check for sequences.
591 SmallVector
<SDValue
, 16> Seq1111
, Seq1133
, Seq0123
, Seq022
, Seq1_3
;
592 BitVector Undefs1111
, Undefs1133
, Undefs0123
, Undefs022
, Undefs1_3
;
594 EXPECT_TRUE(BV1111
->getRepeatedSequence(Seq1111
, &Undefs1111
));
595 EXPECT_EQ(Undefs1111
.count(), 3u);
596 EXPECT_EQ(Seq1111
.size(), 1u);
597 EXPECT_EQ(Seq1111
[0], Val1
);
599 EXPECT_TRUE(BV1133
->getRepeatedSequence(Seq1133
, &Undefs1133
));
600 EXPECT_EQ(Undefs1133
.count(), 2u);
601 EXPECT_EQ(Seq1133
.size(), 4u);
602 EXPECT_EQ(Seq1133
[0], Val1
);
603 EXPECT_EQ(Seq1133
[1], Val1
);
604 EXPECT_EQ(Seq1133
[2], Val3
);
605 EXPECT_EQ(Seq1133
[3], Val3
);
607 EXPECT_TRUE(BV0123
->getRepeatedSequence(Seq0123
, &Undefs0123
));
608 EXPECT_EQ(Undefs0123
.count(), 0u);
609 EXPECT_EQ(Seq0123
.size(), 4u);
610 EXPECT_EQ(Seq0123
[0], Val0
);
611 EXPECT_EQ(Seq0123
[1], Val1
);
612 EXPECT_EQ(Seq0123
[2], Val2
);
613 EXPECT_EQ(Seq0123
[3], Val3
);
615 EXPECT_FALSE(BV022
->getRepeatedSequence(Seq022
, &Undefs022
));
616 EXPECT_FALSE(BV1_3
->getRepeatedSequence(Seq1_3
, &Undefs1_3
));
618 // Try again with DemandedElts masks.
619 APInt Mask1111_0
= APInt::getOneBitSet(NumElts
, 0);
620 EXPECT_TRUE(BV1111
->getRepeatedSequence(Mask1111_0
, Seq1111
, &Undefs1111
));
621 EXPECT_EQ(Undefs1111
.count(), 0u);
622 EXPECT_EQ(Seq1111
.size(), 1u);
623 EXPECT_EQ(Seq1111
[0], Val1
);
625 APInt Mask1111_1
= APInt::getOneBitSet(NumElts
, 2);
626 EXPECT_TRUE(BV1111
->getRepeatedSequence(Mask1111_1
, Seq1111
, &Undefs1111
));
627 EXPECT_EQ(Undefs1111
.count(), 1u);
628 EXPECT_EQ(Seq1111
.size(), 1u);
629 EXPECT_EQ(Seq1111
[0], UndefVal
);
631 APInt Mask0123
= APInt(NumElts
, 0x7777);
632 EXPECT_TRUE(BV0123
->getRepeatedSequence(Mask0123
, Seq0123
, &Undefs0123
));
633 EXPECT_EQ(Undefs0123
.count(), 0u);
634 EXPECT_EQ(Seq0123
.size(), 4u);
635 EXPECT_EQ(Seq0123
[0], Val0
);
636 EXPECT_EQ(Seq0123
[1], Val1
);
637 EXPECT_EQ(Seq0123
[2], Val2
);
638 EXPECT_EQ(Seq0123
[3], SDValue());
640 APInt Mask1_3
= APInt::getHighBitsSet(16, 8);
641 EXPECT_TRUE(BV1_3
->getRepeatedSequence(Mask1_3
, Seq1_3
, &Undefs1_3
));
642 EXPECT_EQ(Undefs1_3
.count(), 0u);
643 EXPECT_EQ(Seq1_3
.size(), 1u);
644 EXPECT_EQ(Seq1_3
[0], Val3
);
647 TEST_F(AArch64SelectionDAGTest
, getTypeConversion_SplitScalableMVT
) {
648 MVT VT
= MVT::nxv4i64
;
649 EXPECT_EQ(getTypeAction(VT
), TargetLoweringBase::TypeSplitVector
);
650 ASSERT_TRUE(getTypeToTransformTo(VT
).isScalableVector());
653 TEST_F(AArch64SelectionDAGTest
, getTypeConversion_PromoteScalableMVT
) {
654 MVT VT
= MVT::nxv2i32
;
655 EXPECT_EQ(getTypeAction(VT
), TargetLoweringBase::TypePromoteInteger
);
656 ASSERT_TRUE(getTypeToTransformTo(VT
).isScalableVector());
659 TEST_F(AArch64SelectionDAGTest
, getTypeConversion_NoScalarizeMVT_nxv1f32
) {
660 MVT VT
= MVT::nxv1f32
;
661 EXPECT_NE(getTypeAction(VT
), TargetLoweringBase::TypeScalarizeVector
);
662 ASSERT_TRUE(getTypeToTransformTo(VT
).isScalableVector());
665 TEST_F(AArch64SelectionDAGTest
, getTypeConversion_SplitScalableEVT
) {
666 EVT VT
= EVT::getVectorVT(Context
, MVT::i64
, 256, true);
667 EXPECT_EQ(getTypeAction(VT
), TargetLoweringBase::TypeSplitVector
);
668 EXPECT_EQ(getTypeToTransformTo(VT
), VT
.getHalfNumVectorElementsVT(Context
));
671 TEST_F(AArch64SelectionDAGTest
, getTypeConversion_WidenScalableEVT
) {
672 EVT FromVT
= EVT::getVectorVT(Context
, MVT::i64
, 6, true);
673 EVT ToVT
= EVT::getVectorVT(Context
, MVT::i64
, 8, true);
675 EXPECT_EQ(getTypeAction(FromVT
), TargetLoweringBase::TypeWidenVector
);
676 EXPECT_EQ(getTypeToTransformTo(FromVT
), ToVT
);
679 TEST_F(AArch64SelectionDAGTest
,
680 getTypeConversion_ScalarizeScalableEVT_nxv1f128
) {
681 EVT VT
= EVT::getVectorVT(Context
, MVT::f128
, ElementCount::getScalable(1));
682 EXPECT_EQ(getTypeAction(VT
), TargetLoweringBase::TypeScalarizeScalableVector
);
683 EXPECT_EQ(getTypeToTransformTo(VT
), MVT::f128
);
686 TEST_F(AArch64SelectionDAGTest
, TestFold_STEP_VECTOR
) {
688 auto IntVT
= EVT::getIntegerVT(Context
, 8);
689 auto VecVT
= EVT::getVectorVT(Context
, MVT::i8
, 16, true);
691 // Should create SPLAT_VECTOR
692 SDValue Zero
= DAG
->getConstant(0, Loc
, IntVT
);
693 SDValue Op
= DAG
->getNode(ISD::STEP_VECTOR
, Loc
, VecVT
, Zero
);
694 EXPECT_EQ(Op
.getOpcode(), ISD::SPLAT_VECTOR
);
697 TEST_F(AArch64SelectionDAGTest
, ReplaceAllUsesWith
) {
699 EVT IntVT
= EVT::getIntegerVT(Context
, 8);
701 SDValue N0
= DAG
->getConstant(0x42, Loc
, IntVT
);
702 SDValue N1
= DAG
->getRegister(0, IntVT
);
703 // Construct node to fill arbitrary ExtraInfo.
704 SDValue N2
= DAG
->getNode(ISD::SUB
, Loc
, IntVT
, N0
, N1
);
705 EXPECT_FALSE(DAG
->getHeapAllocSite(N2
.getNode()));
706 EXPECT_FALSE(DAG
->getNoMergeSiteInfo(N2
.getNode()));
707 EXPECT_FALSE(DAG
->getPCSections(N2
.getNode()));
708 MDNode
*MD
= MDNode::get(Context
, std::nullopt
);
709 DAG
->addHeapAllocSite(N2
.getNode(), MD
);
710 DAG
->addNoMergeSiteInfo(N2
.getNode(), true);
711 DAG
->addPCSections(N2
.getNode(), MD
);
712 EXPECT_EQ(DAG
->getHeapAllocSite(N2
.getNode()), MD
);
713 EXPECT_TRUE(DAG
->getNoMergeSiteInfo(N2
.getNode()));
714 EXPECT_EQ(DAG
->getPCSections(N2
.getNode()), MD
);
716 SDValue Root
= DAG
->getNode(ISD::ADD
, Loc
, IntVT
, N2
, N2
);
717 EXPECT_EQ(Root
->getOperand(0)->getOpcode(), ISD::SUB
);
718 // Create new node and check that ExtraInfo is propagated on RAUW.
719 SDValue New
= DAG
->getNode(ISD::ADD
, Loc
, IntVT
, N1
, N1
);
720 EXPECT_FALSE(DAG
->getHeapAllocSite(New
.getNode()));
721 EXPECT_FALSE(DAG
->getNoMergeSiteInfo(New
.getNode()));
722 EXPECT_FALSE(DAG
->getPCSections(New
.getNode()));
724 DAG
->ReplaceAllUsesWith(N2
, New
);
725 EXPECT_EQ(Root
->getOperand(0), New
);
726 EXPECT_EQ(DAG
->getHeapAllocSite(New
.getNode()), MD
);
727 EXPECT_TRUE(DAG
->getNoMergeSiteInfo(New
.getNode()));
728 EXPECT_EQ(DAG
->getPCSections(New
.getNode()), MD
);
731 } // end namespace llvm