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); 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 } // end anonymous namespace 203