@@ -1649,6 +1649,10 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
1649
1649
case NI_Vector128_GetElement:
1650
1650
{
1651
1651
assert (intrin.numOperands == 2 );
1652
+ assert (!intrin.op1 ->isContained ());
1653
+
1654
+ assert (intrin.op2 ->OperIsConst ());
1655
+ assert (intrin.op2 ->isContained ());
1652
1656
1653
1657
var_types simdType = Compiler::getSIMDTypeForSize (node->GetSimdSize ());
1654
1658
@@ -1658,109 +1662,22 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
1658
1662
simdType = TYP_SIMD16;
1659
1663
}
1660
1664
1661
- if (!intrin.op2 ->OperIsConst ())
1662
- {
1663
- assert (!intrin.op2 ->isContained ());
1664
-
1665
- emitAttr baseTypeSize = emitTypeSize (intrin.baseType );
1666
- unsigned baseTypeScale = genLog2 (EA_SIZE_IN_BYTES (baseTypeSize));
1667
-
1668
- regNumber baseReg;
1669
- regNumber indexReg = op2Reg;
1670
-
1671
- // Optimize the case of op1 is in memory and trying to access i'th element.
1672
- if (!intrin.op1 ->isUsedFromReg ())
1673
- {
1674
- assert (intrin.op1 ->isContained ());
1675
-
1676
- if (intrin.op1 ->OperIsLocal ())
1677
- {
1678
- unsigned varNum = intrin.op1 ->AsLclVarCommon ()->GetLclNum ();
1679
- baseReg = internalRegisters.Extract (node);
1680
-
1681
- // Load the address of varNum
1682
- GetEmitter ()->emitIns_R_S (INS_lea, EA_PTRSIZE, baseReg, varNum, 0 );
1683
- }
1684
- else
1685
- {
1686
- // Require GT_IND addr to be not contained.
1687
- assert (intrin.op1 ->OperIs (GT_IND));
1688
-
1689
- GenTree* addr = intrin.op1 ->AsIndir ()->Addr ();
1690
- assert (!addr->isContained ());
1691
- baseReg = addr->GetRegNum ();
1692
- }
1693
- }
1694
- else
1695
- {
1696
- unsigned simdInitTempVarNum = compiler->lvaSIMDInitTempVarNum ;
1697
- noway_assert (simdInitTempVarNum != BAD_VAR_NUM);
1698
-
1699
- baseReg = internalRegisters.Extract (node);
1700
-
1701
- // Load the address of simdInitTempVarNum
1702
- GetEmitter ()->emitIns_R_S (INS_lea, EA_PTRSIZE, baseReg, simdInitTempVarNum, 0 );
1703
-
1704
- // Store the vector to simdInitTempVarNum
1705
- GetEmitter ()->emitIns_R_R (INS_str, emitTypeSize (simdType), op1Reg, baseReg);
1706
- }
1707
-
1708
- assert (genIsValidIntReg (indexReg));
1709
- assert (genIsValidIntReg (baseReg));
1710
- assert (baseReg != indexReg);
1665
+ ssize_t ival = intrin.op2 ->AsIntCon ()->IconValue ();
1711
1666
1712
- // Load item at baseReg[index]
1713
- GetEmitter ()->emitIns_R_R_R_Ext (ins_Load (intrin.baseType ), baseTypeSize, targetReg, baseReg,
1714
- indexReg, INS_OPTS_LSL, baseTypeScale);
1715
- }
1716
- else if (!GetEmitter ()->isValidVectorIndex (emitTypeSize (simdType), emitTypeSize (intrin.baseType ),
1717
- intrin.op2 ->AsIntCon ()->IconValue ()))
1667
+ if (!GetEmitter ()->isValidVectorIndex (emitTypeSize (simdType), emitTypeSize (intrin.baseType ), ival))
1718
1668
{
1719
1669
// We only need to generate code for the get if the index is valid
1720
1670
// If the index is invalid, previously generated for the range check will throw
1671
+ break ;
1721
1672
}
1722
- else if (!intrin.op1 ->isUsedFromReg ())
1723
- {
1724
- assert (intrin.op1 ->isContained ());
1725
- assert (intrin.op2 ->IsCnsIntOrI ());
1726
-
1727
- int offset = (int )intrin.op2 ->AsIntCon ()->IconValue () * genTypeSize (intrin.baseType );
1728
- instruction ins = ins_Load (intrin.baseType );
1729
-
1730
- assert (!intrin.op1 ->isUsedFromReg ());
1731
-
1732
- if (intrin.op1 ->OperIsLocal ())
1733
- {
1734
- unsigned varNum = intrin.op1 ->AsLclVarCommon ()->GetLclNum ();
1735
- GetEmitter ()->emitIns_R_S (ins, emitActualTypeSize (intrin.baseType ), targetReg, varNum, offset);
1736
- }
1737
- else
1738
- {
1739
- assert (intrin.op1 ->OperIs (GT_IND));
1740
-
1741
- GenTree* addr = intrin.op1 ->AsIndir ()->Addr ();
1742
- assert (!addr->isContained ());
1743
- regNumber baseReg = addr->GetRegNum ();
1744
1673
1745
- // ldr targetReg, [baseReg, #offset]
1746
- GetEmitter ()->emitIns_R_R_I (ins, emitActualTypeSize (intrin.baseType ), targetReg, baseReg,
1747
- offset);
1748
- }
1749
- }
1750
- else
1674
+ if ((varTypeIsFloating (intrin.baseType ) && (targetReg == op1Reg) && (indexValue == 0 )))
1751
1675
{
1752
- assert (intrin.op2 ->IsCnsIntOrI ());
1753
- ssize_t indexValue = intrin.op2 ->AsIntCon ()->IconValue ();
1754
-
1755
1676
// no-op if vector is float/double, targetReg == op1Reg and fetching for 0th index.
1756
- if ((varTypeIsFloating (intrin.baseType ) && (targetReg == op1Reg) && (indexValue == 0 )))
1757
- {
1758
- break ;
1759
- }
1760
-
1761
- GetEmitter ()->emitIns_R_R_I (ins, emitTypeSize (intrin.baseType ), targetReg, op1Reg, indexValue,
1762
- INS_OPTS_NONE);
1677
+ break ;
1763
1678
}
1679
+
1680
+ GetEmitter ()->emitIns_R_R_I (ins, emitTypeSize (intrin.baseType ), targetReg, op1Reg, ival, INS_OPTS_NONE);
1764
1681
break ;
1765
1682
}
1766
1683
0 commit comments