1 //===- llvm/unittest/CodeGen/AArch64SelectionDAGTest.cpp -------------------------===// 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 "llvm/CodeGen/SelectionDAG.h" 10 #include "llvm/Analysis/OptimizationRemarkEmitter.h" 11 #include "llvm/AsmParser/Parser.h" 12 #include "llvm/CodeGen/MachineModuleInfo.h" 13 #include "llvm/CodeGen/TargetLowering.h" 14 #include "llvm/Support/SourceMgr.h" 15 #include "llvm/Support/TargetRegistry.h" 16 #include "llvm/Support/TargetSelect.h" 17 #include "llvm/Target/TargetMachine.h" 18 #include "gtest/gtest.h" 19 20 using namespace llvm; 21 22 namespace { 23 24 class AArch64SelectionDAGTest : public testing::Test { 25 protected: 26 static void SetUpTestCase() { 27 InitializeAllTargets(); 28 InitializeAllTargetMCs(); 29 } 30 31 void SetUp() override { 32 StringRef Assembly = "define void @f() { ret void }"; 33 34 Triple TargetTriple("aarch64--"); 35 std::string Error; 36 const Target *T = TargetRegistry::lookupTarget("", TargetTriple, Error); 37 // FIXME: These tests do not depend on AArch64 specifically, but we have to 38 // initialize a target. A skeleton Target for unittests would allow us to 39 // always run these tests. 40 if (!T) 41 return; 42 43 TargetOptions Options; 44 TM = std::unique_ptr<LLVMTargetMachine>(static_cast<LLVMTargetMachine*>( 45 T->createTargetMachine("AArch64", "", "", Options, None, None, 46 CodeGenOpt::Aggressive))); 47 if (!TM) 48 return; 49 50 SMDiagnostic SMError; 51 M = parseAssemblyString(Assembly, SMError, Context); 52 if (!M) 53 report_fatal_error(SMError.getMessage()); 54 M->setDataLayout(TM->createDataLayout()); 55 56 F = M->getFunction("f"); 57 if (!F) 58 report_fatal_error("F?"); 59 60 MachineModuleInfo MMI(TM.get()); 61 62 MF = std::make_unique<MachineFunction>(*F, *TM, *TM->getSubtargetImpl(*F), 0, 63 MMI); 64 65 DAG = std::make_unique<SelectionDAG>(*TM, CodeGenOpt::None); 66 if (!DAG) 67 report_fatal_error("DAG?"); 68 OptimizationRemarkEmitter ORE(F); 69 DAG->init(*MF, ORE, nullptr, nullptr, nullptr, nullptr, nullptr); 70 } 71 72 LLVMContext Context; 73 std::unique_ptr<LLVMTargetMachine> TM; 74 std::unique_ptr<Module> M; 75 Function *F; 76 std::unique_ptr<MachineFunction> MF; 77 std::unique_ptr<SelectionDAG> DAG; 78 }; 79 80 TEST_F(AArch64SelectionDAGTest, computeKnownBits_ZERO_EXTEND_VECTOR_INREG) { 81 if (!TM) 82 return; 83 SDLoc Loc; 84 auto Int8VT = EVT::getIntegerVT(Context, 8); 85 auto Int16VT = EVT::getIntegerVT(Context, 16); 86 auto InVecVT = EVT::getVectorVT(Context, Int8VT, 4); 87 auto OutVecVT = EVT::getVectorVT(Context, Int16VT, 2); 88 auto InVec = DAG->getConstant(0, Loc, InVecVT); 89 auto Op = DAG->getNode(ISD::ZERO_EXTEND_VECTOR_INREG, Loc, OutVecVT, InVec); 90 auto DemandedElts = APInt(2, 3); 91 KnownBits Known = DAG->computeKnownBits(Op, DemandedElts); 92 EXPECT_TRUE(Known.isZero()); 93 } 94 95 TEST_F(AArch64SelectionDAGTest, computeKnownBits_EXTRACT_SUBVECTOR) { 96 if (!TM) 97 return; 98 SDLoc Loc; 99 auto IntVT = EVT::getIntegerVT(Context, 8); 100 auto VecVT = EVT::getVectorVT(Context, IntVT, 3); 101 auto IdxVT = EVT::getIntegerVT(Context, 64); 102 auto Vec = DAG->getConstant(0, Loc, VecVT); 103 auto ZeroIdx = DAG->getConstant(0, Loc, IdxVT); 104 auto Op = DAG->getNode(ISD::EXTRACT_SUBVECTOR, Loc, VecVT, Vec, ZeroIdx); 105 auto DemandedElts = APInt(3, 7); 106 KnownBits Known = DAG->computeKnownBits(Op, DemandedElts); 107 EXPECT_TRUE(Known.isZero()); 108 } 109 110 TEST_F(AArch64SelectionDAGTest, ComputeNumSignBits_SIGN_EXTEND_VECTOR_INREG) { 111 if (!TM) 112 return; 113 SDLoc Loc; 114 auto Int8VT = EVT::getIntegerVT(Context, 8); 115 auto Int16VT = EVT::getIntegerVT(Context, 16); 116 auto InVecVT = EVT::getVectorVT(Context, Int8VT, 4); 117 auto OutVecVT = EVT::getVectorVT(Context, Int16VT, 2); 118 auto InVec = DAG->getConstant(1, Loc, InVecVT); 119 auto Op = DAG->getNode(ISD::SIGN_EXTEND_VECTOR_INREG, Loc, OutVecVT, InVec); 120 auto DemandedElts = APInt(2, 3); 121 EXPECT_EQ(DAG->ComputeNumSignBits(Op, DemandedElts), 15u); 122 } 123 124 TEST_F(AArch64SelectionDAGTest, ComputeNumSignBits_EXTRACT_SUBVECTOR) { 125 if (!TM) 126 return; 127 SDLoc Loc; 128 auto IntVT = EVT::getIntegerVT(Context, 8); 129 auto VecVT = EVT::getVectorVT(Context, IntVT, 3); 130 auto IdxVT = EVT::getIntegerVT(Context, 64); 131 auto Vec = DAG->getConstant(1, Loc, VecVT); 132 auto ZeroIdx = DAG->getConstant(0, Loc, IdxVT); 133 auto Op = DAG->getNode(ISD::EXTRACT_SUBVECTOR, Loc, VecVT, Vec, ZeroIdx); 134 auto DemandedElts = APInt(3, 7); 135 EXPECT_EQ(DAG->ComputeNumSignBits(Op, DemandedElts), 7u); 136 } 137 138 TEST_F(AArch64SelectionDAGTest, SimplifyDemandedVectorElts_EXTRACT_SUBVECTOR) { 139 if (!TM) 140 return; 141 142 TargetLowering TL(*TM); 143 144 SDLoc Loc; 145 auto IntVT = EVT::getIntegerVT(Context, 8); 146 auto VecVT = EVT::getVectorVT(Context, IntVT, 3); 147 auto IdxVT = EVT::getIntegerVT(Context, 64); 148 auto Vec = DAG->getConstant(1, Loc, VecVT); 149 auto ZeroIdx = DAG->getConstant(0, Loc, IdxVT); 150 auto Op = DAG->getNode(ISD::EXTRACT_SUBVECTOR, Loc, VecVT, Vec, ZeroIdx); 151 auto DemandedElts = APInt(3, 7); 152 auto KnownUndef = APInt(3, 0); 153 auto KnownZero = APInt(3, 0); 154 TargetLowering::TargetLoweringOpt TLO(*DAG, false, false); 155 EXPECT_EQ(TL.SimplifyDemandedVectorElts(Op, DemandedElts, KnownUndef, 156 KnownZero, TLO), 157 false); 158 } 159 160 // Piggy-backing on the AArch64 tests to verify SelectionDAG::computeKnownBits. 161 TEST_F(AArch64SelectionDAGTest, ComputeKnownBits_ADD) { 162 if (!TM) 163 return; 164 SDLoc Loc; 165 auto IntVT = EVT::getIntegerVT(Context, 8); 166 auto UnknownOp = DAG->getRegister(0, IntVT); 167 auto Mask = DAG->getConstant(0x8A, Loc, IntVT); 168 auto N0 = DAG->getNode(ISD::AND, Loc, IntVT, Mask, UnknownOp); 169 auto N1 = DAG->getConstant(0x55, Loc, IntVT); 170 auto Op = DAG->getNode(ISD::ADD, Loc, IntVT, N0, N1); 171 // N0 = ?000?0?0 172 // N1 = 01010101 173 // => 174 // Known.One = 01010101 (0x55) 175 // Known.Zero = 00100000 (0x20) 176 KnownBits Known = DAG->computeKnownBits(Op); 177 EXPECT_EQ(Known.Zero, APInt(8, 0x20)); 178 EXPECT_EQ(Known.One, APInt(8, 0x55)); 179 } 180 181 // Piggy-backing on the AArch64 tests to verify SelectionDAG::computeKnownBits. 182 TEST_F(AArch64SelectionDAGTest, ComputeKnownBits_SUB) { 183 if (!TM) 184 return; 185 SDLoc Loc; 186 auto IntVT = EVT::getIntegerVT(Context, 8); 187 auto N0 = DAG->getConstant(0x55, Loc, IntVT); 188 auto UnknownOp = DAG->getRegister(0, IntVT); 189 auto Mask = DAG->getConstant(0x2e, Loc, IntVT); 190 auto N1 = DAG->getNode(ISD::AND, Loc, IntVT, Mask, UnknownOp); 191 auto Op = DAG->getNode(ISD::SUB, Loc, IntVT, N0, N1); 192 // N0 = 01010101 193 // N1 = 00?0???0 194 // => 195 // Known.One = 00000001 (0x1) 196 // Known.Zero = 10000000 (0x80) 197 KnownBits Known = DAG->computeKnownBits(Op); 198 EXPECT_EQ(Known.Zero, APInt(8, 0x80)); 199 EXPECT_EQ(Known.One, APInt(8, 0x1)); 200 } 201 202 TEST_F(AArch64SelectionDAGTest, isSplatValue_Fixed_BUILD_VECTOR) { 203 if (!TM) 204 return; 205 206 TargetLowering TL(*TM); 207 208 SDLoc Loc; 209 auto IntVT = EVT::getIntegerVT(Context, 8); 210 auto VecVT = EVT::getVectorVT(Context, IntVT, 16, false); 211 // Create a BUILD_VECTOR 212 SDValue Op = DAG->getConstant(1, Loc, VecVT); 213 EXPECT_EQ(Op->getOpcode(), ISD::BUILD_VECTOR); 214 EXPECT_TRUE(DAG->isSplatValue(Op, /*AllowUndefs=*/false)); 215 216 APInt UndefElts; 217 APInt DemandedElts; 218 EXPECT_FALSE(DAG->isSplatValue(Op, DemandedElts, UndefElts)); 219 220 // Width=16, Mask=3 221 DemandedElts = APInt(16, 3); 222 EXPECT_TRUE(DAG->isSplatValue(Op, DemandedElts, UndefElts)); 223 } 224 225 TEST_F(AArch64SelectionDAGTest, isSplatValue_Fixed_ADD_of_BUILD_VECTOR) { 226 if (!TM) 227 return; 228 229 TargetLowering TL(*TM); 230 231 SDLoc Loc; 232 auto IntVT = EVT::getIntegerVT(Context, 8); 233 auto VecVT = EVT::getVectorVT(Context, IntVT, 16, false); 234 235 // Should create BUILD_VECTORs 236 SDValue Val1 = DAG->getConstant(1, Loc, VecVT); 237 SDValue Val2 = DAG->getConstant(3, Loc, VecVT); 238 EXPECT_EQ(Val1->getOpcode(), ISD::BUILD_VECTOR); 239 SDValue Op = DAG->getNode(ISD::ADD, Loc, VecVT, Val1, Val2); 240 241 EXPECT_TRUE(DAG->isSplatValue(Op, /*AllowUndefs=*/false)); 242 243 APInt UndefElts; 244 APInt DemandedElts; 245 EXPECT_FALSE(DAG->isSplatValue(Op, DemandedElts, UndefElts)); 246 247 // Width=16, Mask=3 248 DemandedElts = APInt(16, 3); 249 EXPECT_TRUE(DAG->isSplatValue(Op, DemandedElts, UndefElts)); 250 } 251 252 TEST_F(AArch64SelectionDAGTest, isSplatValue_Scalable_SPLAT_VECTOR) { 253 if (!TM) 254 return; 255 256 TargetLowering TL(*TM); 257 258 SDLoc Loc; 259 auto IntVT = EVT::getIntegerVT(Context, 8); 260 auto VecVT = EVT::getVectorVT(Context, IntVT, 16, true); 261 // Create a SPLAT_VECTOR 262 SDValue Op = DAG->getConstant(1, Loc, VecVT); 263 EXPECT_EQ(Op->getOpcode(), ISD::SPLAT_VECTOR); 264 EXPECT_TRUE(DAG->isSplatValue(Op, /*AllowUndefs=*/false)); 265 266 APInt UndefElts; 267 APInt DemandedElts; 268 EXPECT_TRUE(DAG->isSplatValue(Op, DemandedElts, UndefElts)); 269 270 // Width=16, Mask=3. These bits should be ignored. 271 DemandedElts = APInt(16, 3); 272 EXPECT_TRUE(DAG->isSplatValue(Op, DemandedElts, UndefElts)); 273 } 274 275 TEST_F(AArch64SelectionDAGTest, isSplatValue_Scalable_ADD_of_SPLAT_VECTOR) { 276 if (!TM) 277 return; 278 279 TargetLowering TL(*TM); 280 281 SDLoc Loc; 282 auto IntVT = EVT::getIntegerVT(Context, 8); 283 auto VecVT = EVT::getVectorVT(Context, IntVT, 16, true); 284 285 // Should create SPLAT_VECTORS 286 SDValue Val1 = DAG->getConstant(1, Loc, VecVT); 287 SDValue Val2 = DAG->getConstant(3, Loc, VecVT); 288 EXPECT_EQ(Val1->getOpcode(), ISD::SPLAT_VECTOR); 289 SDValue Op = DAG->getNode(ISD::ADD, Loc, VecVT, Val1, Val2); 290 291 EXPECT_TRUE(DAG->isSplatValue(Op, /*AllowUndefs=*/false)); 292 293 APInt UndefElts; 294 APInt DemandedElts; 295 EXPECT_TRUE(DAG->isSplatValue(Op, DemandedElts, UndefElts)); 296 297 // Width=16, Mask=3. These bits should be ignored. 298 DemandedElts = APInt(16, 3); 299 EXPECT_TRUE(DAG->isSplatValue(Op, DemandedElts, UndefElts)); 300 } 301 302 TEST_F(AArch64SelectionDAGTest, getSplatSourceVector_Fixed_BUILD_VECTOR) { 303 if (!TM) 304 return; 305 306 TargetLowering TL(*TM); 307 308 SDLoc Loc; 309 auto IntVT = EVT::getIntegerVT(Context, 8); 310 auto VecVT = EVT::getVectorVT(Context, IntVT, 16, false); 311 // Create a BUILD_VECTOR 312 SDValue Op = DAG->getConstant(1, Loc, VecVT); 313 EXPECT_EQ(Op->getOpcode(), ISD::BUILD_VECTOR); 314 315 int SplatIdx = -1; 316 EXPECT_EQ(DAG->getSplatSourceVector(Op, SplatIdx), Op); 317 EXPECT_EQ(SplatIdx, 0); 318 } 319 320 TEST_F(AArch64SelectionDAGTest, getSplatSourceVector_Fixed_ADD_of_BUILD_VECTOR) { 321 if (!TM) 322 return; 323 324 TargetLowering TL(*TM); 325 326 SDLoc Loc; 327 auto IntVT = EVT::getIntegerVT(Context, 8); 328 auto VecVT = EVT::getVectorVT(Context, IntVT, 16, false); 329 330 // Should create BUILD_VECTORs 331 SDValue Val1 = DAG->getConstant(1, Loc, VecVT); 332 SDValue Val2 = DAG->getConstant(3, Loc, VecVT); 333 EXPECT_EQ(Val1->getOpcode(), ISD::BUILD_VECTOR); 334 SDValue Op = DAG->getNode(ISD::ADD, Loc, VecVT, Val1, Val2); 335 336 int SplatIdx = -1; 337 EXPECT_EQ(DAG->getSplatSourceVector(Op, SplatIdx), Op); 338 EXPECT_EQ(SplatIdx, 0); 339 } 340 341 TEST_F(AArch64SelectionDAGTest, getSplatSourceVector_Scalable_SPLAT_VECTOR) { 342 if (!TM) 343 return; 344 345 TargetLowering TL(*TM); 346 347 SDLoc Loc; 348 auto IntVT = EVT::getIntegerVT(Context, 8); 349 auto VecVT = EVT::getVectorVT(Context, IntVT, 16, true); 350 // Create a SPLAT_VECTOR 351 SDValue Op = DAG->getConstant(1, Loc, VecVT); 352 EXPECT_EQ(Op->getOpcode(), ISD::SPLAT_VECTOR); 353 354 int SplatIdx = -1; 355 EXPECT_EQ(DAG->getSplatSourceVector(Op, SplatIdx), Op); 356 EXPECT_EQ(SplatIdx, 0); 357 } 358 359 TEST_F(AArch64SelectionDAGTest, getSplatSourceVector_Scalable_ADD_of_SPLAT_VECTOR) { 360 if (!TM) 361 return; 362 363 TargetLowering TL(*TM); 364 365 SDLoc Loc; 366 auto IntVT = EVT::getIntegerVT(Context, 8); 367 auto VecVT = EVT::getVectorVT(Context, IntVT, 16, true); 368 369 // Should create SPLAT_VECTORS 370 SDValue Val1 = DAG->getConstant(1, Loc, VecVT); 371 SDValue Val2 = DAG->getConstant(3, Loc, VecVT); 372 EXPECT_EQ(Val1->getOpcode(), ISD::SPLAT_VECTOR); 373 SDValue Op = DAG->getNode(ISD::ADD, Loc, VecVT, Val1, Val2); 374 375 int SplatIdx = -1; 376 EXPECT_EQ(DAG->getSplatSourceVector(Op, SplatIdx), Op); 377 EXPECT_EQ(SplatIdx, 0); 378 } 379 380 } // end anonymous namespace 381