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<LLVMTargetMachine>(static_cast<LLVMTargetMachine *>( 49 T->createTargetMachine("riscv64", "", "+m,+f,+d,+v", Options, 50 std::nullopt, std::nullopt, 51 CodeGenOptLevel::Aggressive))); 52 if (!TM) 53 GTEST_SKIP(); 54 55 SMDiagnostic SMError; 56 M = parseAssemblyString(Assembly, SMError, Context); 57 if (!M) 58 report_fatal_error(SMError.getMessage()); 59 M->setDataLayout(TM->createDataLayout()); 60 61 F = M->getFunction("f"); 62 if (!F) 63 report_fatal_error("F?"); 64 G = M->getGlobalVariable("g"); 65 if (!G) 66 report_fatal_error("G?"); 67 AliasedG = M->getNamedAlias("g_alias"); 68 if (!AliasedG) 69 report_fatal_error("AliasedG?"); 70 71 MachineModuleInfo MMI(TM.get()); 72 73 MF = std::make_unique<MachineFunction>(*F, *TM, *TM->getSubtargetImpl(*F), 74 MMI.getContext(), 0); 75 76 DAG = std::make_unique<SelectionDAG>(*TM, CodeGenOptLevel::None); 77 if (!DAG) 78 report_fatal_error("DAG?"); 79 OptimizationRemarkEmitter ORE(F); 80 DAG->init(*MF, ORE, nullptr, nullptr, nullptr, nullptr, nullptr, MMI, 81 nullptr); 82 } 83 84 TargetLoweringBase::LegalizeTypeAction getTypeAction(EVT VT) { 85 return DAG->getTargetLoweringInfo().getTypeAction(Context, VT); 86 } 87 88 EVT getTypeToTransformTo(EVT VT) { 89 return DAG->getTargetLoweringInfo().getTypeToTransformTo(Context, VT); 90 } 91 92 LLVMContext Context; 93 std::unique_ptr<LLVMTargetMachine> TM; 94 std::unique_ptr<Module> M; 95 Function *F; 96 GlobalVariable *G; 97 GlobalAlias *AliasedG; 98 std::unique_ptr<MachineFunction> MF; 99 std::unique_ptr<SelectionDAG> DAG; 100 }; 101 102 TEST_F(SelectionDAGPatternMatchTest, matchValueType) { 103 SDLoc DL; 104 auto Int32VT = EVT::getIntegerVT(Context, 32); 105 auto Float32VT = EVT::getFloatingPointVT(32); 106 auto VInt32VT = EVT::getVectorVT(Context, Int32VT, 4); 107 108 SDValue Op0 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, Int32VT); 109 SDValue Op1 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 2, Float32VT); 110 SDValue Op2 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 2, VInt32VT); 111 112 using namespace SDPatternMatch; 113 EXPECT_TRUE(sd_match(Op0, m_SpecificVT(Int32VT))); 114 EVT BindVT; 115 EXPECT_TRUE(sd_match(Op1, m_VT(BindVT))); 116 EXPECT_EQ(BindVT, Float32VT); 117 EXPECT_TRUE(sd_match(Op0, m_IntegerVT())); 118 EXPECT_TRUE(sd_match(Op1, m_FloatingPointVT())); 119 EXPECT_TRUE(sd_match(Op2, m_VectorVT())); 120 EXPECT_FALSE(sd_match(Op2, m_ScalableVectorVT())); 121 } 122 123 TEST_F(SelectionDAGPatternMatchTest, matchTernaryOp) { 124 SDLoc DL; 125 auto Int32VT = EVT::getIntegerVT(Context, 32); 126 127 SDValue Op0 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, Int32VT); 128 SDValue Op1 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 2, Int32VT); 129 130 SDValue ICMP_UGT = DAG->getSetCC(DL, MVT::i1, Op0, Op1, ISD::SETUGT); 131 SDValue ICMP_EQ01 = DAG->getSetCC(DL, MVT::i1, Op0, Op1, ISD::SETEQ); 132 SDValue ICMP_EQ10 = DAG->getSetCC(DL, MVT::i1, Op1, Op0, ISD::SETEQ); 133 134 auto Int1VT = EVT::getIntegerVT(Context, 1); 135 SDValue Cond = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 3, Int1VT); 136 SDValue T = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 4, Int1VT); 137 SDValue F = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 5, Int1VT); 138 SDValue Select = DAG->getSelect(DL, MVT::i1, Cond, T, F); 139 140 auto VInt32VT = EVT::getVectorVT(Context, Int32VT, 4); 141 SDValue V1 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 6, VInt32VT); 142 SDValue V2 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 7, VInt32VT); 143 SDValue VSelect = DAG->getNode(ISD::VSELECT, DL, VInt32VT, Cond, V1, V2); 144 145 using namespace SDPatternMatch; 146 ISD::CondCode CC; 147 EXPECT_TRUE(sd_match(ICMP_UGT, m_SetCC(m_Value(), m_Value(), 148 m_SpecificCondCode(ISD::SETUGT)))); 149 EXPECT_TRUE( 150 sd_match(ICMP_UGT, m_SetCC(m_Value(), m_Value(), m_CondCode(CC)))); 151 EXPECT_TRUE(CC == ISD::SETUGT); 152 EXPECT_FALSE(sd_match( 153 ICMP_UGT, m_SetCC(m_Value(), m_Value(), m_SpecificCondCode(ISD::SETLE)))); 154 155 EXPECT_TRUE(sd_match(ICMP_EQ01, m_SetCC(m_Specific(Op0), m_Specific(Op1), 156 m_SpecificCondCode(ISD::SETEQ)))); 157 EXPECT_TRUE(sd_match(ICMP_EQ10, m_SetCC(m_Specific(Op1), m_Specific(Op0), 158 m_SpecificCondCode(ISD::SETEQ)))); 159 EXPECT_FALSE(sd_match(ICMP_EQ01, m_SetCC(m_Specific(Op1), m_Specific(Op0), 160 m_SpecificCondCode(ISD::SETEQ)))); 161 EXPECT_FALSE(sd_match(ICMP_EQ10, m_SetCC(m_Specific(Op0), m_Specific(Op1), 162 m_SpecificCondCode(ISD::SETEQ)))); 163 EXPECT_TRUE(sd_match(ICMP_EQ01, m_c_SetCC(m_Specific(Op1), m_Specific(Op0), 164 m_SpecificCondCode(ISD::SETEQ)))); 165 EXPECT_TRUE(sd_match(ICMP_EQ10, m_c_SetCC(m_Specific(Op0), m_Specific(Op1), 166 m_SpecificCondCode(ISD::SETEQ)))); 167 168 EXPECT_TRUE(sd_match( 169 Select, m_Select(m_Specific(Cond), m_Specific(T), m_Specific(F)))); 170 EXPECT_FALSE(sd_match( 171 Select, m_Select(m_Specific(Cond), m_Specific(F), m_Specific(T)))); 172 EXPECT_FALSE(sd_match(ICMP_EQ01, m_Select(m_Specific(Op0), m_Specific(Op1), 173 m_SpecificCondCode(ISD::SETEQ)))); 174 EXPECT_TRUE(sd_match( 175 VSelect, m_VSelect(m_Specific(Cond), m_Specific(V1), m_Specific(V2)))); 176 EXPECT_FALSE(sd_match( 177 Select, m_VSelect(m_Specific(Cond), m_Specific(V1), m_Specific(V2)))); 178 } 179 180 TEST_F(SelectionDAGPatternMatchTest, matchBinaryOp) { 181 SDLoc DL; 182 auto Int32VT = EVT::getIntegerVT(Context, 32); 183 auto Float32VT = EVT::getFloatingPointVT(32); 184 185 SDValue Op0 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, Int32VT); 186 SDValue Op1 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 2, Int32VT); 187 SDValue Op2 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 3, Float32VT); 188 SDValue Op3 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 8, Int32VT); 189 190 SDValue Add = DAG->getNode(ISD::ADD, DL, Int32VT, Op0, Op1); 191 SDValue Sub = DAG->getNode(ISD::SUB, DL, Int32VT, Add, Op0); 192 SDValue Mul = DAG->getNode(ISD::MUL, DL, Int32VT, Add, Sub); 193 SDValue And = DAG->getNode(ISD::AND, DL, Int32VT, Op0, Op1); 194 SDValue Xor = DAG->getNode(ISD::XOR, DL, Int32VT, Op1, Op0); 195 SDValue Or = DAG->getNode(ISD::OR, DL, Int32VT, Op0, Op1); 196 SDValue DisOr = 197 DAG->getNode(ISD::OR, DL, Int32VT, Op0, Op3, SDNodeFlags::Disjoint); 198 SDValue SMax = DAG->getNode(ISD::SMAX, DL, Int32VT, Op0, Op1); 199 SDValue SMin = DAG->getNode(ISD::SMIN, DL, Int32VT, Op1, Op0); 200 SDValue UMax = DAG->getNode(ISD::UMAX, DL, Int32VT, Op0, Op1); 201 SDValue UMin = DAG->getNode(ISD::UMIN, DL, Int32VT, Op1, Op0); 202 SDValue Rotl = DAG->getNode(ISD::ROTL, DL, Int32VT, Op0, Op1); 203 SDValue Rotr = DAG->getNode(ISD::ROTR, DL, Int32VT, Op1, Op0); 204 205 SDValue ICMP_GT = DAG->getSetCC(DL, MVT::i1, Op0, Op1, ISD::SETGT); 206 SDValue ICMP_GE = DAG->getSetCC(DL, MVT::i1, Op0, Op1, ISD::SETGE); 207 SDValue ICMP_UGT = DAG->getSetCC(DL, MVT::i1, Op0, Op1, ISD::SETUGT); 208 SDValue ICMP_UGE = DAG->getSetCC(DL, MVT::i1, Op0, Op1, ISD::SETUGE); 209 SDValue ICMP_LT = DAG->getSetCC(DL, MVT::i1, Op0, Op1, ISD::SETLT); 210 SDValue ICMP_LE = DAG->getSetCC(DL, MVT::i1, Op0, Op1, ISD::SETLE); 211 SDValue ICMP_ULT = DAG->getSetCC(DL, MVT::i1, Op0, Op1, ISD::SETULT); 212 SDValue ICMP_ULE = DAG->getSetCC(DL, MVT::i1, Op0, Op1, ISD::SETULE); 213 SDValue SMaxLikeGT = DAG->getSelect(DL, MVT::i32, ICMP_GT, Op0, Op1); 214 SDValue SMaxLikeGE = DAG->getSelect(DL, MVT::i32, ICMP_GE, Op0, Op1); 215 SDValue UMaxLikeUGT = DAG->getSelect(DL, MVT::i32, ICMP_UGT, Op0, Op1); 216 SDValue UMaxLikeUGE = DAG->getSelect(DL, MVT::i32, ICMP_UGE, Op0, Op1); 217 SDValue SMinLikeLT = DAG->getSelect(DL, MVT::i32, ICMP_LT, Op0, Op1); 218 SDValue SMinLikeLE = DAG->getSelect(DL, MVT::i32, ICMP_LE, Op0, Op1); 219 SDValue UMinLikeULT = DAG->getSelect(DL, MVT::i32, ICMP_ULT, Op0, Op1); 220 SDValue UMinLikeULE = DAG->getSelect(DL, MVT::i32, ICMP_ULE, Op0, Op1); 221 222 SDValue SFAdd = DAG->getNode(ISD::STRICT_FADD, DL, {Float32VT, MVT::Other}, 223 {DAG->getEntryNode(), Op2, Op2}); 224 225 using namespace SDPatternMatch; 226 EXPECT_TRUE(sd_match(Sub, m_BinOp(ISD::SUB, m_Value(), m_Value()))); 227 EXPECT_TRUE(sd_match(Sub, m_Sub(m_Value(), m_Value()))); 228 EXPECT_TRUE(sd_match(Add, m_c_BinOp(ISD::ADD, m_Value(), m_Value()))); 229 EXPECT_TRUE(sd_match(Add, m_Add(m_Value(), m_Value()))); 230 EXPECT_TRUE(sd_match(Add, m_AddLike(m_Value(), m_Value()))); 231 EXPECT_TRUE(sd_match( 232 Mul, m_Mul(m_OneUse(m_Opc(ISD::SUB)), m_NUses<2>(m_Specific(Add))))); 233 EXPECT_TRUE( 234 sd_match(SFAdd, m_ChainedBinOp(ISD::STRICT_FADD, m_SpecificVT(Float32VT), 235 m_SpecificVT(Float32VT)))); 236 237 EXPECT_TRUE(sd_match(And, m_c_BinOp(ISD::AND, m_Value(), m_Value()))); 238 EXPECT_TRUE(sd_match(And, m_And(m_Value(), m_Value()))); 239 EXPECT_TRUE(sd_match(Xor, m_c_BinOp(ISD::XOR, m_Value(), m_Value()))); 240 EXPECT_TRUE(sd_match(Xor, m_Xor(m_Value(), m_Value()))); 241 EXPECT_TRUE(sd_match(Or, m_c_BinOp(ISD::OR, m_Value(), m_Value()))); 242 EXPECT_TRUE(sd_match(Or, m_Or(m_Value(), m_Value()))); 243 EXPECT_FALSE(sd_match(Or, m_DisjointOr(m_Value(), m_Value()))); 244 245 EXPECT_TRUE(sd_match(DisOr, m_Or(m_Value(), m_Value()))); 246 EXPECT_TRUE(sd_match(DisOr, m_DisjointOr(m_Value(), m_Value()))); 247 EXPECT_FALSE(sd_match(DisOr, m_Add(m_Value(), m_Value()))); 248 EXPECT_TRUE(sd_match(DisOr, m_AddLike(m_Value(), m_Value()))); 249 250 EXPECT_TRUE(sd_match(Rotl, m_Rotl(m_Value(), m_Value()))); 251 EXPECT_TRUE(sd_match(Rotr, m_Rotr(m_Value(), m_Value()))); 252 EXPECT_FALSE(sd_match(Rotl, m_Rotr(m_Value(), m_Value()))); 253 EXPECT_FALSE(sd_match(Rotr, m_Rotl(m_Value(), m_Value()))); 254 255 EXPECT_TRUE(sd_match(SMax, m_c_BinOp(ISD::SMAX, m_Value(), m_Value()))); 256 EXPECT_TRUE(sd_match(SMax, m_SMax(m_Value(), m_Value()))); 257 EXPECT_TRUE(sd_match(SMax, m_SMaxLike(m_Value(), m_Value()))); 258 EXPECT_TRUE(sd_match(SMaxLikeGT, m_SMaxLike(m_Value(), m_Value()))); 259 EXPECT_TRUE(sd_match(SMaxLikeGE, m_SMaxLike(m_Value(), m_Value()))); 260 EXPECT_TRUE(sd_match(SMin, m_c_BinOp(ISD::SMIN, m_Value(), m_Value()))); 261 EXPECT_TRUE(sd_match(SMin, m_SMin(m_Value(), m_Value()))); 262 EXPECT_TRUE(sd_match(SMin, m_SMinLike(m_Value(), m_Value()))); 263 EXPECT_TRUE(sd_match(SMinLikeLT, m_SMinLike(m_Value(), m_Value()))); 264 EXPECT_TRUE(sd_match(SMinLikeLE, m_SMinLike(m_Value(), m_Value()))); 265 EXPECT_TRUE(sd_match(UMax, m_c_BinOp(ISD::UMAX, m_Value(), m_Value()))); 266 EXPECT_TRUE(sd_match(UMax, m_UMax(m_Value(), m_Value()))); 267 EXPECT_TRUE(sd_match(UMax, m_UMaxLike(m_Value(), m_Value()))); 268 EXPECT_TRUE(sd_match(UMaxLikeUGT, m_UMaxLike(m_Value(), m_Value()))); 269 EXPECT_TRUE(sd_match(UMaxLikeUGE, m_UMaxLike(m_Value(), m_Value()))); 270 EXPECT_TRUE(sd_match(UMin, m_c_BinOp(ISD::UMIN, m_Value(), m_Value()))); 271 EXPECT_TRUE(sd_match(UMin, m_UMin(m_Value(), m_Value()))); 272 EXPECT_TRUE(sd_match(UMin, m_UMinLike(m_Value(), m_Value()))); 273 EXPECT_TRUE(sd_match(UMinLikeULT, m_UMinLike(m_Value(), m_Value()))); 274 EXPECT_TRUE(sd_match(UMinLikeULE, m_UMinLike(m_Value(), m_Value()))); 275 276 SDValue BindVal; 277 EXPECT_TRUE(sd_match(SFAdd, m_ChainedBinOp(ISD::STRICT_FADD, m_Value(BindVal), 278 m_Deferred(BindVal)))); 279 EXPECT_FALSE(sd_match(SFAdd, m_ChainedBinOp(ISD::STRICT_FADD, m_OtherVT(), 280 m_SpecificVT(Float32VT)))); 281 } 282 283 TEST_F(SelectionDAGPatternMatchTest, matchUnaryOp) { 284 SDLoc DL; 285 auto Int32VT = EVT::getIntegerVT(Context, 32); 286 auto Int64VT = EVT::getIntegerVT(Context, 64); 287 auto FloatVT = EVT::getFloatingPointVT(32); 288 289 SDValue Op0 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, Int32VT); 290 SDValue Op1 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, Int64VT); 291 SDValue Op2 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, FloatVT); 292 SDValue Op3 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 3, Int32VT); 293 294 SDValue ZExt = DAG->getNode(ISD::ZERO_EXTEND, DL, Int64VT, Op0); 295 SDValue ZExtNNeg = 296 DAG->getNode(ISD::ZERO_EXTEND, DL, Int64VT, Op3, SDNodeFlags::NonNeg); 297 SDValue SExt = DAG->getNode(ISD::SIGN_EXTEND, DL, Int64VT, Op0); 298 SDValue Trunc = DAG->getNode(ISD::TRUNCATE, DL, Int32VT, Op1); 299 300 SDValue Sub = DAG->getNode(ISD::SUB, DL, Int32VT, Trunc, Op0); 301 SDValue Neg = DAG->getNegative(Op0, DL, Int32VT); 302 SDValue Not = DAG->getNOT(DL, Op0, Int32VT); 303 304 SDValue VScale = DAG->getVScale(DL, Int32VT, APInt::getMaxValue(32)); 305 306 SDValue FPToSI = DAG->getNode(ISD::FP_TO_SINT, DL, FloatVT, Op2); 307 SDValue FPToUI = DAG->getNode(ISD::FP_TO_UINT, DL, FloatVT, Op2); 308 309 SDValue Brev = DAG->getNode(ISD::BITREVERSE, DL, Int32VT, Op0); 310 SDValue Bswap = DAG->getNode(ISD::BSWAP, DL, Int32VT, Op0); 311 312 SDValue Ctpop = DAG->getNode(ISD::CTPOP, DL, Int32VT, Op0); 313 SDValue Ctlz = DAG->getNode(ISD::CTLZ, DL, Int32VT, Op0); 314 SDValue Cttz = DAG->getNode(ISD::CTTZ, DL, Int32VT, Op0); 315 316 using namespace SDPatternMatch; 317 EXPECT_TRUE(sd_match(ZExt, m_UnaryOp(ISD::ZERO_EXTEND, m_Value()))); 318 EXPECT_TRUE(sd_match(SExt, m_SExt(m_Value()))); 319 EXPECT_TRUE(sd_match(SExt, m_SExtLike(m_Value()))); 320 ASSERT_TRUE(ZExtNNeg->getFlags().hasNonNeg()); 321 EXPECT_FALSE(sd_match(ZExtNNeg, m_SExt(m_Value()))); 322 EXPECT_TRUE(sd_match(ZExtNNeg, m_NNegZExt(m_Value()))); 323 EXPECT_FALSE(sd_match(ZExt, m_NNegZExt(m_Value()))); 324 EXPECT_TRUE(sd_match(ZExtNNeg, m_SExtLike(m_Value()))); 325 EXPECT_FALSE(sd_match(ZExt, m_SExtLike(m_Value()))); 326 EXPECT_TRUE(sd_match(Trunc, m_Trunc(m_Specific(Op1)))); 327 328 EXPECT_TRUE(sd_match(Neg, m_Neg(m_Value()))); 329 EXPECT_TRUE(sd_match(Not, m_Not(m_Value()))); 330 EXPECT_FALSE(sd_match(ZExt, m_Neg(m_Value()))); 331 EXPECT_FALSE(sd_match(Sub, m_Neg(m_Value()))); 332 EXPECT_FALSE(sd_match(Neg, m_Not(m_Value()))); 333 EXPECT_TRUE(sd_match(VScale, m_VScale(m_Value()))); 334 335 EXPECT_TRUE(sd_match(FPToUI, m_FPToUI(m_Value()))); 336 EXPECT_TRUE(sd_match(FPToSI, m_FPToSI(m_Value()))); 337 EXPECT_FALSE(sd_match(FPToUI, m_FPToSI(m_Value()))); 338 EXPECT_FALSE(sd_match(FPToSI, m_FPToUI(m_Value()))); 339 340 EXPECT_TRUE(sd_match(Brev, m_BitReverse(m_Value()))); 341 EXPECT_TRUE(sd_match(Bswap, m_BSwap(m_Value()))); 342 EXPECT_FALSE(sd_match(Brev, m_BSwap(m_Value()))); 343 EXPECT_FALSE(sd_match(Bswap, m_BitReverse(m_Value()))); 344 345 EXPECT_TRUE(sd_match(Ctpop, m_Ctpop(m_Value()))); 346 EXPECT_TRUE(sd_match(Ctlz, m_Ctlz(m_Value()))); 347 EXPECT_TRUE(sd_match(Cttz, m_Cttz(m_Value()))); 348 EXPECT_FALSE(sd_match(Ctpop, m_Ctlz(m_Value()))); 349 EXPECT_FALSE(sd_match(Ctlz, m_Cttz(m_Value()))); 350 EXPECT_FALSE(sd_match(Cttz, m_Ctlz(m_Value()))); 351 } 352 353 TEST_F(SelectionDAGPatternMatchTest, matchConstants) { 354 SDLoc DL; 355 auto Int32VT = EVT::getIntegerVT(Context, 32); 356 auto VInt32VT = EVT::getVectorVT(Context, Int32VT, 4); 357 358 SDValue Arg0 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, Int32VT); 359 360 SDValue Const3 = DAG->getConstant(3, DL, Int32VT); 361 SDValue Const87 = DAG->getConstant(87, DL, Int32VT); 362 SDValue Splat = DAG->getSplat(VInt32VT, DL, Arg0); 363 SDValue ConstSplat = DAG->getSplat(VInt32VT, DL, Const3); 364 SDValue Zero = DAG->getConstant(0, DL, Int32VT); 365 SDValue One = DAG->getConstant(1, DL, Int32VT); 366 SDValue AllOnes = DAG->getConstant(APInt::getAllOnes(32), DL, Int32VT); 367 SDValue SetCC = DAG->getSetCC(DL, Int32VT, Arg0, Const3, ISD::SETULT); 368 369 using namespace SDPatternMatch; 370 EXPECT_TRUE(sd_match(Const87, m_ConstInt())); 371 EXPECT_FALSE(sd_match(Arg0, m_ConstInt())); 372 APInt ConstVal; 373 EXPECT_TRUE(sd_match(ConstSplat, m_ConstInt(ConstVal))); 374 EXPECT_EQ(ConstVal, 3); 375 EXPECT_FALSE(sd_match(Splat, m_ConstInt())); 376 377 EXPECT_TRUE(sd_match(Const87, m_SpecificInt(87))); 378 EXPECT_TRUE(sd_match(Const3, m_SpecificInt(ConstVal))); 379 EXPECT_TRUE(sd_match(AllOnes, m_AllOnes())); 380 381 EXPECT_TRUE(sd_match(Zero, DAG.get(), m_False())); 382 EXPECT_TRUE(sd_match(One, DAG.get(), m_True())); 383 EXPECT_FALSE(sd_match(AllOnes, DAG.get(), m_True())); 384 385 ISD::CondCode CC; 386 EXPECT_TRUE(sd_match( 387 SetCC, m_Node(ISD::SETCC, m_Value(), m_Value(), m_CondCode(CC)))); 388 EXPECT_EQ(CC, ISD::SETULT); 389 EXPECT_TRUE(sd_match(SetCC, m_Node(ISD::SETCC, m_Value(), m_Value(), 390 m_SpecificCondCode(ISD::SETULT)))); 391 } 392 393 TEST_F(SelectionDAGPatternMatchTest, patternCombinators) { 394 SDLoc DL; 395 auto Int32VT = EVT::getIntegerVT(Context, 32); 396 397 SDValue Op0 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, Int32VT); 398 SDValue Op1 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 2, Int32VT); 399 400 SDValue Add = DAG->getNode(ISD::ADD, DL, Int32VT, Op0, Op1); 401 SDValue Sub = DAG->getNode(ISD::SUB, DL, Int32VT, Add, Op0); 402 403 using namespace SDPatternMatch; 404 EXPECT_TRUE(sd_match( 405 Sub, m_AnyOf(m_Opc(ISD::ADD), m_Opc(ISD::SUB), m_Opc(ISD::MUL)))); 406 EXPECT_TRUE(sd_match(Add, m_AllOf(m_Opc(ISD::ADD), m_OneUse()))); 407 EXPECT_TRUE(sd_match(Add, m_NoneOf(m_Opc(ISD::SUB), m_Opc(ISD::MUL)))); 408 } 409 410 TEST_F(SelectionDAGPatternMatchTest, optionalResizing) { 411 SDLoc DL; 412 auto Int32VT = EVT::getIntegerVT(Context, 32); 413 auto Int64VT = EVT::getIntegerVT(Context, 64); 414 415 SDValue Op32 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, Int32VT); 416 SDValue Op64 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, Int64VT); 417 SDValue ZExt = DAG->getNode(ISD::ZERO_EXTEND, DL, Int64VT, Op32); 418 SDValue SExt = DAG->getNode(ISD::SIGN_EXTEND, DL, Int64VT, Op32); 419 SDValue AExt = DAG->getNode(ISD::ANY_EXTEND, DL, Int64VT, Op32); 420 SDValue Trunc = DAG->getNode(ISD::TRUNCATE, DL, Int32VT, Op64); 421 422 using namespace SDPatternMatch; 423 SDValue A; 424 EXPECT_TRUE(sd_match(Op32, m_ZExtOrSelf(m_Value(A)))); 425 EXPECT_TRUE(A == Op32); 426 EXPECT_TRUE(sd_match(ZExt, m_ZExtOrSelf(m_Value(A)))); 427 EXPECT_TRUE(A == Op32); 428 EXPECT_TRUE(sd_match(Op64, m_SExtOrSelf(m_Value(A)))); 429 EXPECT_TRUE(A == Op64); 430 EXPECT_TRUE(sd_match(SExt, m_SExtOrSelf(m_Value(A)))); 431 EXPECT_TRUE(A == Op32); 432 EXPECT_TRUE(sd_match(Op32, m_AExtOrSelf(m_Value(A)))); 433 EXPECT_TRUE(A == Op32); 434 EXPECT_TRUE(sd_match(AExt, m_AExtOrSelf(m_Value(A)))); 435 EXPECT_TRUE(A == Op32); 436 EXPECT_TRUE(sd_match(Op64, m_TruncOrSelf(m_Value(A)))); 437 EXPECT_TRUE(A == Op64); 438 EXPECT_TRUE(sd_match(Trunc, m_TruncOrSelf(m_Value(A)))); 439 EXPECT_TRUE(A == Op64); 440 } 441 442 TEST_F(SelectionDAGPatternMatchTest, matchNode) { 443 SDLoc DL; 444 auto Int32VT = EVT::getIntegerVT(Context, 32); 445 446 SDValue Op0 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, Int32VT); 447 SDValue Op1 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 2, Int32VT); 448 449 SDValue Add = DAG->getNode(ISD::ADD, DL, Int32VT, Op0, Op1); 450 451 using namespace SDPatternMatch; 452 EXPECT_TRUE(sd_match(Add, m_Node(ISD::ADD, m_Value(), m_Value()))); 453 EXPECT_FALSE(sd_match(Add, m_Node(ISD::SUB, m_Value(), m_Value()))); 454 EXPECT_FALSE(sd_match(Add, m_Node(ISD::ADD, m_Value()))); 455 EXPECT_FALSE( 456 sd_match(Add, m_Node(ISD::ADD, m_Value(), m_Value(), m_Value()))); 457 EXPECT_FALSE(sd_match(Add, m_Node(ISD::ADD, m_ConstInt(), m_Value()))); 458 } 459 460 namespace { 461 struct VPMatchContext : public SDPatternMatch::BasicMatchContext { 462 using SDPatternMatch::BasicMatchContext::BasicMatchContext; 463 464 bool match(SDValue OpVal, unsigned Opc) const { 465 if (!OpVal->isVPOpcode()) 466 return OpVal->getOpcode() == Opc; 467 468 auto BaseOpc = ISD::getBaseOpcodeForVP(OpVal->getOpcode(), false); 469 return BaseOpc.has_value() && *BaseOpc == Opc; 470 } 471 472 unsigned getNumOperands(SDValue N) const { 473 return N->isVPOpcode() ? N->getNumOperands() - 2 : N->getNumOperands(); 474 } 475 }; 476 } // anonymous namespace 477 TEST_F(SelectionDAGPatternMatchTest, matchContext) { 478 SDLoc DL; 479 auto BoolVT = EVT::getIntegerVT(Context, 1); 480 auto Int32VT = EVT::getIntegerVT(Context, 32); 481 auto VInt32VT = EVT::getVectorVT(Context, Int32VT, 4); 482 auto MaskVT = EVT::getVectorVT(Context, BoolVT, 4); 483 484 SDValue Scalar0 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, Int32VT); 485 SDValue Vector0 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 2, VInt32VT); 486 SDValue Mask0 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 3, MaskVT); 487 488 SDValue VPAdd = DAG->getNode(ISD::VP_ADD, DL, VInt32VT, 489 {Vector0, Vector0, Mask0, Scalar0}); 490 SDValue VPReduceAdd = DAG->getNode(ISD::VP_REDUCE_ADD, DL, Int32VT, 491 {Scalar0, VPAdd, Mask0, Scalar0}); 492 SDValue Add = DAG->getNode(ISD::ADD, DL, VInt32VT, {Vector0, Vector0}); 493 494 using namespace SDPatternMatch; 495 VPMatchContext VPCtx(DAG.get()); 496 EXPECT_TRUE(sd_context_match(VPAdd, VPCtx, m_Opc(ISD::ADD))); 497 EXPECT_TRUE( 498 sd_context_match(VPAdd, VPCtx, m_Node(ISD::ADD, m_Value(), m_Value()))); 499 // VPMatchContext can't match pattern using explicit VP Opcode 500 EXPECT_FALSE(sd_context_match(VPAdd, VPCtx, 501 m_Node(ISD::VP_ADD, m_Value(), m_Value()))); 502 EXPECT_FALSE(sd_context_match( 503 VPAdd, VPCtx, 504 m_Node(ISD::VP_ADD, m_Value(), m_Value(), m_Value(), m_Value()))); 505 // Check Binary Op Pattern 506 EXPECT_TRUE(sd_context_match(VPAdd, VPCtx, m_Add(m_Value(), m_Value()))); 507 // VP_REDUCE_ADD doesn't have a based opcode, so we use a normal 508 // sd_match before switching to VPMatchContext when checking VPAdd. 509 EXPECT_TRUE(sd_match(VPReduceAdd, m_Node(ISD::VP_REDUCE_ADD, m_Value(), 510 m_Context(VPCtx, m_Opc(ISD::ADD)), 511 m_Value(), m_Value()))); 512 // non-vector predicated should match too 513 EXPECT_TRUE(sd_context_match(Add, VPCtx, m_Opc(ISD::ADD))); 514 EXPECT_TRUE( 515 sd_context_match(Add, VPCtx, m_Node(ISD::ADD, m_Value(), m_Value()))); 516 EXPECT_FALSE(sd_context_match( 517 Add, VPCtx, 518 m_Node(ISD::ADD, m_Value(), m_Value(), m_Value(), m_Value()))); 519 EXPECT_TRUE(sd_context_match(Add, VPCtx, m_Add(m_Value(), m_Value()))); 520 } 521 522 TEST_F(SelectionDAGPatternMatchTest, matchVPWithBasicContext) { 523 SDLoc DL; 524 auto BoolVT = EVT::getIntegerVT(Context, 1); 525 auto Int32VT = EVT::getIntegerVT(Context, 32); 526 auto VInt32VT = EVT::getVectorVT(Context, Int32VT, 4); 527 auto MaskVT = EVT::getVectorVT(Context, BoolVT, 4); 528 529 SDValue Vector0 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, VInt32VT); 530 SDValue Mask = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 2, MaskVT); 531 SDValue EL = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 3, Int32VT); 532 533 SDValue VPAdd = 534 DAG->getNode(ISD::VP_ADD, DL, VInt32VT, Vector0, Vector0, Mask, EL); 535 536 using namespace SDPatternMatch; 537 EXPECT_FALSE(sd_match(VPAdd, m_Node(ISD::VP_ADD, m_Value(), m_Value()))); 538 EXPECT_TRUE(sd_match( 539 VPAdd, m_Node(ISD::VP_ADD, m_Value(), m_Value(), m_Value(), m_Value()))); 540 } 541 542 TEST_F(SelectionDAGPatternMatchTest, matchAdvancedProperties) { 543 SDLoc DL; 544 auto Int16VT = EVT::getIntegerVT(Context, 16); 545 auto Int64VT = EVT::getIntegerVT(Context, 64); 546 547 SDValue Op0 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, Int64VT); 548 SDValue Op1 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 2, Int16VT); 549 550 SDValue Add = DAG->getNode(ISD::ADD, DL, Int64VT, Op0, Op0); 551 552 using namespace SDPatternMatch; 553 EXPECT_TRUE(sd_match(Op0, DAG.get(), m_LegalType(m_Value()))); 554 EXPECT_FALSE(sd_match(Op1, DAG.get(), m_LegalType(m_Value()))); 555 EXPECT_TRUE(sd_match(Add, DAG.get(), 556 m_LegalOp(m_IntegerVT(m_Add(m_Value(), m_Value()))))); 557 } 558