1 //===---- llvm/unittest/CodeGen/SelectionDAGPatternMatchTest.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/Analysis/OptimizationRemarkEmitter.h" 10 #include "llvm/AsmParser/Parser.h" 11 #include "llvm/CodeGen/MachineModuleInfo.h" 12 #include "llvm/CodeGen/SDPatternMatch.h" 13 #include "llvm/CodeGen/TargetLowering.h" 14 #include "llvm/IR/Module.h" 15 #include "llvm/MC/TargetRegistry.h" 16 #include "llvm/Support/SourceMgr.h" 17 #include "llvm/Support/TargetSelect.h" 18 #include "llvm/Target/TargetMachine.h" 19 #include "gtest/gtest.h" 20 21 using namespace llvm; 22 23 class SelectionDAGPatternMatchTest : public testing::Test { 24 protected: 25 static void SetUpTestCase() { 26 InitializeAllTargets(); 27 InitializeAllTargetMCs(); 28 } 29 30 void SetUp() override { 31 StringRef Assembly = "@g = global i32 0\n" 32 "@g_alias = alias i32, i32* @g\n" 33 "define i32 @f() {\n" 34 " %1 = load i32, i32* @g\n" 35 " ret i32 %1\n" 36 "}"; 37 38 Triple TargetTriple("riscv64--"); 39 std::string Error; 40 const Target *T = TargetRegistry::lookupTarget("", TargetTriple, Error); 41 // FIXME: These tests do not depend on RISCV specifically, but we have to 42 // initialize a target. A skeleton Target for unittests would allow us to 43 // always run these tests. 44 if (!T) 45 GTEST_SKIP(); 46 47 TargetOptions Options; 48 TM = std::unique_ptr<TargetMachine>(T->createTargetMachine( 49 "riscv64", "", "+m,+f,+d,+v", Options, std::nullopt, std::nullopt, 50 CodeGenOptLevel::Aggressive)); 51 if (!TM) 52 GTEST_SKIP(); 53 54 SMDiagnostic SMError; 55 M = parseAssemblyString(Assembly, SMError, Context); 56 if (!M) 57 report_fatal_error(SMError.getMessage()); 58 M->setDataLayout(TM->createDataLayout()); 59 60 F = M->getFunction("f"); 61 if (!F) 62 report_fatal_error("F?"); 63 G = M->getGlobalVariable("g"); 64 if (!G) 65 report_fatal_error("G?"); 66 AliasedG = M->getNamedAlias("g_alias"); 67 if (!AliasedG) 68 report_fatal_error("AliasedG?"); 69 70 MachineModuleInfo MMI(TM.get()); 71 72 MF = std::make_unique<MachineFunction>(*F, *TM, *TM->getSubtargetImpl(*F), 73 MMI.getContext(), 0); 74 75 DAG = std::make_unique<SelectionDAG>(*TM, CodeGenOptLevel::None); 76 if (!DAG) 77 report_fatal_error("DAG?"); 78 OptimizationRemarkEmitter ORE(F); 79 DAG->init(*MF, ORE, nullptr, nullptr, nullptr, nullptr, nullptr, MMI, 80 nullptr); 81 } 82 83 TargetLoweringBase::LegalizeTypeAction getTypeAction(EVT VT) { 84 return DAG->getTargetLoweringInfo().getTypeAction(Context, VT); 85 } 86 87 EVT getTypeToTransformTo(EVT VT) { 88 return DAG->getTargetLoweringInfo().getTypeToTransformTo(Context, VT); 89 } 90 91 LLVMContext Context; 92 std::unique_ptr<TargetMachine> TM; 93 std::unique_ptr<Module> M; 94 Function *F; 95 GlobalVariable *G; 96 GlobalAlias *AliasedG; 97 std::unique_ptr<MachineFunction> MF; 98 std::unique_ptr<SelectionDAG> DAG; 99 }; 100 101 TEST_F(SelectionDAGPatternMatchTest, matchValueType) { 102 SDLoc DL; 103 auto Int32VT = EVT::getIntegerVT(Context, 32); 104 auto Float32VT = EVT::getFloatingPointVT(32); 105 auto VInt32VT = EVT::getVectorVT(Context, Int32VT, 4); 106 107 SDValue Op0 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, Int32VT); 108 SDValue Op1 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 2, Float32VT); 109 SDValue Op2 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 2, VInt32VT); 110 111 using namespace SDPatternMatch; 112 EXPECT_TRUE(sd_match(Op0, m_SpecificVT(Int32VT))); 113 EVT BindVT; 114 EXPECT_TRUE(sd_match(Op1, m_VT(BindVT))); 115 EXPECT_EQ(BindVT, Float32VT); 116 EXPECT_TRUE(sd_match(Op0, m_IntegerVT())); 117 EXPECT_TRUE(sd_match(Op1, m_FloatingPointVT())); 118 EXPECT_TRUE(sd_match(Op2, m_VectorVT())); 119 EXPECT_FALSE(sd_match(Op2, m_ScalableVectorVT())); 120 } 121 122 TEST_F(SelectionDAGPatternMatchTest, matchVecShuffle) { 123 SDLoc DL; 124 auto Int32VT = EVT::getIntegerVT(Context, 32); 125 auto VInt32VT = EVT::getVectorVT(Context, Int32VT, 4); 126 const std::array<int, 4> MaskData = {2, 0, 3, 1}; 127 const std::array<int, 4> OtherMaskData = {1, 2, 3, 4}; 128 ArrayRef<int> Mask; 129 130 SDValue V0 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, VInt32VT); 131 SDValue V1 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 2, VInt32VT); 132 SDValue VecShuffleWithMask = 133 DAG->getVectorShuffle(VInt32VT, DL, V0, V1, MaskData); 134 135 using namespace SDPatternMatch; 136 EXPECT_TRUE(sd_match(VecShuffleWithMask, m_Shuffle(m_Value(), m_Value()))); 137 EXPECT_TRUE(sd_match(VecShuffleWithMask, 138 m_Shuffle(m_Value(), m_Value(), m_Mask(Mask)))); 139 EXPECT_TRUE( 140 sd_match(VecShuffleWithMask, 141 m_Shuffle(m_Value(), m_Value(), m_SpecificMask(MaskData)))); 142 EXPECT_FALSE( 143 sd_match(VecShuffleWithMask, 144 m_Shuffle(m_Value(), m_Value(), m_SpecificMask(OtherMaskData)))); 145 EXPECT_TRUE( 146 std::equal(MaskData.begin(), MaskData.end(), Mask.begin(), Mask.end())); 147 } 148 149 TEST_F(SelectionDAGPatternMatchTest, matchTernaryOp) { 150 SDLoc DL; 151 auto Int32VT = EVT::getIntegerVT(Context, 32); 152 153 SDValue Op0 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, Int32VT); 154 SDValue Op1 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 2, Int32VT); 155 SDValue Op3 = DAG->getConstant(1, DL, Int32VT); 156 157 SDValue ICMP_UGT = DAG->getSetCC(DL, MVT::i1, Op0, Op1, ISD::SETUGT); 158 SDValue ICMP_EQ01 = DAG->getSetCC(DL, MVT::i1, Op0, Op1, ISD::SETEQ); 159 SDValue ICMP_EQ10 = DAG->getSetCC(DL, MVT::i1, Op1, Op0, ISD::SETEQ); 160 161 auto Int1VT = EVT::getIntegerVT(Context, 1); 162 SDValue Cond = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 3, Int1VT); 163 SDValue T = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 4, Int1VT); 164 SDValue F = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 5, Int1VT); 165 SDValue Select = DAG->getSelect(DL, MVT::i1, Cond, T, F); 166 167 auto VInt32VT = EVT::getVectorVT(Context, Int32VT, 4); 168 auto SmallVInt32VT = EVT::getVectorVT(Context, Int32VT, 2); 169 auto Idx0 = DAG->getVectorIdxConstant(0, DL); 170 auto Idx3 = DAG->getVectorIdxConstant(3, DL); 171 SDValue V1 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 6, VInt32VT); 172 SDValue V2 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 7, VInt32VT); 173 SDValue V3 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 8, SmallVInt32VT); 174 SDValue VSelect = DAG->getNode(ISD::VSELECT, DL, VInt32VT, Cond, V1, V2); 175 SDValue InsertSubvector = 176 DAG->getNode(ISD::INSERT_SUBVECTOR, DL, VInt32VT, V2, V3, Idx0); 177 178 SDValue ExtractELT = 179 DAG->getNode(ISD::EXTRACT_VECTOR_ELT, DL, Int32VT, V1, Op3); 180 181 using namespace SDPatternMatch; 182 ISD::CondCode CC; 183 EXPECT_TRUE(sd_match(ICMP_UGT, m_SetCC(m_Value(), m_Value(), 184 m_SpecificCondCode(ISD::SETUGT)))); 185 EXPECT_TRUE( 186 sd_match(ICMP_UGT, m_SetCC(m_Value(), m_Value(), m_CondCode(CC)))); 187 EXPECT_TRUE(CC == ISD::SETUGT); 188 EXPECT_FALSE(sd_match( 189 ICMP_UGT, m_SetCC(m_Value(), m_Value(), m_SpecificCondCode(ISD::SETLE)))); 190 191 EXPECT_TRUE(sd_match(ICMP_EQ01, m_SetCC(m_Specific(Op0), m_Specific(Op1), 192 m_SpecificCondCode(ISD::SETEQ)))); 193 EXPECT_TRUE(sd_match(ICMP_EQ10, m_SetCC(m_Specific(Op1), m_Specific(Op0), 194 m_SpecificCondCode(ISD::SETEQ)))); 195 EXPECT_FALSE(sd_match(ICMP_EQ01, m_SetCC(m_Specific(Op1), m_Specific(Op0), 196 m_SpecificCondCode(ISD::SETEQ)))); 197 EXPECT_FALSE(sd_match(ICMP_EQ10, m_SetCC(m_Specific(Op0), m_Specific(Op1), 198 m_SpecificCondCode(ISD::SETEQ)))); 199 EXPECT_TRUE(sd_match(ICMP_EQ01, m_c_SetCC(m_Specific(Op1), m_Specific(Op0), 200 m_SpecificCondCode(ISD::SETEQ)))); 201 EXPECT_TRUE(sd_match(ICMP_EQ10, m_c_SetCC(m_Specific(Op0), m_Specific(Op1), 202 m_SpecificCondCode(ISD::SETEQ)))); 203 204 EXPECT_TRUE(sd_match( 205 Select, m_Select(m_Specific(Cond), m_Specific(T), m_Specific(F)))); 206 EXPECT_FALSE(sd_match( 207 Select, m_Select(m_Specific(Cond), m_Specific(F), m_Specific(T)))); 208 EXPECT_FALSE(sd_match(ICMP_EQ01, m_Select(m_Specific(Op0), m_Specific(Op1), 209 m_SpecificCondCode(ISD::SETEQ)))); 210 EXPECT_TRUE(sd_match( 211 VSelect, m_VSelect(m_Specific(Cond), m_Specific(V1), m_Specific(V2)))); 212 EXPECT_FALSE(sd_match( 213 Select, m_VSelect(m_Specific(Cond), m_Specific(V1), m_Specific(V2)))); 214 215 EXPECT_TRUE(sd_match(ExtractELT, m_ExtractElt(m_Value(), m_Value()))); 216 EXPECT_TRUE(sd_match(ExtractELT, m_ExtractElt(m_Value(), m_ConstInt()))); 217 EXPECT_TRUE(sd_match(ExtractELT, m_ExtractElt(m_Value(), m_SpecificInt(1)))); 218 219 EXPECT_TRUE(sd_match(InsertSubvector, 220 m_InsertSubvector(m_Value(), m_Value(), m_Value()))); 221 EXPECT_TRUE(sd_match( 222 InsertSubvector, 223 m_InsertSubvector(m_Specific(V2), m_Specific(V3), m_Specific(Idx0)))); 224 EXPECT_TRUE(sd_match( 225 InsertSubvector, 226 m_InsertSubvector(m_Specific(V2), m_Specific(V3), m_SpecificInt(0)))); 227 EXPECT_FALSE(sd_match( 228 InsertSubvector, 229 m_InsertSubvector(m_Specific(V2), m_Specific(V3), m_Specific(Idx3)))); 230 EXPECT_FALSE(sd_match( 231 InsertSubvector, 232 m_InsertSubvector(m_Specific(V2), m_Specific(V3), m_SpecificInt(3)))); 233 } 234 235 TEST_F(SelectionDAGPatternMatchTest, matchBinaryOp) { 236 SDLoc DL; 237 auto Int32VT = EVT::getIntegerVT(Context, 32); 238 auto Float32VT = EVT::getFloatingPointVT(32); 239 auto BigVInt32VT = EVT::getVectorVT(Context, Int32VT, 8); 240 auto VInt32VT = EVT::getVectorVT(Context, Int32VT, 4); 241 242 SDValue V1 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 6, VInt32VT); 243 auto Idx0 = DAG->getVectorIdxConstant(0, DL); 244 auto Idx1 = DAG->getVectorIdxConstant(1, DL); 245 246 SDValue Op0 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, Int32VT); 247 SDValue Op1 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 2, Int32VT); 248 SDValue Op2 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 3, Float32VT); 249 SDValue Op3 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 8, Int32VT); 250 SDValue Op4 = DAG->getConstant(1, DL, Int32VT); 251 252 SDValue Add = DAG->getNode(ISD::ADD, DL, Int32VT, Op0, Op1); 253 SDValue Sub = DAG->getNode(ISD::SUB, DL, Int32VT, Add, Op0); 254 SDValue Mul = DAG->getNode(ISD::MUL, DL, Int32VT, Add, Sub); 255 SDValue And = DAG->getNode(ISD::AND, DL, Int32VT, Op0, Op1); 256 SDValue Xor = DAG->getNode(ISD::XOR, DL, Int32VT, Op1, Op0); 257 SDValue Or = DAG->getNode(ISD::OR, DL, Int32VT, Op0, Op1); 258 SDValue DisOr = 259 DAG->getNode(ISD::OR, DL, Int32VT, Op0, Op3, SDNodeFlags::Disjoint); 260 SDValue SMax = DAG->getNode(ISD::SMAX, DL, Int32VT, Op0, Op1); 261 SDValue SMin = DAG->getNode(ISD::SMIN, DL, Int32VT, Op1, Op0); 262 SDValue UMax = DAG->getNode(ISD::UMAX, DL, Int32VT, Op0, Op1); 263 SDValue UMin = DAG->getNode(ISD::UMIN, DL, Int32VT, Op1, Op0); 264 SDValue Rotl = DAG->getNode(ISD::ROTL, DL, Int32VT, Op0, Op1); 265 SDValue Rotr = DAG->getNode(ISD::ROTR, DL, Int32VT, Op1, Op0); 266 267 SDValue ICMP_GT = DAG->getSetCC(DL, MVT::i1, Op0, Op1, ISD::SETGT); 268 SDValue ICMP_GE = DAG->getSetCC(DL, MVT::i1, Op0, Op1, ISD::SETGE); 269 SDValue ICMP_UGT = DAG->getSetCC(DL, MVT::i1, Op0, Op1, ISD::SETUGT); 270 SDValue ICMP_UGE = DAG->getSetCC(DL, MVT::i1, Op0, Op1, ISD::SETUGE); 271 SDValue ICMP_LT = DAG->getSetCC(DL, MVT::i1, Op0, Op1, ISD::SETLT); 272 SDValue ICMP_LE = DAG->getSetCC(DL, MVT::i1, Op0, Op1, ISD::SETLE); 273 SDValue ICMP_ULT = DAG->getSetCC(DL, MVT::i1, Op0, Op1, ISD::SETULT); 274 SDValue ICMP_ULE = DAG->getSetCC(DL, MVT::i1, Op0, Op1, ISD::SETULE); 275 SDValue SMaxLikeGT = DAG->getSelect(DL, MVT::i32, ICMP_GT, Op0, Op1); 276 SDValue SMaxLikeGE = DAG->getSelect(DL, MVT::i32, ICMP_GE, Op0, Op1); 277 SDValue UMaxLikeUGT = DAG->getSelect(DL, MVT::i32, ICMP_UGT, Op0, Op1); 278 SDValue UMaxLikeUGE = DAG->getSelect(DL, MVT::i32, ICMP_UGE, Op0, Op1); 279 SDValue SMinLikeLT = DAG->getSelect(DL, MVT::i32, ICMP_LT, Op0, Op1); 280 SDValue SMinLikeLE = DAG->getSelect(DL, MVT::i32, ICMP_LE, Op0, Op1); 281 SDValue UMinLikeULT = DAG->getSelect(DL, MVT::i32, ICMP_ULT, Op0, Op1); 282 SDValue UMinLikeULE = DAG->getSelect(DL, MVT::i32, ICMP_ULE, Op0, Op1); 283 284 SDValue SFAdd = DAG->getNode(ISD::STRICT_FADD, DL, {Float32VT, MVT::Other}, 285 {DAG->getEntryNode(), Op2, Op2}); 286 287 SDValue Vec = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 9, BigVInt32VT); 288 SDValue SubVec = 289 DAG->getNode(ISD::EXTRACT_SUBVECTOR, DL, VInt32VT, Vec, Idx0); 290 291 SDValue InsertELT = 292 DAG->getNode(ISD::INSERT_VECTOR_ELT, DL, VInt32VT, V1, Op0, Op4); 293 294 using namespace SDPatternMatch; 295 EXPECT_TRUE(sd_match(Sub, m_BinOp(ISD::SUB, m_Value(), m_Value()))); 296 EXPECT_TRUE(sd_match(Sub, m_Sub(m_Value(), m_Value()))); 297 EXPECT_TRUE(sd_match(Add, m_c_BinOp(ISD::ADD, m_Value(), m_Value()))); 298 EXPECT_TRUE(sd_match(Add, m_Add(m_Value(), m_Value()))); 299 EXPECT_TRUE(sd_match(Add, m_AddLike(m_Value(), m_Value()))); 300 EXPECT_TRUE(sd_match( 301 Mul, m_Mul(m_OneUse(m_Opc(ISD::SUB)), m_NUses<2>(m_Specific(Add))))); 302 EXPECT_TRUE( 303 sd_match(SFAdd, m_ChainedBinOp(ISD::STRICT_FADD, m_SpecificVT(Float32VT), 304 m_SpecificVT(Float32VT)))); 305 306 EXPECT_TRUE(sd_match(And, m_c_BinOp(ISD::AND, m_Value(), m_Value()))); 307 EXPECT_TRUE(sd_match(And, m_And(m_Value(), m_Value()))); 308 EXPECT_TRUE(sd_match(Xor, m_c_BinOp(ISD::XOR, m_Value(), m_Value()))); 309 EXPECT_TRUE(sd_match(Xor, m_Xor(m_Value(), m_Value()))); 310 EXPECT_TRUE(sd_match(Or, m_c_BinOp(ISD::OR, m_Value(), m_Value()))); 311 EXPECT_TRUE(sd_match(Or, m_Or(m_Value(), m_Value()))); 312 EXPECT_FALSE(sd_match(Or, m_DisjointOr(m_Value(), m_Value()))); 313 314 EXPECT_TRUE(sd_match(DisOr, m_Or(m_Value(), m_Value()))); 315 EXPECT_TRUE(sd_match(DisOr, m_DisjointOr(m_Value(), m_Value()))); 316 EXPECT_FALSE(sd_match(DisOr, m_Add(m_Value(), m_Value()))); 317 EXPECT_TRUE(sd_match(DisOr, m_AddLike(m_Value(), m_Value()))); 318 319 EXPECT_TRUE(sd_match(Rotl, m_Rotl(m_Value(), m_Value()))); 320 EXPECT_TRUE(sd_match(Rotr, m_Rotr(m_Value(), m_Value()))); 321 EXPECT_FALSE(sd_match(Rotl, m_Rotr(m_Value(), m_Value()))); 322 EXPECT_FALSE(sd_match(Rotr, m_Rotl(m_Value(), m_Value()))); 323 324 EXPECT_TRUE(sd_match(SMax, m_c_BinOp(ISD::SMAX, m_Value(), m_Value()))); 325 EXPECT_TRUE(sd_match(SMax, m_SMax(m_Value(), m_Value()))); 326 EXPECT_TRUE(sd_match(SMax, m_SMaxLike(m_Value(), m_Value()))); 327 EXPECT_TRUE(sd_match(SMaxLikeGT, m_SMaxLike(m_Value(), m_Value()))); 328 EXPECT_TRUE(sd_match(SMaxLikeGE, m_SMaxLike(m_Value(), m_Value()))); 329 EXPECT_TRUE(sd_match(SMin, m_c_BinOp(ISD::SMIN, m_Value(), m_Value()))); 330 EXPECT_TRUE(sd_match(SMin, m_SMin(m_Value(), m_Value()))); 331 EXPECT_TRUE(sd_match(SMin, m_SMinLike(m_Value(), m_Value()))); 332 EXPECT_TRUE(sd_match(SMinLikeLT, m_SMinLike(m_Value(), m_Value()))); 333 EXPECT_TRUE(sd_match(SMinLikeLE, m_SMinLike(m_Value(), m_Value()))); 334 EXPECT_TRUE(sd_match(UMax, m_c_BinOp(ISD::UMAX, m_Value(), m_Value()))); 335 EXPECT_TRUE(sd_match(UMax, m_UMax(m_Value(), m_Value()))); 336 EXPECT_TRUE(sd_match(UMax, m_UMaxLike(m_Value(), m_Value()))); 337 EXPECT_TRUE(sd_match(UMaxLikeUGT, m_UMaxLike(m_Value(), m_Value()))); 338 EXPECT_TRUE(sd_match(UMaxLikeUGE, m_UMaxLike(m_Value(), m_Value()))); 339 EXPECT_TRUE(sd_match(UMin, m_c_BinOp(ISD::UMIN, m_Value(), m_Value()))); 340 EXPECT_TRUE(sd_match(UMin, m_UMin(m_Value(), m_Value()))); 341 EXPECT_TRUE(sd_match(UMin, m_UMinLike(m_Value(), m_Value()))); 342 EXPECT_TRUE(sd_match(UMinLikeULT, m_UMinLike(m_Value(), m_Value()))); 343 EXPECT_TRUE(sd_match(UMinLikeULE, m_UMinLike(m_Value(), m_Value()))); 344 345 SDValue BindVal; 346 EXPECT_TRUE(sd_match(SFAdd, m_ChainedBinOp(ISD::STRICT_FADD, m_Value(BindVal), 347 m_Deferred(BindVal)))); 348 EXPECT_FALSE(sd_match(SFAdd, m_ChainedBinOp(ISD::STRICT_FADD, m_OtherVT(), 349 m_SpecificVT(Float32VT)))); 350 351 EXPECT_TRUE(sd_match(SubVec, m_ExtractSubvector(m_Value(), m_Value()))); 352 EXPECT_TRUE( 353 sd_match(SubVec, m_ExtractSubvector(m_Specific(Vec), m_Specific(Idx0)))); 354 EXPECT_TRUE( 355 sd_match(SubVec, m_ExtractSubvector(m_Specific(Vec), m_SpecificInt(0)))); 356 EXPECT_FALSE( 357 sd_match(SubVec, m_ExtractSubvector(m_Specific(Vec), m_Specific(Idx1)))); 358 EXPECT_FALSE( 359 sd_match(SubVec, m_ExtractSubvector(m_Specific(Vec), m_SpecificInt(1)))); 360 361 EXPECT_TRUE( 362 sd_match(InsertELT, m_InsertElt(m_Value(), m_Value(), m_Value()))); 363 EXPECT_TRUE( 364 sd_match(InsertELT, m_InsertElt(m_Value(), m_Value(), m_ConstInt()))); 365 EXPECT_TRUE( 366 sd_match(InsertELT, m_InsertElt(m_Value(), m_Value(), m_SpecificInt(1)))); 367 } 368 369 TEST_F(SelectionDAGPatternMatchTest, matchUnaryOp) { 370 SDLoc DL; 371 auto Int32VT = EVT::getIntegerVT(Context, 32); 372 auto Int64VT = EVT::getIntegerVT(Context, 64); 373 auto FloatVT = EVT::getFloatingPointVT(32); 374 375 SDValue Op0 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, Int32VT); 376 SDValue Op1 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, Int64VT); 377 SDValue Op2 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, FloatVT); 378 SDValue Op3 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 3, Int32VT); 379 380 SDValue ZExt = DAG->getNode(ISD::ZERO_EXTEND, DL, Int64VT, Op0); 381 SDValue ZExtNNeg = 382 DAG->getNode(ISD::ZERO_EXTEND, DL, Int64VT, Op3, SDNodeFlags::NonNeg); 383 SDValue SExt = DAG->getNode(ISD::SIGN_EXTEND, DL, Int64VT, Op0); 384 SDValue Trunc = DAG->getNode(ISD::TRUNCATE, DL, Int32VT, Op1); 385 386 SDValue Sub = DAG->getNode(ISD::SUB, DL, Int32VT, Trunc, Op0); 387 SDValue Neg = DAG->getNegative(Op0, DL, Int32VT); 388 SDValue Not = DAG->getNOT(DL, Op0, Int32VT); 389 390 SDValue VScale = DAG->getVScale(DL, Int32VT, APInt::getMaxValue(32)); 391 392 SDValue FPToSI = DAG->getNode(ISD::FP_TO_SINT, DL, FloatVT, Op2); 393 SDValue FPToUI = DAG->getNode(ISD::FP_TO_UINT, DL, FloatVT, Op2); 394 395 SDValue Bcast = DAG->getNode(ISD::BITCAST, DL, FloatVT, Op0); 396 SDValue Brev = DAG->getNode(ISD::BITREVERSE, DL, Int32VT, Op0); 397 SDValue Bswap = DAG->getNode(ISD::BSWAP, DL, Int32VT, Op0); 398 399 SDValue Ctpop = DAG->getNode(ISD::CTPOP, DL, Int32VT, Op0); 400 SDValue Ctlz = DAG->getNode(ISD::CTLZ, DL, Int32VT, Op0); 401 SDValue Cttz = DAG->getNode(ISD::CTTZ, DL, Int32VT, Op0); 402 403 using namespace SDPatternMatch; 404 EXPECT_TRUE(sd_match(ZExt, m_UnaryOp(ISD::ZERO_EXTEND, m_Value()))); 405 EXPECT_TRUE(sd_match(SExt, m_SExt(m_Value()))); 406 EXPECT_TRUE(sd_match(SExt, m_SExtLike(m_Value()))); 407 ASSERT_TRUE(ZExtNNeg->getFlags().hasNonNeg()); 408 EXPECT_FALSE(sd_match(ZExtNNeg, m_SExt(m_Value()))); 409 EXPECT_TRUE(sd_match(ZExtNNeg, m_NNegZExt(m_Value()))); 410 EXPECT_FALSE(sd_match(ZExt, m_NNegZExt(m_Value()))); 411 EXPECT_TRUE(sd_match(ZExtNNeg, m_SExtLike(m_Value()))); 412 EXPECT_FALSE(sd_match(ZExt, m_SExtLike(m_Value()))); 413 EXPECT_TRUE(sd_match(Trunc, m_Trunc(m_Specific(Op1)))); 414 415 EXPECT_TRUE(sd_match(Neg, m_Neg(m_Value()))); 416 EXPECT_TRUE(sd_match(Not, m_Not(m_Value()))); 417 EXPECT_FALSE(sd_match(ZExt, m_Neg(m_Value()))); 418 EXPECT_FALSE(sd_match(Sub, m_Neg(m_Value()))); 419 EXPECT_FALSE(sd_match(Neg, m_Not(m_Value()))); 420 EXPECT_TRUE(sd_match(VScale, m_VScale(m_Value()))); 421 422 EXPECT_TRUE(sd_match(FPToUI, m_FPToUI(m_Value()))); 423 EXPECT_TRUE(sd_match(FPToSI, m_FPToSI(m_Value()))); 424 EXPECT_FALSE(sd_match(FPToUI, m_FPToSI(m_Value()))); 425 EXPECT_FALSE(sd_match(FPToSI, m_FPToUI(m_Value()))); 426 427 EXPECT_TRUE(sd_match(Bcast, m_BitCast(m_Value()))); 428 EXPECT_TRUE(sd_match(Bcast, m_BitCast(m_SpecificVT(MVT::i32)))); 429 EXPECT_TRUE(sd_match(Brev, m_BitReverse(m_Value()))); 430 EXPECT_TRUE(sd_match(Bswap, m_BSwap(m_Value()))); 431 EXPECT_FALSE(sd_match(Bcast, m_BitReverse(m_Value()))); 432 EXPECT_FALSE(sd_match(Bcast, m_BitCast(m_SpecificVT(MVT::f32)))); 433 EXPECT_FALSE(sd_match(Brev, m_BSwap(m_Value()))); 434 EXPECT_FALSE(sd_match(Bswap, m_BitReverse(m_Value()))); 435 436 EXPECT_TRUE(sd_match(Ctpop, m_Ctpop(m_Value()))); 437 EXPECT_TRUE(sd_match(Ctlz, m_Ctlz(m_Value()))); 438 EXPECT_TRUE(sd_match(Cttz, m_Cttz(m_Value()))); 439 EXPECT_FALSE(sd_match(Ctpop, m_Ctlz(m_Value()))); 440 EXPECT_FALSE(sd_match(Ctlz, m_Cttz(m_Value()))); 441 EXPECT_FALSE(sd_match(Cttz, m_Ctlz(m_Value()))); 442 } 443 444 TEST_F(SelectionDAGPatternMatchTest, matchConstants) { 445 SDLoc DL; 446 auto Int32VT = EVT::getIntegerVT(Context, 32); 447 auto VInt32VT = EVT::getVectorVT(Context, Int32VT, 4); 448 449 SDValue Arg0 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, Int32VT); 450 451 SDValue Const3 = DAG->getConstant(3, DL, Int32VT); 452 SDValue Const87 = DAG->getConstant(87, DL, Int32VT); 453 SDValue Splat = DAG->getSplat(VInt32VT, DL, Arg0); 454 SDValue ConstSplat = DAG->getSplat(VInt32VT, DL, Const3); 455 SDValue Zero = DAG->getConstant(0, DL, Int32VT); 456 SDValue One = DAG->getConstant(1, DL, Int32VT); 457 SDValue AllOnes = DAG->getConstant(APInt::getAllOnes(32), DL, Int32VT); 458 SDValue SetCC = DAG->getSetCC(DL, Int32VT, Arg0, Const3, ISD::SETULT); 459 460 using namespace SDPatternMatch; 461 EXPECT_TRUE(sd_match(Const87, m_ConstInt())); 462 EXPECT_FALSE(sd_match(Arg0, m_ConstInt())); 463 APInt ConstVal; 464 EXPECT_TRUE(sd_match(ConstSplat, m_ConstInt(ConstVal))); 465 EXPECT_EQ(ConstVal, 3); 466 EXPECT_FALSE(sd_match(Splat, m_ConstInt())); 467 468 EXPECT_TRUE(sd_match(Const87, m_SpecificInt(87))); 469 EXPECT_TRUE(sd_match(Const3, m_SpecificInt(ConstVal))); 470 EXPECT_TRUE(sd_match(AllOnes, m_AllOnes())); 471 472 EXPECT_TRUE(sd_match(Zero, DAG.get(), m_False())); 473 EXPECT_TRUE(sd_match(One, DAG.get(), m_True())); 474 EXPECT_FALSE(sd_match(AllOnes, DAG.get(), m_True())); 475 476 ISD::CondCode CC; 477 EXPECT_TRUE(sd_match( 478 SetCC, m_Node(ISD::SETCC, m_Value(), m_Value(), m_CondCode(CC)))); 479 EXPECT_EQ(CC, ISD::SETULT); 480 EXPECT_TRUE(sd_match(SetCC, m_Node(ISD::SETCC, m_Value(), m_Value(), 481 m_SpecificCondCode(ISD::SETULT)))); 482 483 SDValue UndefInt32VT = DAG->getUNDEF(Int32VT); 484 SDValue UndefVInt32VT = DAG->getUNDEF(VInt32VT); 485 EXPECT_TRUE(sd_match(UndefInt32VT, m_Undef())); 486 EXPECT_TRUE(sd_match(UndefVInt32VT, m_Undef())); 487 } 488 489 TEST_F(SelectionDAGPatternMatchTest, patternCombinators) { 490 SDLoc DL; 491 auto Int32VT = EVT::getIntegerVT(Context, 32); 492 493 SDValue Op0 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, Int32VT); 494 SDValue Op1 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 2, Int32VT); 495 496 SDValue Add = DAG->getNode(ISD::ADD, DL, Int32VT, Op0, Op1); 497 SDValue Sub = DAG->getNode(ISD::SUB, DL, Int32VT, Add, Op0); 498 499 using namespace SDPatternMatch; 500 EXPECT_TRUE(sd_match( 501 Sub, m_AnyOf(m_Opc(ISD::ADD), m_Opc(ISD::SUB), m_Opc(ISD::MUL)))); 502 EXPECT_TRUE(sd_match(Add, m_AllOf(m_Opc(ISD::ADD), m_OneUse()))); 503 EXPECT_TRUE(sd_match(Add, m_NoneOf(m_Opc(ISD::SUB), m_Opc(ISD::MUL)))); 504 } 505 506 TEST_F(SelectionDAGPatternMatchTest, optionalResizing) { 507 SDLoc DL; 508 auto Int32VT = EVT::getIntegerVT(Context, 32); 509 auto Int64VT = EVT::getIntegerVT(Context, 64); 510 511 SDValue Op32 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, Int32VT); 512 SDValue Op64 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, Int64VT); 513 SDValue ZExt = DAG->getNode(ISD::ZERO_EXTEND, DL, Int64VT, Op32); 514 SDValue SExt = DAG->getNode(ISD::SIGN_EXTEND, DL, Int64VT, Op32); 515 SDValue AExt = DAG->getNode(ISD::ANY_EXTEND, DL, Int64VT, Op32); 516 SDValue Trunc = DAG->getNode(ISD::TRUNCATE, DL, Int32VT, Op64); 517 518 using namespace SDPatternMatch; 519 SDValue A; 520 EXPECT_TRUE(sd_match(Op32, m_ZExtOrSelf(m_Value(A)))); 521 EXPECT_TRUE(A == Op32); 522 EXPECT_TRUE(sd_match(ZExt, m_ZExtOrSelf(m_Value(A)))); 523 EXPECT_TRUE(A == Op32); 524 EXPECT_TRUE(sd_match(Op64, m_SExtOrSelf(m_Value(A)))); 525 EXPECT_TRUE(A == Op64); 526 EXPECT_TRUE(sd_match(SExt, m_SExtOrSelf(m_Value(A)))); 527 EXPECT_TRUE(A == Op32); 528 EXPECT_TRUE(sd_match(Op32, m_AExtOrSelf(m_Value(A)))); 529 EXPECT_TRUE(A == Op32); 530 EXPECT_TRUE(sd_match(AExt, m_AExtOrSelf(m_Value(A)))); 531 EXPECT_TRUE(A == Op32); 532 EXPECT_TRUE(sd_match(Op64, m_TruncOrSelf(m_Value(A)))); 533 EXPECT_TRUE(A == Op64); 534 EXPECT_TRUE(sd_match(Trunc, m_TruncOrSelf(m_Value(A)))); 535 EXPECT_TRUE(A == Op64); 536 } 537 538 TEST_F(SelectionDAGPatternMatchTest, matchNode) { 539 SDLoc DL; 540 auto Int32VT = EVT::getIntegerVT(Context, 32); 541 542 SDValue Op0 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, Int32VT); 543 SDValue Op1 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 2, Int32VT); 544 545 SDValue Add = DAG->getNode(ISD::ADD, DL, Int32VT, Op0, Op1); 546 547 using namespace SDPatternMatch; 548 EXPECT_TRUE(sd_match(Add, m_Node(ISD::ADD, m_Value(), m_Value()))); 549 EXPECT_FALSE(sd_match(Add, m_Node(ISD::SUB, m_Value(), m_Value()))); 550 EXPECT_FALSE(sd_match(Add, m_Node(ISD::ADD, m_Value()))); 551 EXPECT_FALSE( 552 sd_match(Add, m_Node(ISD::ADD, m_Value(), m_Value(), m_Value()))); 553 EXPECT_FALSE(sd_match(Add, m_Node(ISD::ADD, m_ConstInt(), m_Value()))); 554 } 555 556 namespace { 557 struct VPMatchContext : public SDPatternMatch::BasicMatchContext { 558 using SDPatternMatch::BasicMatchContext::BasicMatchContext; 559 560 bool match(SDValue OpVal, unsigned Opc) const { 561 if (!OpVal->isVPOpcode()) 562 return OpVal->getOpcode() == Opc; 563 564 auto BaseOpc = ISD::getBaseOpcodeForVP(OpVal->getOpcode(), false); 565 return BaseOpc.has_value() && *BaseOpc == Opc; 566 } 567 568 unsigned getNumOperands(SDValue N) const { 569 return N->isVPOpcode() ? N->getNumOperands() - 2 : N->getNumOperands(); 570 } 571 }; 572 } // anonymous namespace 573 TEST_F(SelectionDAGPatternMatchTest, matchContext) { 574 SDLoc DL; 575 auto BoolVT = EVT::getIntegerVT(Context, 1); 576 auto Int32VT = EVT::getIntegerVT(Context, 32); 577 auto VInt32VT = EVT::getVectorVT(Context, Int32VT, 4); 578 auto MaskVT = EVT::getVectorVT(Context, BoolVT, 4); 579 580 SDValue Scalar0 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, Int32VT); 581 SDValue Vector0 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 2, VInt32VT); 582 SDValue Mask0 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 3, MaskVT); 583 584 SDValue VPAdd = DAG->getNode(ISD::VP_ADD, DL, VInt32VT, 585 {Vector0, Vector0, Mask0, Scalar0}); 586 SDValue VPReduceAdd = DAG->getNode(ISD::VP_REDUCE_ADD, DL, Int32VT, 587 {Scalar0, VPAdd, Mask0, Scalar0}); 588 SDValue Add = DAG->getNode(ISD::ADD, DL, VInt32VT, {Vector0, Vector0}); 589 590 using namespace SDPatternMatch; 591 VPMatchContext VPCtx(DAG.get()); 592 EXPECT_TRUE(sd_context_match(VPAdd, VPCtx, m_Opc(ISD::ADD))); 593 EXPECT_TRUE( 594 sd_context_match(VPAdd, VPCtx, m_Node(ISD::ADD, m_Value(), m_Value()))); 595 // VPMatchContext can't match pattern using explicit VP Opcode 596 EXPECT_FALSE(sd_context_match(VPAdd, VPCtx, 597 m_Node(ISD::VP_ADD, m_Value(), m_Value()))); 598 EXPECT_FALSE(sd_context_match( 599 VPAdd, VPCtx, 600 m_Node(ISD::VP_ADD, m_Value(), m_Value(), m_Value(), m_Value()))); 601 // Check Binary Op Pattern 602 EXPECT_TRUE(sd_context_match(VPAdd, VPCtx, m_Add(m_Value(), m_Value()))); 603 // VP_REDUCE_ADD doesn't have a based opcode, so we use a normal 604 // sd_match before switching to VPMatchContext when checking VPAdd. 605 EXPECT_TRUE(sd_match(VPReduceAdd, m_Node(ISD::VP_REDUCE_ADD, m_Value(), 606 m_Context(VPCtx, m_Opc(ISD::ADD)), 607 m_Value(), m_Value()))); 608 // non-vector predicated should match too 609 EXPECT_TRUE(sd_context_match(Add, VPCtx, m_Opc(ISD::ADD))); 610 EXPECT_TRUE( 611 sd_context_match(Add, VPCtx, m_Node(ISD::ADD, m_Value(), m_Value()))); 612 EXPECT_FALSE(sd_context_match( 613 Add, VPCtx, 614 m_Node(ISD::ADD, m_Value(), m_Value(), m_Value(), m_Value()))); 615 EXPECT_TRUE(sd_context_match(Add, VPCtx, m_Add(m_Value(), m_Value()))); 616 } 617 618 TEST_F(SelectionDAGPatternMatchTest, matchVPWithBasicContext) { 619 SDLoc DL; 620 auto BoolVT = EVT::getIntegerVT(Context, 1); 621 auto Int32VT = EVT::getIntegerVT(Context, 32); 622 auto VInt32VT = EVT::getVectorVT(Context, Int32VT, 4); 623 auto MaskVT = EVT::getVectorVT(Context, BoolVT, 4); 624 625 SDValue Vector0 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, VInt32VT); 626 SDValue Mask = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 2, MaskVT); 627 SDValue EL = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 3, Int32VT); 628 629 SDValue VPAdd = 630 DAG->getNode(ISD::VP_ADD, DL, VInt32VT, Vector0, Vector0, Mask, EL); 631 632 using namespace SDPatternMatch; 633 EXPECT_FALSE(sd_match(VPAdd, m_Node(ISD::VP_ADD, m_Value(), m_Value()))); 634 EXPECT_TRUE(sd_match( 635 VPAdd, m_Node(ISD::VP_ADD, m_Value(), m_Value(), m_Value(), m_Value()))); 636 } 637 638 TEST_F(SelectionDAGPatternMatchTest, matchAdvancedProperties) { 639 SDLoc DL; 640 auto Int16VT = EVT::getIntegerVT(Context, 16); 641 auto Int64VT = EVT::getIntegerVT(Context, 64); 642 643 SDValue Op0 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, Int64VT); 644 SDValue Op1 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 2, Int16VT); 645 646 SDValue Add = DAG->getNode(ISD::ADD, DL, Int64VT, Op0, Op0); 647 648 using namespace SDPatternMatch; 649 EXPECT_TRUE(sd_match(Op0, DAG.get(), m_LegalType(m_Value()))); 650 EXPECT_FALSE(sd_match(Op1, DAG.get(), m_LegalType(m_Value()))); 651 EXPECT_TRUE(sd_match(Add, DAG.get(), 652 m_LegalOp(m_IntegerVT(m_Add(m_Value(), m_Value()))))); 653 } 654