Files
clang-p2996/llvm/unittests/CodeGen/AArch64SelectionDAGTest.cpp
Philip Reames 186c192261 [SDAG] Allow scalable vectors in SimplifyDemanded routines
This is a continuation of the series of patches adding lane wise support for scalable vectors in various knownbit-esq routines.

The basic idea here is that we track a single lane for scalable vectors which corresponds to an unknown number of lanes at runtime. This is enough for us to perform lane wise reasoning on many arithmetic operations.

Differential Revision: https://reviews.llvm.org/D137190
2022-12-05 12:42:16 -08:00

625 lines
22 KiB
C++

//===- llvm/unittest/CodeGen/AArch64SelectionDAGTest.cpp -------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
#include "llvm/AsmParser/Parser.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/KnownBits.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Target/TargetMachine.h"
#include "gtest/gtest.h"
namespace llvm {
class AArch64SelectionDAGTest : public testing::Test {
protected:
static void SetUpTestCase() {
InitializeAllTargets();
InitializeAllTargetMCs();
}
void SetUp() override {
StringRef Assembly = "define void @f() { ret void }";
Triple TargetTriple("aarch64--");
std::string Error;
const Target *T = TargetRegistry::lookupTarget("", TargetTriple, Error);
// FIXME: These tests do not depend on AArch64 specifically, but we have to
// initialize a target. A skeleton Target for unittests would allow us to
// always run these tests.
if (!T)
GTEST_SKIP();
TargetOptions Options;
TM = std::unique_ptr<LLVMTargetMachine>(static_cast<LLVMTargetMachine *>(
T->createTargetMachine("AArch64", "", "+sve", Options, std::nullopt,
std::nullopt, CodeGenOpt::Aggressive)));
if (!TM)
GTEST_SKIP();
SMDiagnostic SMError;
M = parseAssemblyString(Assembly, SMError, Context);
if (!M)
report_fatal_error(SMError.getMessage());
M->setDataLayout(TM->createDataLayout());
F = M->getFunction("f");
if (!F)
report_fatal_error("F?");
MachineModuleInfo MMI(TM.get());
MF = std::make_unique<MachineFunction>(*F, *TM, *TM->getSubtargetImpl(*F), 0,
MMI);
DAG = std::make_unique<SelectionDAG>(*TM, CodeGenOpt::None);
if (!DAG)
report_fatal_error("DAG?");
OptimizationRemarkEmitter ORE(F);
DAG->init(*MF, ORE, nullptr, nullptr, nullptr, nullptr, nullptr);
}
TargetLoweringBase::LegalizeTypeAction getTypeAction(EVT VT) {
return DAG->getTargetLoweringInfo().getTypeAction(Context, VT);
}
EVT getTypeToTransformTo(EVT VT) {
return DAG->getTargetLoweringInfo().getTypeToTransformTo(Context, VT);
}
LLVMContext Context;
std::unique_ptr<LLVMTargetMachine> TM;
std::unique_ptr<Module> M;
Function *F;
std::unique_ptr<MachineFunction> MF;
std::unique_ptr<SelectionDAG> DAG;
};
TEST_F(AArch64SelectionDAGTest, computeKnownBits_ZERO_EXTEND_VECTOR_INREG) {
SDLoc Loc;
auto Int8VT = EVT::getIntegerVT(Context, 8);
auto Int16VT = EVT::getIntegerVT(Context, 16);
auto InVecVT = EVT::getVectorVT(Context, Int8VT, 4);
auto OutVecVT = EVT::getVectorVT(Context, Int16VT, 2);
auto InVec = DAG->getConstant(0, Loc, InVecVT);
auto Op = DAG->getNode(ISD::ZERO_EXTEND_VECTOR_INREG, Loc, OutVecVT, InVec);
auto DemandedElts = APInt(2, 3);
KnownBits Known = DAG->computeKnownBits(Op, DemandedElts);
EXPECT_TRUE(Known.isZero());
}
TEST_F(AArch64SelectionDAGTest, computeKnownBitsSVE_ZERO_EXTEND_VECTOR_INREG) {
SDLoc Loc;
auto Int8VT = EVT::getIntegerVT(Context, 8);
auto Int16VT = EVT::getIntegerVT(Context, 16);
auto InVecVT = EVT::getVectorVT(Context, Int8VT, 4, true);
auto OutVecVT = EVT::getVectorVT(Context, Int16VT, 2, true);
auto InVec = DAG->getConstant(0, Loc, InVecVT);
auto Op = DAG->getNode(ISD::ZERO_EXTEND_VECTOR_INREG, Loc, OutVecVT, InVec);
auto DemandedElts = APInt(2, 3);
KnownBits Known = DAG->computeKnownBits(Op, DemandedElts);
// We don't know anything for SVE at the moment.
EXPECT_EQ(Known.Zero, APInt(16, 0u));
EXPECT_EQ(Known.One, APInt(16, 0u));
EXPECT_FALSE(Known.isZero());
}
TEST_F(AArch64SelectionDAGTest, computeKnownBits_EXTRACT_SUBVECTOR) {
SDLoc Loc;
auto IntVT = EVT::getIntegerVT(Context, 8);
auto VecVT = EVT::getVectorVT(Context, IntVT, 3);
auto IdxVT = EVT::getIntegerVT(Context, 64);
auto Vec = DAG->getConstant(0, Loc, VecVT);
auto ZeroIdx = DAG->getConstant(0, Loc, IdxVT);
auto Op = DAG->getNode(ISD::EXTRACT_SUBVECTOR, Loc, VecVT, Vec, ZeroIdx);
auto DemandedElts = APInt(3, 7);
KnownBits Known = DAG->computeKnownBits(Op, DemandedElts);
EXPECT_TRUE(Known.isZero());
}
TEST_F(AArch64SelectionDAGTest, ComputeNumSignBits_SIGN_EXTEND_VECTOR_INREG) {
SDLoc Loc;
auto Int8VT = EVT::getIntegerVT(Context, 8);
auto Int16VT = EVT::getIntegerVT(Context, 16);
auto InVecVT = EVT::getVectorVT(Context, Int8VT, 4);
auto OutVecVT = EVT::getVectorVT(Context, Int16VT, 2);
auto InVec = DAG->getConstant(1, Loc, InVecVT);
auto Op = DAG->getNode(ISD::SIGN_EXTEND_VECTOR_INREG, Loc, OutVecVT, InVec);
auto DemandedElts = APInt(2, 3);
EXPECT_EQ(DAG->ComputeNumSignBits(Op, DemandedElts), 15u);
}
TEST_F(AArch64SelectionDAGTest, ComputeNumSignBitsSVE_SIGN_EXTEND_VECTOR_INREG) {
SDLoc Loc;
auto Int8VT = EVT::getIntegerVT(Context, 8);
auto Int16VT = EVT::getIntegerVT(Context, 16);
auto InVecVT = EVT::getVectorVT(Context, Int8VT, 4, /*IsScalable=*/true);
auto OutVecVT = EVT::getVectorVT(Context, Int16VT, 2, /*IsScalable=*/true);
auto InVec = DAG->getConstant(1, Loc, InVecVT);
auto Op = DAG->getNode(ISD::SIGN_EXTEND_VECTOR_INREG, Loc, OutVecVT, InVec);
auto DemandedElts = APInt(2, 3);
EXPECT_EQ(DAG->ComputeNumSignBits(Op, DemandedElts), 1u);
}
TEST_F(AArch64SelectionDAGTest, ComputeNumSignBits_EXTRACT_SUBVECTOR) {
SDLoc Loc;
auto IntVT = EVT::getIntegerVT(Context, 8);
auto VecVT = EVT::getVectorVT(Context, IntVT, 3);
auto IdxVT = EVT::getIntegerVT(Context, 64);
auto Vec = DAG->getConstant(1, Loc, VecVT);
auto ZeroIdx = DAG->getConstant(0, Loc, IdxVT);
auto Op = DAG->getNode(ISD::EXTRACT_SUBVECTOR, Loc, VecVT, Vec, ZeroIdx);
auto DemandedElts = APInt(3, 7);
EXPECT_EQ(DAG->ComputeNumSignBits(Op, DemandedElts), 7u);
}
TEST_F(AArch64SelectionDAGTest, SimplifyDemandedVectorElts_EXTRACT_SUBVECTOR) {
TargetLowering TL(*TM);
SDLoc Loc;
auto IntVT = EVT::getIntegerVT(Context, 8);
auto VecVT = EVT::getVectorVT(Context, IntVT, 3);
auto IdxVT = EVT::getIntegerVT(Context, 64);
auto Vec = DAG->getConstant(1, Loc, VecVT);
auto ZeroIdx = DAG->getConstant(0, Loc, IdxVT);
auto Op = DAG->getNode(ISD::EXTRACT_SUBVECTOR, Loc, VecVT, Vec, ZeroIdx);
auto DemandedElts = APInt(3, 7);
auto KnownUndef = APInt(3, 0);
auto KnownZero = APInt(3, 0);
TargetLowering::TargetLoweringOpt TLO(*DAG, false, false);
EXPECT_EQ(TL.SimplifyDemandedVectorElts(Op, DemandedElts, KnownUndef,
KnownZero, TLO),
false);
}
TEST_F(AArch64SelectionDAGTest, SimplifyDemandedBitsNEON) {
TargetLowering TL(*TM);
SDLoc Loc;
auto Int8VT = EVT::getIntegerVT(Context, 8);
auto InVecVT = EVT::getVectorVT(Context, Int8VT, 16);
SDValue UnknownOp = DAG->getRegister(0, InVecVT);
SDValue Mask1S = DAG->getConstant(0x8A, Loc, Int8VT);
SDValue Mask1V = DAG->getSplatBuildVector(InVecVT, Loc, Mask1S);
SDValue N0 = DAG->getNode(ISD::AND, Loc, InVecVT, Mask1V, UnknownOp);
SDValue Mask2S = DAG->getConstant(0x55, Loc, Int8VT);
SDValue Mask2V = DAG->getSplatBuildVector(InVecVT, Loc, Mask2S);
SDValue Op = DAG->getNode(ISD::AND, Loc, InVecVT, N0, Mask2V);
// N0 = ?000?0?0
// Mask2V = 01010101
// =>
// Known.Zero = 00100000 (0xAA)
KnownBits Known;
APInt DemandedBits = APInt(8, 0xFF);
TargetLowering::TargetLoweringOpt TLO(*DAG, false, false);
EXPECT_TRUE(TL.SimplifyDemandedBits(Op, DemandedBits, Known, TLO));
EXPECT_EQ(Known.Zero, APInt(8, 0xAA));
}
TEST_F(AArch64SelectionDAGTest, SimplifyDemandedBitsSVE) {
TargetLowering TL(*TM);
SDLoc Loc;
auto Int8VT = EVT::getIntegerVT(Context, 8);
auto InVecVT = EVT::getVectorVT(Context, Int8VT, 16, /*IsScalable=*/true);
SDValue UnknownOp = DAG->getRegister(0, InVecVT);
SDValue Mask1S = DAG->getConstant(0x8A, Loc, Int8VT);
SDValue Mask1V = DAG->getSplatVector(InVecVT, Loc, Mask1S);
SDValue N0 = DAG->getNode(ISD::AND, Loc, InVecVT, Mask1V, UnknownOp);
SDValue Mask2S = DAG->getConstant(0x55, Loc, Int8VT);
SDValue Mask2V = DAG->getSplatVector(InVecVT, Loc, Mask2S);
SDValue Op = DAG->getNode(ISD::AND, Loc, InVecVT, N0, Mask2V);
// N0 = ?000?0?0
// Mask2V = 01010101
// =>
// Known.Zero = 00100000 (0xAA)
KnownBits Known;
APInt DemandedBits = APInt(8, 0xFF);
TargetLowering::TargetLoweringOpt TLO(*DAG, false, false);
EXPECT_TRUE(TL.SimplifyDemandedBits(Op, DemandedBits, Known, TLO));
EXPECT_EQ(Known.Zero, APInt(8, 0xAA));
}
// Piggy-backing on the AArch64 tests to verify SelectionDAG::computeKnownBits.
TEST_F(AArch64SelectionDAGTest, ComputeKnownBits_ADD) {
SDLoc Loc;
auto IntVT = EVT::getIntegerVT(Context, 8);
auto UnknownOp = DAG->getRegister(0, IntVT);
auto Mask = DAG->getConstant(0x8A, Loc, IntVT);
auto N0 = DAG->getNode(ISD::AND, Loc, IntVT, Mask, UnknownOp);
auto N1 = DAG->getConstant(0x55, Loc, IntVT);
auto Op = DAG->getNode(ISD::ADD, Loc, IntVT, N0, N1);
// N0 = ?000?0?0
// N1 = 01010101
// =>
// Known.One = 01010101 (0x55)
// Known.Zero = 00100000 (0x20)
KnownBits Known = DAG->computeKnownBits(Op);
EXPECT_EQ(Known.Zero, APInt(8, 0x20));
EXPECT_EQ(Known.One, APInt(8, 0x55));
}
// Piggy-backing on the AArch64 tests to verify SelectionDAG::computeKnownBits.
TEST_F(AArch64SelectionDAGTest, ComputeKnownBits_SUB) {
SDLoc Loc;
auto IntVT = EVT::getIntegerVT(Context, 8);
auto N0 = DAG->getConstant(0x55, Loc, IntVT);
auto UnknownOp = DAG->getRegister(0, IntVT);
auto Mask = DAG->getConstant(0x2e, Loc, IntVT);
auto N1 = DAG->getNode(ISD::AND, Loc, IntVT, Mask, UnknownOp);
auto Op = DAG->getNode(ISD::SUB, Loc, IntVT, N0, N1);
// N0 = 01010101
// N1 = 00?0???0
// =>
// Known.One = 00000001 (0x1)
// Known.Zero = 10000000 (0x80)
KnownBits Known = DAG->computeKnownBits(Op);
EXPECT_EQ(Known.Zero, APInt(8, 0x80));
EXPECT_EQ(Known.One, APInt(8, 0x1));
}
TEST_F(AArch64SelectionDAGTest, isSplatValue_Fixed_BUILD_VECTOR) {
TargetLowering TL(*TM);
SDLoc Loc;
auto IntVT = EVT::getIntegerVT(Context, 8);
auto VecVT = EVT::getVectorVT(Context, IntVT, 16, false);
// Create a BUILD_VECTOR
SDValue Op = DAG->getConstant(1, Loc, VecVT);
EXPECT_EQ(Op->getOpcode(), ISD::BUILD_VECTOR);
EXPECT_TRUE(DAG->isSplatValue(Op, /*AllowUndefs=*/false));
APInt UndefElts;
APInt DemandedElts;
EXPECT_FALSE(DAG->isSplatValue(Op, DemandedElts, UndefElts));
// Width=16, Mask=3
DemandedElts = APInt(16, 3);
EXPECT_TRUE(DAG->isSplatValue(Op, DemandedElts, UndefElts));
}
TEST_F(AArch64SelectionDAGTest, isSplatValue_Fixed_ADD_of_BUILD_VECTOR) {
TargetLowering TL(*TM);
SDLoc Loc;
auto IntVT = EVT::getIntegerVT(Context, 8);
auto VecVT = EVT::getVectorVT(Context, IntVT, 16, false);
// Should create BUILD_VECTORs
SDValue Val1 = DAG->getConstant(1, Loc, VecVT);
SDValue Val2 = DAG->getConstant(3, Loc, VecVT);
EXPECT_EQ(Val1->getOpcode(), ISD::BUILD_VECTOR);
SDValue Op = DAG->getNode(ISD::ADD, Loc, VecVT, Val1, Val2);
EXPECT_TRUE(DAG->isSplatValue(Op, /*AllowUndefs=*/false));
APInt UndefElts;
APInt DemandedElts;
EXPECT_FALSE(DAG->isSplatValue(Op, DemandedElts, UndefElts));
// Width=16, Mask=3
DemandedElts = APInt(16, 3);
EXPECT_TRUE(DAG->isSplatValue(Op, DemandedElts, UndefElts));
}
TEST_F(AArch64SelectionDAGTest, isSplatValue_Scalable_SPLAT_VECTOR) {
TargetLowering TL(*TM);
SDLoc Loc;
auto IntVT = EVT::getIntegerVT(Context, 8);
auto VecVT = EVT::getVectorVT(Context, IntVT, 16, true);
// Create a SPLAT_VECTOR
SDValue Op = DAG->getConstant(1, Loc, VecVT);
EXPECT_EQ(Op->getOpcode(), ISD::SPLAT_VECTOR);
EXPECT_TRUE(DAG->isSplatValue(Op, /*AllowUndefs=*/false));
APInt UndefElts;
APInt DemandedElts(1,1);
EXPECT_TRUE(DAG->isSplatValue(Op, DemandedElts, UndefElts));
}
TEST_F(AArch64SelectionDAGTest, isSplatValue_Scalable_ADD_of_SPLAT_VECTOR) {
TargetLowering TL(*TM);
SDLoc Loc;
auto IntVT = EVT::getIntegerVT(Context, 8);
auto VecVT = EVT::getVectorVT(Context, IntVT, 16, true);
// Should create SPLAT_VECTORS
SDValue Val1 = DAG->getConstant(1, Loc, VecVT);
SDValue Val2 = DAG->getConstant(3, Loc, VecVT);
EXPECT_EQ(Val1->getOpcode(), ISD::SPLAT_VECTOR);
SDValue Op = DAG->getNode(ISD::ADD, Loc, VecVT, Val1, Val2);
EXPECT_TRUE(DAG->isSplatValue(Op, /*AllowUndefs=*/false));
APInt UndefElts;
APInt DemandedElts(1, 1);
EXPECT_TRUE(DAG->isSplatValue(Op, DemandedElts, UndefElts));
}
TEST_F(AArch64SelectionDAGTest, getSplatSourceVector_Fixed_BUILD_VECTOR) {
TargetLowering TL(*TM);
SDLoc Loc;
auto IntVT = EVT::getIntegerVT(Context, 8);
auto VecVT = EVT::getVectorVT(Context, IntVT, 16, false);
// Create a BUILD_VECTOR
SDValue Op = DAG->getConstant(1, Loc, VecVT);
EXPECT_EQ(Op->getOpcode(), ISD::BUILD_VECTOR);
int SplatIdx = -1;
EXPECT_EQ(DAG->getSplatSourceVector(Op, SplatIdx), Op);
EXPECT_EQ(SplatIdx, 0);
}
TEST_F(AArch64SelectionDAGTest, getSplatSourceVector_Fixed_ADD_of_BUILD_VECTOR) {
TargetLowering TL(*TM);
SDLoc Loc;
auto IntVT = EVT::getIntegerVT(Context, 8);
auto VecVT = EVT::getVectorVT(Context, IntVT, 16, false);
// Should create BUILD_VECTORs
SDValue Val1 = DAG->getConstant(1, Loc, VecVT);
SDValue Val2 = DAG->getConstant(3, Loc, VecVT);
EXPECT_EQ(Val1->getOpcode(), ISD::BUILD_VECTOR);
SDValue Op = DAG->getNode(ISD::ADD, Loc, VecVT, Val1, Val2);
int SplatIdx = -1;
EXPECT_EQ(DAG->getSplatSourceVector(Op, SplatIdx), Op);
EXPECT_EQ(SplatIdx, 0);
}
TEST_F(AArch64SelectionDAGTest, getSplatSourceVector_Scalable_SPLAT_VECTOR) {
TargetLowering TL(*TM);
SDLoc Loc;
auto IntVT = EVT::getIntegerVT(Context, 8);
auto VecVT = EVT::getVectorVT(Context, IntVT, 16, true);
// Create a SPLAT_VECTOR
SDValue Op = DAG->getConstant(1, Loc, VecVT);
EXPECT_EQ(Op->getOpcode(), ISD::SPLAT_VECTOR);
int SplatIdx = -1;
EXPECT_EQ(DAG->getSplatSourceVector(Op, SplatIdx), Op);
EXPECT_EQ(SplatIdx, 0);
}
TEST_F(AArch64SelectionDAGTest, getSplatSourceVector_Scalable_ADD_of_SPLAT_VECTOR) {
TargetLowering TL(*TM);
SDLoc Loc;
auto IntVT = EVT::getIntegerVT(Context, 8);
auto VecVT = EVT::getVectorVT(Context, IntVT, 16, true);
// Should create SPLAT_VECTORS
SDValue Val1 = DAG->getConstant(1, Loc, VecVT);
SDValue Val2 = DAG->getConstant(3, Loc, VecVT);
EXPECT_EQ(Val1->getOpcode(), ISD::SPLAT_VECTOR);
SDValue Op = DAG->getNode(ISD::ADD, Loc, VecVT, Val1, Val2);
int SplatIdx = -1;
EXPECT_EQ(DAG->getSplatSourceVector(Op, SplatIdx), Op);
EXPECT_EQ(SplatIdx, 0);
}
TEST_F(AArch64SelectionDAGTest, getRepeatedSequence_Patterns) {
TargetLowering TL(*TM);
SDLoc Loc;
unsigned NumElts = 16;
MVT IntVT = MVT::i8;
MVT VecVT = MVT::getVectorVT(IntVT, NumElts);
// Base scalar constants.
SDValue Val0 = DAG->getConstant(0, Loc, IntVT);
SDValue Val1 = DAG->getConstant(1, Loc, IntVT);
SDValue Val2 = DAG->getConstant(2, Loc, IntVT);
SDValue Val3 = DAG->getConstant(3, Loc, IntVT);
SDValue UndefVal = DAG->getUNDEF(IntVT);
// Build some repeating sequences.
SmallVector<SDValue, 16> Pattern1111, Pattern1133, Pattern0123;
for(int I = 0; I != 4; ++I) {
Pattern1111.append(4, Val1);
Pattern1133.append(2, Val1);
Pattern1133.append(2, Val3);
Pattern0123.push_back(Val0);
Pattern0123.push_back(Val1);
Pattern0123.push_back(Val2);
Pattern0123.push_back(Val3);
}
// Build a non-pow2 repeating sequence.
SmallVector<SDValue, 16> Pattern022;
Pattern022.push_back(Val0);
Pattern022.append(2, Val2);
Pattern022.push_back(Val0);
Pattern022.append(2, Val2);
Pattern022.push_back(Val0);
Pattern022.append(2, Val2);
Pattern022.push_back(Val0);
Pattern022.append(2, Val2);
Pattern022.push_back(Val0);
Pattern022.append(2, Val2);
Pattern022.push_back(Val0);
// Build a non-repeating sequence.
SmallVector<SDValue, 16> Pattern1_3;
Pattern1_3.append(8, Val1);
Pattern1_3.append(8, Val3);
// Add some undefs to make it trickier.
Pattern1111[1] = Pattern1111[2] = Pattern1111[15] = UndefVal;
Pattern1133[0] = Pattern1133[2] = UndefVal;
auto *BV1111 =
cast<BuildVectorSDNode>(DAG->getBuildVector(VecVT, Loc, Pattern1111));
auto *BV1133 =
cast<BuildVectorSDNode>(DAG->getBuildVector(VecVT, Loc, Pattern1133));
auto *BV0123=
cast<BuildVectorSDNode>(DAG->getBuildVector(VecVT, Loc, Pattern0123));
auto *BV022 =
cast<BuildVectorSDNode>(DAG->getBuildVector(VecVT, Loc, Pattern022));
auto *BV1_3 =
cast<BuildVectorSDNode>(DAG->getBuildVector(VecVT, Loc, Pattern1_3));
// Check for sequences.
SmallVector<SDValue, 16> Seq1111, Seq1133, Seq0123, Seq022, Seq1_3;
BitVector Undefs1111, Undefs1133, Undefs0123, Undefs022, Undefs1_3;
EXPECT_TRUE(BV1111->getRepeatedSequence(Seq1111, &Undefs1111));
EXPECT_EQ(Undefs1111.count(), 3u);
EXPECT_EQ(Seq1111.size(), 1u);
EXPECT_EQ(Seq1111[0], Val1);
EXPECT_TRUE(BV1133->getRepeatedSequence(Seq1133, &Undefs1133));
EXPECT_EQ(Undefs1133.count(), 2u);
EXPECT_EQ(Seq1133.size(), 4u);
EXPECT_EQ(Seq1133[0], Val1);
EXPECT_EQ(Seq1133[1], Val1);
EXPECT_EQ(Seq1133[2], Val3);
EXPECT_EQ(Seq1133[3], Val3);
EXPECT_TRUE(BV0123->getRepeatedSequence(Seq0123, &Undefs0123));
EXPECT_EQ(Undefs0123.count(), 0u);
EXPECT_EQ(Seq0123.size(), 4u);
EXPECT_EQ(Seq0123[0], Val0);
EXPECT_EQ(Seq0123[1], Val1);
EXPECT_EQ(Seq0123[2], Val2);
EXPECT_EQ(Seq0123[3], Val3);
EXPECT_FALSE(BV022->getRepeatedSequence(Seq022, &Undefs022));
EXPECT_FALSE(BV1_3->getRepeatedSequence(Seq1_3, &Undefs1_3));
// Try again with DemandedElts masks.
APInt Mask1111_0 = APInt::getOneBitSet(NumElts, 0);
EXPECT_TRUE(BV1111->getRepeatedSequence(Mask1111_0, Seq1111, &Undefs1111));
EXPECT_EQ(Undefs1111.count(), 0u);
EXPECT_EQ(Seq1111.size(), 1u);
EXPECT_EQ(Seq1111[0], Val1);
APInt Mask1111_1 = APInt::getOneBitSet(NumElts, 2);
EXPECT_TRUE(BV1111->getRepeatedSequence(Mask1111_1, Seq1111, &Undefs1111));
EXPECT_EQ(Undefs1111.count(), 1u);
EXPECT_EQ(Seq1111.size(), 1u);
EXPECT_EQ(Seq1111[0], UndefVal);
APInt Mask0123 = APInt(NumElts, 0x7777);
EXPECT_TRUE(BV0123->getRepeatedSequence(Mask0123, Seq0123, &Undefs0123));
EXPECT_EQ(Undefs0123.count(), 0u);
EXPECT_EQ(Seq0123.size(), 4u);
EXPECT_EQ(Seq0123[0], Val0);
EXPECT_EQ(Seq0123[1], Val1);
EXPECT_EQ(Seq0123[2], Val2);
EXPECT_EQ(Seq0123[3], SDValue());
APInt Mask1_3 = APInt::getHighBitsSet(16, 8);
EXPECT_TRUE(BV1_3->getRepeatedSequence(Mask1_3, Seq1_3, &Undefs1_3));
EXPECT_EQ(Undefs1_3.count(), 0u);
EXPECT_EQ(Seq1_3.size(), 1u);
EXPECT_EQ(Seq1_3[0], Val3);
}
TEST_F(AArch64SelectionDAGTest, getTypeConversion_SplitScalableMVT) {
MVT VT = MVT::nxv4i64;
EXPECT_EQ(getTypeAction(VT), TargetLoweringBase::TypeSplitVector);
ASSERT_TRUE(getTypeToTransformTo(VT).isScalableVector());
}
TEST_F(AArch64SelectionDAGTest, getTypeConversion_PromoteScalableMVT) {
MVT VT = MVT::nxv2i32;
EXPECT_EQ(getTypeAction(VT), TargetLoweringBase::TypePromoteInteger);
ASSERT_TRUE(getTypeToTransformTo(VT).isScalableVector());
}
TEST_F(AArch64SelectionDAGTest, getTypeConversion_NoScalarizeMVT_nxv1f32) {
MVT VT = MVT::nxv1f32;
EXPECT_NE(getTypeAction(VT), TargetLoweringBase::TypeScalarizeVector);
ASSERT_TRUE(getTypeToTransformTo(VT).isScalableVector());
}
TEST_F(AArch64SelectionDAGTest, getTypeConversion_SplitScalableEVT) {
EVT VT = EVT::getVectorVT(Context, MVT::i64, 256, true);
EXPECT_EQ(getTypeAction(VT), TargetLoweringBase::TypeSplitVector);
EXPECT_EQ(getTypeToTransformTo(VT), VT.getHalfNumVectorElementsVT(Context));
}
TEST_F(AArch64SelectionDAGTest, getTypeConversion_WidenScalableEVT) {
EVT FromVT = EVT::getVectorVT(Context, MVT::i64, 6, true);
EVT ToVT = EVT::getVectorVT(Context, MVT::i64, 8, true);
EXPECT_EQ(getTypeAction(FromVT), TargetLoweringBase::TypeWidenVector);
EXPECT_EQ(getTypeToTransformTo(FromVT), ToVT);
}
TEST_F(AArch64SelectionDAGTest,
getTypeConversion_ScalarizeScalableEVT_nxv1f128) {
EVT VT = EVT::getVectorVT(Context, MVT::f128, ElementCount::getScalable(1));
EXPECT_EQ(getTypeAction(VT), TargetLoweringBase::TypeScalarizeScalableVector);
EXPECT_EQ(getTypeToTransformTo(VT), MVT::f128);
}
TEST_F(AArch64SelectionDAGTest, TestFold_STEP_VECTOR) {
SDLoc Loc;
auto IntVT = EVT::getIntegerVT(Context, 8);
auto VecVT = EVT::getVectorVT(Context, MVT::i8, 16, true);
// Should create SPLAT_VECTOR
SDValue Zero = DAG->getConstant(0, Loc, IntVT);
SDValue Op = DAG->getNode(ISD::STEP_VECTOR, Loc, VecVT, Zero);
EXPECT_EQ(Op.getOpcode(), ISD::SPLAT_VECTOR);
}
TEST_F(AArch64SelectionDAGTest, ReplaceAllUsesWith) {
SDLoc Loc;
EVT IntVT = EVT::getIntegerVT(Context, 8);
SDValue N0 = DAG->getConstant(0x42, Loc, IntVT);
SDValue N1 = DAG->getRegister(0, IntVT);
// Construct node to fill arbitrary ExtraInfo.
SDValue N2 = DAG->getNode(ISD::SUB, Loc, IntVT, N0, N1);
EXPECT_FALSE(DAG->getHeapAllocSite(N2.getNode()));
EXPECT_FALSE(DAG->getNoMergeSiteInfo(N2.getNode()));
EXPECT_FALSE(DAG->getPCSections(N2.getNode()));
MDNode *MD = MDNode::get(Context, std::nullopt);
DAG->addHeapAllocSite(N2.getNode(), MD);
DAG->addNoMergeSiteInfo(N2.getNode(), true);
DAG->addPCSections(N2.getNode(), MD);
EXPECT_EQ(DAG->getHeapAllocSite(N2.getNode()), MD);
EXPECT_TRUE(DAG->getNoMergeSiteInfo(N2.getNode()));
EXPECT_EQ(DAG->getPCSections(N2.getNode()), MD);
SDValue Root = DAG->getNode(ISD::ADD, Loc, IntVT, N2, N2);
EXPECT_EQ(Root->getOperand(0)->getOpcode(), ISD::SUB);
// Create new node and check that ExtraInfo is propagated on RAUW.
SDValue New = DAG->getNode(ISD::ADD, Loc, IntVT, N1, N1);
EXPECT_FALSE(DAG->getHeapAllocSite(New.getNode()));
EXPECT_FALSE(DAG->getNoMergeSiteInfo(New.getNode()));
EXPECT_FALSE(DAG->getPCSections(New.getNode()));
DAG->ReplaceAllUsesWith(N2, New);
EXPECT_EQ(Root->getOperand(0), New);
EXPECT_EQ(DAG->getHeapAllocSite(New.getNode()), MD);
EXPECT_TRUE(DAG->getNoMergeSiteInfo(New.getNode()));
EXPECT_EQ(DAG->getPCSections(New.getNode()), MD);
}
} // end namespace llvm