1 //===- PatternMatchTest.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 "GISelMITest.h" 10 #include "llvm/CodeGen/GlobalISel/ConstantFoldingMIRBuilder.h" 11 #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h" 12 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" 13 #include "llvm/CodeGen/GlobalISel/Utils.h" 14 #include "llvm/CodeGen/MIRParser/MIRParser.h" 15 #include "llvm/CodeGen/MachineFunction.h" 16 #include "llvm/CodeGen/MachineModuleInfo.h" 17 #include "llvm/CodeGen/TargetFrameLowering.h" 18 #include "llvm/CodeGen/TargetInstrInfo.h" 19 #include "llvm/CodeGen/TargetLowering.h" 20 #include "llvm/CodeGen/TargetSubtargetInfo.h" 21 #include "llvm/Support/SourceMgr.h" 22 #include "llvm/Support/TargetRegistry.h" 23 #include "llvm/Support/TargetSelect.h" 24 #include "llvm/Target/TargetMachine.h" 25 #include "llvm/Target/TargetOptions.h" 26 #include "gtest/gtest.h" 27 28 using namespace llvm; 29 using namespace MIPatternMatch; 30 31 namespace { 32 33 TEST_F(GISelMITest, MatchIntConstant) { 34 setUp(); 35 if (!TM) 36 return; 37 auto MIBCst = B.buildConstant(LLT::scalar(64), 42); 38 int64_t Cst; 39 bool match = mi_match(MIBCst.getReg(0), *MRI, m_ICst(Cst)); 40 EXPECT_TRUE(match); 41 EXPECT_EQ(Cst, 42); 42 } 43 44 TEST_F(GISelMITest, MatchBinaryOp) { 45 setUp(); 46 if (!TM) 47 return; 48 LLT s64 = LLT::scalar(64); 49 auto MIBAdd = B.buildAdd(s64, Copies[0], Copies[1]); 50 // Test case for no bind. 51 bool match = 52 mi_match(MIBAdd.getReg(0), *MRI, m_GAdd(m_Reg(), m_Reg())); 53 EXPECT_TRUE(match); 54 Register Src0, Src1, Src2; 55 match = mi_match(MIBAdd.getReg(0), *MRI, 56 m_GAdd(m_Reg(Src0), m_Reg(Src1))); 57 EXPECT_TRUE(match); 58 EXPECT_EQ(Src0, Copies[0]); 59 EXPECT_EQ(Src1, Copies[1]); 60 61 // Build MUL(ADD %0, %1), %2 62 auto MIBMul = B.buildMul(s64, MIBAdd, Copies[2]); 63 64 // Try to match MUL. 65 match = mi_match(MIBMul.getReg(0), *MRI, 66 m_GMul(m_Reg(Src0), m_Reg(Src1))); 67 EXPECT_TRUE(match); 68 EXPECT_EQ(Src0, MIBAdd.getReg(0)); 69 EXPECT_EQ(Src1, Copies[2]); 70 71 // Try to match MUL(ADD) 72 match = mi_match(MIBMul.getReg(0), *MRI, 73 m_GMul(m_GAdd(m_Reg(Src0), m_Reg(Src1)), m_Reg(Src2))); 74 EXPECT_TRUE(match); 75 EXPECT_EQ(Src0, Copies[0]); 76 EXPECT_EQ(Src1, Copies[1]); 77 EXPECT_EQ(Src2, Copies[2]); 78 79 // Test Commutativity. 80 auto MIBMul2 = B.buildMul(s64, Copies[0], B.buildConstant(s64, 42)); 81 // Try to match MUL(Cst, Reg) on src of MUL(Reg, Cst) to validate 82 // commutativity. 83 int64_t Cst; 84 match = mi_match(MIBMul2.getReg(0), *MRI, 85 m_GMul(m_ICst(Cst), m_Reg(Src0))); 86 EXPECT_TRUE(match); 87 EXPECT_EQ(Cst, 42); 88 EXPECT_EQ(Src0, Copies[0]); 89 90 // Make sure commutative doesn't work with something like SUB. 91 auto MIBSub = B.buildSub(s64, Copies[0], B.buildConstant(s64, 42)); 92 match = mi_match(MIBSub.getReg(0), *MRI, 93 m_GSub(m_ICst(Cst), m_Reg(Src0))); 94 EXPECT_FALSE(match); 95 96 auto MIBFMul = B.buildInstr(TargetOpcode::G_FMUL, {s64}, 97 {Copies[0], B.buildConstant(s64, 42)}); 98 // Match and test commutativity for FMUL. 99 match = mi_match(MIBFMul.getReg(0), *MRI, 100 m_GFMul(m_ICst(Cst), m_Reg(Src0))); 101 EXPECT_TRUE(match); 102 EXPECT_EQ(Cst, 42); 103 EXPECT_EQ(Src0, Copies[0]); 104 105 // FSUB 106 auto MIBFSub = B.buildInstr(TargetOpcode::G_FSUB, {s64}, 107 {Copies[0], B.buildConstant(s64, 42)}); 108 match = mi_match(MIBFSub.getReg(0), *MRI, 109 m_GFSub(m_Reg(Src0), m_Reg())); 110 EXPECT_TRUE(match); 111 EXPECT_EQ(Src0, Copies[0]); 112 113 // Build AND %0, %1 114 auto MIBAnd = B.buildAnd(s64, Copies[0], Copies[1]); 115 // Try to match AND. 116 match = mi_match(MIBAnd.getReg(0), *MRI, 117 m_GAnd(m_Reg(Src0), m_Reg(Src1))); 118 EXPECT_TRUE(match); 119 EXPECT_EQ(Src0, Copies[0]); 120 EXPECT_EQ(Src1, Copies[1]); 121 122 // Build OR %0, %1 123 auto MIBOr = B.buildOr(s64, Copies[0], Copies[1]); 124 // Try to match OR. 125 match = mi_match(MIBOr.getReg(0), *MRI, 126 m_GOr(m_Reg(Src0), m_Reg(Src1))); 127 EXPECT_TRUE(match); 128 EXPECT_EQ(Src0, Copies[0]); 129 EXPECT_EQ(Src1, Copies[1]); 130 } 131 132 TEST_F(GISelMITest, MatchFPUnaryOp) { 133 setUp(); 134 if (!TM) 135 return; 136 137 // Truncate s64 to s32. 138 LLT s32 = LLT::scalar(32); 139 auto Copy0s32 = B.buildFPTrunc(s32, Copies[0]); 140 141 // Match G_FABS. 142 auto MIBFabs = B.buildInstr(TargetOpcode::G_FABS, {s32}, {Copy0s32}); 143 bool match = 144 mi_match(MIBFabs.getReg(0), *MRI, m_GFabs(m_Reg())); 145 EXPECT_TRUE(match); 146 147 Register Src; 148 auto MIBFNeg = B.buildInstr(TargetOpcode::G_FNEG, {s32}, {Copy0s32}); 149 match = mi_match(MIBFNeg.getReg(0), *MRI, m_GFNeg(m_Reg(Src))); 150 EXPECT_TRUE(match); 151 EXPECT_EQ(Src, Copy0s32.getReg(0)); 152 153 match = mi_match(MIBFabs.getReg(0), *MRI, m_GFabs(m_Reg(Src))); 154 EXPECT_TRUE(match); 155 EXPECT_EQ(Src, Copy0s32.getReg(0)); 156 157 // Build and match FConstant. 158 auto MIBFCst = B.buildFConstant(s32, .5); 159 const ConstantFP *TmpFP{}; 160 match = mi_match(MIBFCst.getReg(0), *MRI, m_GFCst(TmpFP)); 161 EXPECT_TRUE(match); 162 EXPECT_TRUE(TmpFP); 163 APFloat APF((float).5); 164 auto *CFP = ConstantFP::get(Context, APF); 165 EXPECT_EQ(CFP, TmpFP); 166 167 // Build double float. 168 LLT s64 = LLT::scalar(64); 169 auto MIBFCst64 = B.buildFConstant(s64, .5); 170 const ConstantFP *TmpFP64{}; 171 match = mi_match(MIBFCst64.getReg(0), *MRI, m_GFCst(TmpFP64)); 172 EXPECT_TRUE(match); 173 EXPECT_TRUE(TmpFP64); 174 APFloat APF64(.5); 175 auto CFP64 = ConstantFP::get(Context, APF64); 176 EXPECT_EQ(CFP64, TmpFP64); 177 EXPECT_NE(TmpFP64, TmpFP); 178 179 // Build half float. 180 LLT s16 = LLT::scalar(16); 181 auto MIBFCst16 = B.buildFConstant(s16, .5); 182 const ConstantFP *TmpFP16{}; 183 match = mi_match(MIBFCst16.getReg(0), *MRI, m_GFCst(TmpFP16)); 184 EXPECT_TRUE(match); 185 EXPECT_TRUE(TmpFP16); 186 bool Ignored; 187 APFloat APF16(.5); 188 APF16.convert(APFloat::IEEEhalf(), APFloat::rmNearestTiesToEven, &Ignored); 189 auto CFP16 = ConstantFP::get(Context, APF16); 190 EXPECT_EQ(TmpFP16, CFP16); 191 EXPECT_NE(TmpFP16, TmpFP); 192 } 193 194 TEST_F(GISelMITest, MatchExtendsTrunc) { 195 setUp(); 196 if (!TM) 197 return; 198 199 LLT s64 = LLT::scalar(64); 200 LLT s32 = LLT::scalar(32); 201 202 auto MIBTrunc = B.buildTrunc(s32, Copies[0]); 203 auto MIBAExt = B.buildAnyExt(s64, MIBTrunc); 204 auto MIBZExt = B.buildZExt(s64, MIBTrunc); 205 auto MIBSExt = B.buildSExt(s64, MIBTrunc); 206 Register Src0; 207 bool match = 208 mi_match(MIBTrunc.getReg(0), *MRI, m_GTrunc(m_Reg(Src0))); 209 EXPECT_TRUE(match); 210 EXPECT_EQ(Src0, Copies[0]); 211 match = 212 mi_match(MIBAExt.getReg(0), *MRI, m_GAnyExt(m_Reg(Src0))); 213 EXPECT_TRUE(match); 214 EXPECT_EQ(Src0, MIBTrunc.getReg(0)); 215 216 match = mi_match(MIBSExt.getReg(0), *MRI, m_GSExt(m_Reg(Src0))); 217 EXPECT_TRUE(match); 218 EXPECT_EQ(Src0, MIBTrunc.getReg(0)); 219 220 match = mi_match(MIBZExt.getReg(0), *MRI, m_GZExt(m_Reg(Src0))); 221 EXPECT_TRUE(match); 222 EXPECT_EQ(Src0, MIBTrunc.getReg(0)); 223 224 // Match ext(trunc src) 225 match = mi_match(MIBAExt.getReg(0), *MRI, 226 m_GAnyExt(m_GTrunc(m_Reg(Src0)))); 227 EXPECT_TRUE(match); 228 EXPECT_EQ(Src0, Copies[0]); 229 230 match = mi_match(MIBSExt.getReg(0), *MRI, 231 m_GSExt(m_GTrunc(m_Reg(Src0)))); 232 EXPECT_TRUE(match); 233 EXPECT_EQ(Src0, Copies[0]); 234 235 match = mi_match(MIBZExt.getReg(0), *MRI, 236 m_GZExt(m_GTrunc(m_Reg(Src0)))); 237 EXPECT_TRUE(match); 238 EXPECT_EQ(Src0, Copies[0]); 239 } 240 241 TEST_F(GISelMITest, MatchSpecificType) { 242 setUp(); 243 if (!TM) 244 return; 245 246 // Try to match a 64bit add. 247 LLT s64 = LLT::scalar(64); 248 LLT s32 = LLT::scalar(32); 249 auto MIBAdd = B.buildAdd(s64, Copies[0], Copies[1]); 250 EXPECT_FALSE(mi_match(MIBAdd.getReg(0), *MRI, 251 m_GAdd(m_SpecificType(s32), m_Reg()))); 252 EXPECT_TRUE(mi_match(MIBAdd.getReg(0), *MRI, 253 m_GAdd(m_SpecificType(s64), m_Reg()))); 254 255 // Try to match the destination type of a bitcast. 256 LLT v2s32 = LLT::vector(2, 32); 257 auto MIBCast = B.buildCast(v2s32, Copies[0]); 258 EXPECT_TRUE( 259 mi_match(MIBCast.getReg(0), *MRI, m_GBitcast(m_Reg()))); 260 EXPECT_TRUE( 261 mi_match(MIBCast.getReg(0), *MRI, m_SpecificType(v2s32))); 262 EXPECT_TRUE( 263 mi_match(MIBCast.getReg(1), *MRI, m_SpecificType(s64))); 264 265 // Build a PTRToInt and INTTOPTR and match and test them. 266 LLT PtrTy = LLT::pointer(0, 64); 267 auto MIBIntToPtr = B.buildCast(PtrTy, Copies[0]); 268 auto MIBPtrToInt = B.buildCast(s64, MIBIntToPtr); 269 Register Src0; 270 271 // match the ptrtoint(inttoptr reg) 272 bool match = mi_match(MIBPtrToInt.getReg(0), *MRI, 273 m_GPtrToInt(m_GIntToPtr(m_Reg(Src0)))); 274 EXPECT_TRUE(match); 275 EXPECT_EQ(Src0, Copies[0]); 276 } 277 278 TEST_F(GISelMITest, MatchCombinators) { 279 setUp(); 280 if (!TM) 281 return; 282 283 LLT s64 = LLT::scalar(64); 284 LLT s32 = LLT::scalar(32); 285 auto MIBAdd = B.buildAdd(s64, Copies[0], Copies[1]); 286 Register Src0, Src1; 287 bool match = 288 mi_match(MIBAdd.getReg(0), *MRI, 289 m_all_of(m_SpecificType(s64), m_GAdd(m_Reg(Src0), m_Reg(Src1)))); 290 EXPECT_TRUE(match); 291 EXPECT_EQ(Src0, Copies[0]); 292 EXPECT_EQ(Src1, Copies[1]); 293 // Check for s32 (which should fail). 294 match = 295 mi_match(MIBAdd.getReg(0), *MRI, 296 m_all_of(m_SpecificType(s32), m_GAdd(m_Reg(Src0), m_Reg(Src1)))); 297 EXPECT_FALSE(match); 298 match = 299 mi_match(MIBAdd.getReg(0), *MRI, 300 m_any_of(m_SpecificType(s32), m_GAdd(m_Reg(Src0), m_Reg(Src1)))); 301 EXPECT_TRUE(match); 302 EXPECT_EQ(Src0, Copies[0]); 303 EXPECT_EQ(Src1, Copies[1]); 304 305 // Match a case where none of the predicates hold true. 306 match = mi_match( 307 MIBAdd.getReg(0), *MRI, 308 m_any_of(m_SpecificType(LLT::scalar(16)), m_GSub(m_Reg(), m_Reg()))); 309 EXPECT_FALSE(match); 310 } 311 312 TEST_F(GISelMITest, MatchMiscellaneous) { 313 setUp(); 314 if (!TM) 315 return; 316 317 LLT s64 = LLT::scalar(64); 318 auto MIBAdd = B.buildAdd(s64, Copies[0], Copies[1]); 319 // Make multiple uses of this add. 320 B.buildCast(LLT::pointer(0, 32), MIBAdd); 321 B.buildCast(LLT::pointer(1, 32), MIBAdd); 322 bool match = mi_match(MIBAdd.getReg(0), *MRI, m_GAdd(m_Reg(), m_Reg())); 323 EXPECT_TRUE(match); 324 match = mi_match(MIBAdd.getReg(0), *MRI, m_OneUse(m_GAdd(m_Reg(), m_Reg()))); 325 EXPECT_FALSE(match); 326 } 327 } // namespace 328 329 int main(int argc, char **argv) { 330 ::testing::InitGoogleTest(&argc, argv); 331 initLLVM(); 332 return RUN_ALL_TESTS(); 333 } 334