@@ -10824,7 +10824,6 @@ regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst,
10824
10824
}
10825
10825
bool isMulOverflow = false ;
10826
10826
bool isUnsignedMul = false ;
10827
- instruction ins2 = INS_invalid;
10828
10827
regNumber extraReg = REG_NA;
10829
10828
if (dst->gtOverflowEx ())
10830
10829
{
@@ -10840,7 +10839,6 @@ regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst,
10840
10839
{
10841
10840
isMulOverflow = true ;
10842
10841
isUnsignedMul = ((dst->gtFlags & GTF_UNSIGNED) != 0 );
10843
- ins2 = isUnsignedMul ? INS_umulh : INS_smulh;
10844
10842
assert (intConst == nullptr ); // overflow format doesn't support an int constant operand
10845
10843
}
10846
10844
else
@@ -10856,43 +10854,66 @@ regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst,
10856
10854
{
10857
10855
if (isMulOverflow)
10858
10856
{
10857
+ // Make sure that we have an internal register
10858
+ assert (genCountBits (dst->gtRsvdRegs ) == 2 );
10859
+
10860
+ // There will be two bits set in tmpRegsMask.
10861
+ // Remove the bit for 'dst->gtRegNum' from 'tmpRegsMask'
10862
+ regMaskTP tmpRegsMask = dst->gtRsvdRegs & ~genRegMask (dst->gtRegNum);
10863
+ assert (tmpRegsMask != RBM_NONE);
10864
+ regMaskTP tmpRegMask = genFindLowestBit (tmpRegsMask); // set tmpRegMsk to a one-bit mask
10865
+ extraReg = genRegNumFromMask (tmpRegMask); // set tmpReg from that mask
10866
+
10859
10867
if (isUnsignedMul)
10860
10868
{
10861
- assert (genCountBits (dst->gtRsvdRegs ) == 1 );
10862
- extraReg = genRegNumFromMask (dst->gtRsvdRegs );
10869
+ if (attr == EA_4BYTE)
10870
+ {
10871
+ // Compute 8 byte results from 4 byte by 4 byte multiplication.
10872
+ emitIns_R_R_R (INS_umull, EA_8BYTE, dst->gtRegNum , src1->gtRegNum , src2->gtRegNum );
10863
10873
10864
- // Compute the high result
10865
- emitIns_R_R_R (ins2, attr, extraReg, src1->gtRegNum , src2->gtRegNum );
10874
+ // Get the high result by shifting dst.
10875
+ emitIns_R_R_I (INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum , 32 );
10876
+ }
10877
+ else
10878
+ {
10879
+ assert (attr == EA_8BYTE);
10880
+ // Compute the high result.
10881
+ emitIns_R_R_R (INS_umulh, attr, extraReg, src1->gtRegNum , src2->gtRegNum );
10866
10882
10867
- emitIns_R_I (INS_cmp, EA_8BYTE, extraReg, 0 );
10868
- codeGen->genCheckOverflow (dst);
10883
+ // Now multiply without skewing the high result.
10884
+ emitIns_R_R_R (ins, attr, dst->gtRegNum , src1->gtRegNum , src2->gtRegNum );
10885
+ }
10869
10886
10870
- // Now multiply without skewing the high result if no overflow.
10871
- emitIns_R_R_R (ins , attr, dst-> gtRegNum , src1-> gtRegNum , src2-> gtRegNum );
10887
+ // zero-sign bit comparision to detect overflow.
10888
+ emitIns_R_I (INS_cmp , attr, extraReg, 0 );
10872
10889
}
10873
10890
else
10874
10891
{
10875
- // Make sure that we have an internal register
10876
- assert (genCountBits (dst->gtRsvdRegs ) == 2 );
10877
-
10878
- // There will be two bits set in tmpRegsMask.
10879
- // Remove the bit for 'dst->gtRegNum' from 'tmpRegsMask'
10880
- regMaskTP tmpRegsMask = dst->gtRsvdRegs & ~genRegMask (dst->gtRegNum);
10881
- regMaskTP tmpRegMask = genFindLowestBit (tmpRegsMask); // set tmpRegMsk to a one-bit mask
10882
- extraReg = genRegNumFromMask (tmpRegMask); // set tmpReg from that mask
10892
+ int bitShift = 0 ;
10893
+ if (attr == EA_4BYTE)
10894
+ {
10895
+ // Compute 8 byte results from 4 byte by 4 byte multiplication.
10896
+ emitIns_R_R_R (INS_smull, EA_8BYTE, dst->gtRegNum , src1->gtRegNum , src2->gtRegNum );
10883
10897
10884
- // Make sure the two registers are not the same .
10885
- assert (extraReg != dst->gtRegNum );
10898
+ // Get the high result by shifting dst .
10899
+ emitIns_R_R_I (INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum , 32 );
10886
10900
10887
- // Save the high result in a temporary register
10888
- emitIns_R_R_R (ins2, attr, extraReg, src1->gtRegNum , src2->gtRegNum );
10901
+ bitShift = 31 ;
10902
+ }
10903
+ else
10904
+ {
10905
+ assert (attr == EA_8BYTE);
10906
+ // Save the high result in a temporary register.
10907
+ emitIns_R_R_R (INS_smulh, attr, extraReg, src1->gtRegNum , src2->gtRegNum );
10889
10908
10890
- // Now multiply without skewing the high result.
10891
- emitIns_R_R_R (ins, attr, dst->gtRegNum , src1->gtRegNum , src2->gtRegNum );
10909
+ // Now multiply without skewing the high result.
10910
+ emitIns_R_R_R (ins, attr, dst->gtRegNum , src1->gtRegNum , src2->gtRegNum );
10892
10911
10893
- emitIns_R_R_I (INS_cmp, EA_8BYTE, extraReg, dst->gtRegNum , 63 , INS_OPTS_ASR);
10912
+ bitShift = 63 ;
10913
+ }
10894
10914
10895
- codeGen->genCheckOverflow (dst);
10915
+ // Sign bit comparision to detect overflow.
10916
+ emitIns_R_R_I (INS_cmp, attr, extraReg, dst->gtRegNum , bitShift, INS_OPTS_ASR);
10896
10917
}
10897
10918
}
10898
10919
else
@@ -10902,7 +10923,7 @@ regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst,
10902
10923
}
10903
10924
}
10904
10925
10905
- if (dst->gtOverflowEx () && !isMulOverflow )
10926
+ if (dst->gtOverflowEx ())
10906
10927
{
10907
10928
assert (!varTypeIsFloating (dst));
10908
10929
codeGen->genCheckOverflow (dst);
0 commit comments