@@ -1284,117 +1284,89 @@ bool WebAssemblyFastISel::selectBitCast(const Instruction *I) {
12841284 return true ;
12851285}
12861286
1287- static unsigned getSExtLoadOpcode (unsigned LoadSize, bool I64Result, bool A64) {
1288- if (I64Result) {
1289- switch (LoadSize) {
1290- default :
1291- return WebAssembly::INSTRUCTION_LIST_END;
1292- case 8 :
1293- return A64 ? WebAssembly::LOAD8_S_I64_A64 : WebAssembly::LOAD8_S_I64_A32;
1294- case 16 :
1295- return A64 ? WebAssembly::LOAD16_S_I64_A64
1296- : WebAssembly::LOAD16_S_I64_A32;
1297- case 32 :
1298- return A64 ? WebAssembly::LOAD32_S_I64_A64
1299- : WebAssembly::LOAD32_S_I64_A32;
1300- }
1301- }
1302-
1303- switch (LoadSize) {
1304- default :
1305- return WebAssembly::INSTRUCTION_LIST_END;
1306- case 8 :
1307- return A64 ? WebAssembly::LOAD8_S_I32_A64 : WebAssembly::LOAD8_S_I32_A32;
1308- case 16 :
1309- return A64 ? WebAssembly::LOAD16_S_I32_A64 : WebAssembly::LOAD16_S_I32_A32;
1310- }
1311- }
1312-
1313- static unsigned getZExtLoadOpcode (unsigned LoadSize, bool I64Result, bool A64) {
1314- if (I64Result) {
1315- switch (LoadSize) {
1316- default :
1317- return WebAssembly::INSTRUCTION_LIST_END;
1318- case 8 :
1319- return A64 ? WebAssembly::LOAD8_U_I64_A64 : WebAssembly::LOAD8_U_I64_A32;
1320- case 16 :
1321- return A64 ? WebAssembly::LOAD16_U_I64_A64
1322- : WebAssembly::LOAD16_U_I64_A32;
1323- case 32 :
1324- return A64 ? WebAssembly::LOAD32_U_I64_A64
1325- : WebAssembly::LOAD32_U_I64_A32;
1326- }
1327- }
1328-
1329- switch (LoadSize) {
1330- default :
1331- return WebAssembly::INSTRUCTION_LIST_END;
1332- case 8 :
1333- return A64 ? WebAssembly::LOAD8_U_I32_A64 : WebAssembly::LOAD8_U_I32_A32;
1334- case 16 :
1335- return A64 ? WebAssembly::LOAD16_U_I32_A64 : WebAssembly::LOAD16_U_I32_A32;
1336- }
1337- }
1338-
1339- static bool isFoldableSExtOpcode (unsigned Opc) {
1287+ static unsigned getSExtLoadOpcode (unsigned Opc, bool A64) {
13401288 switch (Opc) {
13411289 default :
1342- return false ;
1290+ return WebAssembly::INSTRUCTION_LIST_END ;
13431291 case WebAssembly::I32_EXTEND8_S_I32:
1292+ Opc = A64 ? WebAssembly::LOAD8_S_I32_A64 : WebAssembly::LOAD8_S_I32_A32;
1293+ break ;
13441294 case WebAssembly::I32_EXTEND16_S_I32:
1295+ Opc = A64 ? WebAssembly::LOAD16_S_I32_A64 : WebAssembly::LOAD16_S_I32_A32;
1296+ break ;
13451297 case WebAssembly::I64_EXTEND8_S_I64:
1298+ Opc = A64 ? WebAssembly::LOAD8_S_I64_A64 : WebAssembly::LOAD8_S_I64_A32;
1299+ break ;
13461300 case WebAssembly::I64_EXTEND16_S_I64:
1301+ Opc = A64 ? WebAssembly::LOAD16_S_I64_A64 : WebAssembly::LOAD16_S_I64_A32;
1302+ break ;
13471303 case WebAssembly::I64_EXTEND32_S_I64:
13481304 case WebAssembly::I64_EXTEND_S_I32:
1349- return true ;
1305+ Opc = A64 ? WebAssembly::LOAD32_S_I64_A64 : WebAssembly::LOAD32_S_I64_A32;
1306+ break ;
13501307 }
1308+
1309+ return Opc;
13511310}
13521311
1353- static bool isI64SExtResult (unsigned Opc) {
1354- switch (Opc) {
1355- default :
1356- llvm_unreachable (" unexpected opcode" );
1357- case WebAssembly::I32_EXTEND8_S_I32:
1358- case WebAssembly::I32_EXTEND16_S_I32:
1359- return false ;
1360- case WebAssembly::I64_EXTEND8_S_I64:
1361- case WebAssembly::I64_EXTEND16_S_I64:
1362- case WebAssembly::I64_EXTEND32_S_I64:
1363- case WebAssembly::I64_EXTEND_S_I32:
1364- return true ;
1312+ static unsigned getZExtLoadOpcodeFromAnd (MachineInstr *MI,
1313+ MachineRegisterInfo &MRI,
1314+ const LoadInst *LI, bool A64) {
1315+ uint64_t Mask = 0 ;
1316+ bool IsConstant = false ;
1317+ for (unsigned I = 1 ; I <= 2 ; ++I) {
1318+ Register Reg = MI->getOperand (I).getReg ();
1319+ MachineInstr *DefMI = MRI.getUniqueVRegDef (Reg);
1320+ if (DefMI && (DefMI->getOpcode () == WebAssembly::CONST_I32 ||
1321+ DefMI->getOpcode () == WebAssembly::CONST_I64)) {
1322+ Mask = DefMI->getOperand (1 ).getImm ();
1323+ IsConstant = true ;
1324+ break ;
1325+ }
13651326 }
1366- }
13671327
1368- static unsigned getFoldedLoadOpcode (MachineInstr *MI, MachineRegisterInfo &MRI,
1369- const LoadInst *LI, bool A64) {
1370- unsigned Opc = MI->getOpcode ();
1328+ if (!IsConstant)
1329+ return WebAssembly::INSTRUCTION_LIST_END;
1330+
1331+ unsigned LoadSize = LI->getType ()->getPrimitiveSizeInBits ();
1332+ if (Mask != llvm::maskTrailingOnes<uint64_t >(LoadSize))
1333+ return WebAssembly::INSTRUCTION_LIST_END;
13711334
1372- if (isFoldableSExtOpcode (Opc)) {
1373- unsigned LoadSize = LI->getType ()->getPrimitiveSizeInBits ();
1374- return getSExtLoadOpcode (LoadSize, isI64SExtResult (Opc), A64);
1335+ if (MI->getOpcode () == WebAssembly::AND_I32) {
1336+ if (LoadSize == 8 )
1337+ return A64 ? WebAssembly::LOAD8_U_I32_A64 : WebAssembly::LOAD8_U_I32_A32;
1338+ if (LoadSize == 16 )
1339+ return A64 ? WebAssembly::LOAD16_U_I32_A64
1340+ : WebAssembly::LOAD16_U_I32_A32;
1341+ } else if (MI->getOpcode () == WebAssembly::AND_I64) {
1342+ if (LoadSize == 8 )
1343+ return A64 ? WebAssembly::LOAD8_U_I64_A64 : WebAssembly::LOAD8_U_I64_A32;
1344+ if (LoadSize == 16 )
1345+ return A64 ? WebAssembly::LOAD16_U_I64_A64
1346+ : WebAssembly::LOAD16_U_I64_A32;
1347+ if (LoadSize == 32 )
1348+ return A64 ? WebAssembly::LOAD32_U_I64_A64
1349+ : WebAssembly::LOAD32_U_I64_A32;
13751350 }
13761351
13771352 return WebAssembly::INSTRUCTION_LIST_END;
13781353}
13791354
1380- static unsigned getFoldedI64LoadOpcode (Register DestReg, const LoadInst *LI,
1381- MachineRegisterInfo &MRI, bool A64,
1382- MachineInstr *&OuterUserMI,
1383- unsigned NarrowOpc) {
1384- if (!MRI.hasOneNonDBGUse (DestReg))
1385- return NarrowOpc;
1386-
1387- MachineInstr *UserMI = &*MRI.use_instr_nodbg_begin (DestReg);
1388- unsigned LoadSize = LI->getType ()->getPrimitiveSizeInBits ();
1389- switch (UserMI->getOpcode ()) {
1390- case WebAssembly::I64_EXTEND_U_I32:
1391- OuterUserMI = UserMI;
1392- return getZExtLoadOpcode (LoadSize, /* I64Result=*/ true , A64);
1355+ static unsigned getFoldedLoadOpcode (MachineInstr *MI, MachineRegisterInfo &MRI,
1356+ const LoadInst *LI, bool A64) {
1357+ switch (MI->getOpcode ()) {
1358+ case WebAssembly::I32_EXTEND8_S_I32:
1359+ case WebAssembly::I32_EXTEND16_S_I32:
1360+ case WebAssembly::I64_EXTEND8_S_I64:
1361+ case WebAssembly::I64_EXTEND16_S_I64:
1362+ case WebAssembly::I64_EXTEND32_S_I64:
13931363 case WebAssembly::I64_EXTEND_S_I32:
1394- OuterUserMI = UserMI;
1395- return getSExtLoadOpcode (LoadSize, /* I64Result=*/ true , A64);
1364+ return getSExtLoadOpcode (MI->getOpcode (), A64);
1365+ case WebAssembly::AND_I32:
1366+ case WebAssembly::AND_I64:
1367+ return getZExtLoadOpcodeFromAnd (MI, MRI, LI, A64);
13961368 default :
1397- return NarrowOpc ;
1369+ return WebAssembly::INSTRUCTION_LIST_END ;
13981370 }
13991371}
14001372
@@ -1407,8 +1379,7 @@ static unsigned getFoldedI64LoadOpcode(Register DestReg, const LoadInst *LI,
14071379// / size (32 - LoadBitWidth).
14081380static unsigned matchFoldableShift (MachineInstr *MI, const LoadInst *LI,
14091381 MachineRegisterInfo &MRI, bool A64,
1410- MachineInstr *&UserMI,
1411- MachineInstr *&OuterUserMI) {
1382+ MachineInstr *&UserMI) {
14121383 unsigned Opc = MI->getOpcode ();
14131384 unsigned NewOpc = WebAssembly::INSTRUCTION_LIST_END;
14141385 if (Opc != WebAssembly::SHL_I32)
@@ -1439,104 +1410,13 @@ static unsigned matchFoldableShift(MachineInstr *MI, const LoadInst *LI,
14391410 if (!IsExpectedConst (ShlAmtDef) || !IsExpectedConst (ShrAmtDef))
14401411 return NewOpc;
14411412
1442- unsigned LoadSize = LoadTy->getIntegerBitWidth ();
1443- unsigned NarrowOpc = getSExtLoadOpcode (LoadSize, /* I64Result=*/ false , A64);
1444- if (NarrowOpc == WebAssembly::INSTRUCTION_LIST_END)
1445- return WebAssembly::INSTRUCTION_LIST_END;
1446-
1447- return getFoldedI64LoadOpcode (UserMI->getOperand (0 ).getReg (), LI, MRI, A64,
1448- OuterUserMI, NarrowOpc);
1449- }
1450-
1451- static unsigned matchFoldableSExtFromPromotedI32 (MachineInstr *MI,
1452- const LoadInst *LI,
1453- MachineRegisterInfo &MRI,
1454- bool A64,
1455- MachineInstr *&UserMI) {
1456- if (MI->getOpcode () != WebAssembly::I64_EXTEND_U_I32)
1457- return WebAssembly::INSTRUCTION_LIST_END;
1458-
1459- unsigned LoadSize = LI->getType ()->getPrimitiveSizeInBits ();
1460- Register DestReg = MI->getOperand (0 ).getReg ();
1461- if (!MRI.hasOneNonDBGUse (DestReg))
1462- return WebAssembly::INSTRUCTION_LIST_END;
1463-
1464- UserMI = &*MRI.use_instr_nodbg_begin (DestReg);
1465- switch (UserMI->getOpcode ()) {
1466- default :
1467- return WebAssembly::INSTRUCTION_LIST_END;
1468- case WebAssembly::I64_EXTEND8_S_I64:
1469- if (LoadSize != 8 )
1470- return WebAssembly::INSTRUCTION_LIST_END;
1471- return getSExtLoadOpcode (LoadSize, true , A64);
1472- case WebAssembly::I64_EXTEND16_S_I64:
1473- if (LoadSize != 16 )
1474- return WebAssembly::INSTRUCTION_LIST_END;
1475- return getSExtLoadOpcode (LoadSize, true , A64);
1476- }
1477- }
1478-
1479- static unsigned matchFoldableCopyToI64Ext (MachineInstr *MI, const LoadInst *LI,
1480- MachineRegisterInfo &MRI, bool A64,
1481- MachineInstr *&OuterUserMI) {
1482- if (MI->getOpcode () != WebAssembly::COPY)
1483- return WebAssembly::INSTRUCTION_LIST_END;
1413+ if (LoadTy->isIntegerTy (8 ))
1414+ NewOpc = A64 ? WebAssembly::LOAD8_S_I32_A64 : WebAssembly::LOAD8_S_I32_A32;
1415+ else if (LoadTy->isIntegerTy (16 ))
1416+ NewOpc =
1417+ A64 ? WebAssembly::LOAD16_S_I32_A64 : WebAssembly::LOAD16_S_I32_A32;
14841418
1485- unsigned LoadSize = LI->getType ()->getPrimitiveSizeInBits ();
1486- if (LoadSize != 32 )
1487- return WebAssembly::INSTRUCTION_LIST_END;
1488-
1489- Register CopyDst = MI->getOperand (0 ).getReg ();
1490- if (!MRI.hasOneNonDBGUse (CopyDst))
1491- return WebAssembly::INSTRUCTION_LIST_END;
1492-
1493- OuterUserMI = &*MRI.use_instr_nodbg_begin (CopyDst);
1494- switch (OuterUserMI->getOpcode ()) {
1495- default :
1496- return WebAssembly::INSTRUCTION_LIST_END;
1497- case WebAssembly::I64_EXTEND_U_I32:
1498- return getZExtLoadOpcode (LoadSize, true , A64);
1499- case WebAssembly::I64_EXTEND_S_I32:
1500- return getSExtLoadOpcode (LoadSize, true , A64);
1501- }
1502- }
1503-
1504- static unsigned matchFoldableAnd (MachineInstr *MI, const LoadInst *LI,
1505- MachineRegisterInfo &MRI, bool A64,
1506- MachineInstr *&OuterUserMI) {
1507- if (MI->getOpcode () != WebAssembly::AND_I32 &&
1508- MI->getOpcode () != WebAssembly::AND_I64)
1509- return WebAssembly::INSTRUCTION_LIST_END;
1510-
1511- uint64_t Mask = 0 ;
1512- bool IsConstant = false ;
1513- for (unsigned I = 1 ; I <= 2 ; ++I) {
1514- Register Reg = MI->getOperand (I).getReg ();
1515- MachineInstr *DefMI = MRI.getUniqueVRegDef (Reg);
1516- if (DefMI && (DefMI->getOpcode () == WebAssembly::CONST_I32 ||
1517- DefMI->getOpcode () == WebAssembly::CONST_I64)) {
1518- Mask = DefMI->getOperand (1 ).getImm ();
1519- IsConstant = true ;
1520- break ;
1521- }
1522- }
1523-
1524- if (!IsConstant)
1525- return WebAssembly::INSTRUCTION_LIST_END;
1526-
1527- unsigned LoadSize = LI->getType ()->getPrimitiveSizeInBits ();
1528- if (Mask != llvm::maskTrailingOnes<uint64_t >(LoadSize))
1529- return WebAssembly::INSTRUCTION_LIST_END;
1530-
1531- if (MI->getOpcode () == WebAssembly::AND_I64)
1532- return getZExtLoadOpcode (LoadSize, /* I64Result=*/ true , A64);
1533-
1534- unsigned NarrowOpc = getZExtLoadOpcode (LoadSize, /* I64Result=*/ false , A64);
1535- if (NarrowOpc == WebAssembly::INSTRUCTION_LIST_END)
1536- return WebAssembly::INSTRUCTION_LIST_END;
1537-
1538- return getFoldedI64LoadOpcode (MI->getOperand (0 ).getReg (), LI, MRI, A64,
1539- OuterUserMI, NarrowOpc);
1419+ return NewOpc;
15401420}
15411421
15421422bool WebAssemblyFastISel::tryToFoldLoadIntoMI (MachineInstr *MI, unsigned OpNo,
@@ -1545,39 +1425,20 @@ bool WebAssemblyFastISel::tryToFoldLoadIntoMI(MachineInstr *MI, unsigned OpNo,
15451425 MachineRegisterInfo &MRI = FuncInfo.MF ->getRegInfo ();
15461426 Register ResultReg;
15471427 MachineInstr *UserMI = nullptr ;
1548- MachineInstr *OuterUserMI = nullptr ;
1549- unsigned NewOpc = WebAssembly::INSTRUCTION_LIST_END;
1550- if ((NewOpc = matchFoldableSExtFromPromotedI32 (MI, LI, MRI, A64, UserMI)) !=
1428+ unsigned NewOpc;
1429+ if ((NewOpc = getFoldedLoadOpcode (MI, MRI, LI, A64)) !=
15511430 WebAssembly::INSTRUCTION_LIST_END) {
1552- ResultReg = UserMI->getOperand (0 ).getReg ();
1553- } else if ((NewOpc =
1554- matchFoldableCopyToI64Ext (MI, LI, MRI, A64, OuterUserMI)) !=
1555- WebAssembly::INSTRUCTION_LIST_END) {
1556- ResultReg = OuterUserMI->getOperand (0 ).getReg ();
1557- } else if ((NewOpc = matchFoldableAnd (MI, LI, MRI, A64, OuterUserMI)) !=
1558- WebAssembly::INSTRUCTION_LIST_END) {
1559- ResultReg = OuterUserMI ? OuterUserMI->getOperand (0 ).getReg ()
1560- : MI->getOperand (0 ).getReg ();
1561- } else if ((NewOpc = getFoldedLoadOpcode (MI, MRI, LI, A64)) !=
1562- WebAssembly::INSTRUCTION_LIST_END) {
15631431 ResultReg = MI->getOperand (0 ).getReg ();
1564- } else if ((NewOpc =
1565- matchFoldableShift (MI, LI, MRI, A64, UserMI, OuterUserMI)) !=
1432+ } else if ((NewOpc = matchFoldableShift (MI, LI, MRI, A64, UserMI)) !=
15661433 WebAssembly::INSTRUCTION_LIST_END) {
1567- ResultReg = OuterUserMI ? OuterUserMI->getOperand (0 ).getReg ()
1568- : UserMI->getOperand (0 ).getReg ();
1434+ ResultReg = UserMI->getOperand (0 ).getReg ();
15691435 } else {
15701436 return false ;
15711437 }
15721438
15731439 if (!emitLoad (ResultReg, NewOpc, LI))
15741440 return false ;
15751441
1576- if (OuterUserMI) {
1577- MachineBasicBlock::iterator OuterIter (OuterUserMI);
1578- removeDeadCode (OuterIter, std::next (OuterIter));
1579- }
1580-
15811442 if (UserMI) {
15821443 MachineBasicBlock::iterator UserIter (UserMI);
15831444 removeDeadCode (UserIter, std::next (UserIter));
0 commit comments