@@ -10149,6 +10149,122 @@ SDValue TargetLowering::expandShlSat(SDNode *Node, SelectionDAG &DAG) const {
10149
10149
return DAG.getSelect (dl, VT, Cond, SatVal, Result);
10150
10150
}
10151
10151
10152
+ void TargetLowering::forceExpandWideMUL (SelectionDAG &DAG, const SDLoc &dl,
10153
+ bool Signed, EVT WideVT,
10154
+ const SDValue LL, const SDValue LH,
10155
+ const SDValue RL, const SDValue RH,
10156
+ SDValue &Lo, SDValue &Hi) const {
10157
+ // We can fall back to a libcall with an illegal type for the MUL if we
10158
+ // have a libcall big enough.
10159
+ // Also, we can fall back to a division in some cases, but that's a big
10160
+ // performance hit in the general case.
10161
+ RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
10162
+ if (WideVT == MVT::i16 )
10163
+ LC = RTLIB::MUL_I16;
10164
+ else if (WideVT == MVT::i32 )
10165
+ LC = RTLIB::MUL_I32;
10166
+ else if (WideVT == MVT::i64 )
10167
+ LC = RTLIB::MUL_I64;
10168
+ else if (WideVT == MVT::i128 )
10169
+ LC = RTLIB::MUL_I128;
10170
+
10171
+ if (LC == RTLIB::UNKNOWN_LIBCALL || !getLibcallName (LC)) {
10172
+ // We'll expand the multiplication by brute force because we have no other
10173
+ // options. This is a trivially-generalized version of the code from
10174
+ // Hacker's Delight (itself derived from Knuth's Algorithm M from section
10175
+ // 4.3.1).
10176
+ EVT VT = LL.getValueType ();
10177
+ unsigned Bits = VT.getSizeInBits ();
10178
+ unsigned HalfBits = Bits >> 1 ;
10179
+ SDValue Mask =
10180
+ DAG.getConstant (APInt::getLowBitsSet (Bits, HalfBits), dl, VT);
10181
+ SDValue LLL = DAG.getNode (ISD::AND, dl, VT, LL, Mask);
10182
+ SDValue RLL = DAG.getNode (ISD::AND, dl, VT, RL, Mask);
10183
+
10184
+ SDValue T = DAG.getNode (ISD::MUL, dl, VT, LLL, RLL);
10185
+ SDValue TL = DAG.getNode (ISD::AND, dl, VT, T, Mask);
10186
+
10187
+ SDValue Shift = DAG.getShiftAmountConstant (HalfBits, VT, dl);
10188
+ SDValue TH = DAG.getNode (ISD::SRL, dl, VT, T, Shift);
10189
+ SDValue LLH = DAG.getNode (ISD::SRL, dl, VT, LL, Shift);
10190
+ SDValue RLH = DAG.getNode (ISD::SRL, dl, VT, RL, Shift);
10191
+
10192
+ SDValue U = DAG.getNode (ISD::ADD, dl, VT,
10193
+ DAG.getNode (ISD::MUL, dl, VT, LLH, RLL), TH);
10194
+ SDValue UL = DAG.getNode (ISD::AND, dl, VT, U, Mask);
10195
+ SDValue UH = DAG.getNode (ISD::SRL, dl, VT, U, Shift);
10196
+
10197
+ SDValue V = DAG.getNode (ISD::ADD, dl, VT,
10198
+ DAG.getNode (ISD::MUL, dl, VT, LLL, RLH), UL);
10199
+ SDValue VH = DAG.getNode (ISD::SRL, dl, VT, V, Shift);
10200
+
10201
+ SDValue W =
10202
+ DAG.getNode (ISD::ADD, dl, VT, DAG.getNode (ISD::MUL, dl, VT, LLH, RLH),
10203
+ DAG.getNode (ISD::ADD, dl, VT, UH, VH));
10204
+ Lo = DAG.getNode (ISD::ADD, dl, VT, TL,
10205
+ DAG.getNode (ISD::SHL, dl, VT, V, Shift));
10206
+
10207
+ Hi = DAG.getNode (ISD::ADD, dl, VT, W,
10208
+ DAG.getNode (ISD::ADD, dl, VT,
10209
+ DAG.getNode (ISD::MUL, dl, VT, RH, LL),
10210
+ DAG.getNode (ISD::MUL, dl, VT, RL, LH)));
10211
+ } else {
10212
+ // Attempt a libcall.
10213
+ SDValue Ret;
10214
+ TargetLowering::MakeLibCallOptions CallOptions;
10215
+ CallOptions.setSExt (Signed);
10216
+ CallOptions.setIsPostTypeLegalization (true );
10217
+ if (shouldSplitFunctionArgumentsAsLittleEndian (DAG.getDataLayout ())) {
10218
+ // Halves of WideVT are packed into registers in different order
10219
+ // depending on platform endianness. This is usually handled by
10220
+ // the C calling convention, but we can't defer to it in
10221
+ // the legalizer.
10222
+ SDValue Args[] = {LL, LH, RL, RH};
10223
+ Ret = makeLibCall (DAG, LC, WideVT, Args, CallOptions, dl).first ;
10224
+ } else {
10225
+ SDValue Args[] = {LH, LL, RH, RL};
10226
+ Ret = makeLibCall (DAG, LC, WideVT, Args, CallOptions, dl).first ;
10227
+ }
10228
+ assert (Ret.getOpcode () == ISD::MERGE_VALUES &&
10229
+ " Ret value is a collection of constituent nodes holding result." );
10230
+ if (DAG.getDataLayout ().isLittleEndian ()) {
10231
+ // Same as above.
10232
+ Lo = Ret.getOperand (0 );
10233
+ Hi = Ret.getOperand (1 );
10234
+ } else {
10235
+ Lo = Ret.getOperand (1 );
10236
+ Hi = Ret.getOperand (0 );
10237
+ }
10238
+ }
10239
+ }
10240
+
10241
+ void TargetLowering::forceExpandWideMUL (SelectionDAG &DAG, const SDLoc &dl,
10242
+ bool Signed, const SDValue LHS,
10243
+ const SDValue RHS, SDValue &Lo,
10244
+ SDValue &Hi) const {
10245
+ EVT VT = LHS.getValueType ();
10246
+ assert (RHS.getValueType () == VT && " Mismatching operand types" );
10247
+
10248
+ SDValue HiLHS;
10249
+ SDValue HiRHS;
10250
+ if (Signed) {
10251
+ // The high part is obtained by SRA'ing all but one of the bits of low
10252
+ // part.
10253
+ unsigned LoSize = VT.getFixedSizeInBits ();
10254
+ HiLHS = DAG.getNode (
10255
+ ISD::SRA, dl, VT, LHS,
10256
+ DAG.getConstant (LoSize - 1 , dl, getPointerTy (DAG.getDataLayout ())));
10257
+ HiRHS = DAG.getNode (
10258
+ ISD::SRA, dl, VT, RHS,
10259
+ DAG.getConstant (LoSize - 1 , dl, getPointerTy (DAG.getDataLayout ())));
10260
+ } else {
10261
+ HiLHS = DAG.getConstant (0 , dl, VT);
10262
+ HiRHS = DAG.getConstant (0 , dl, VT);
10263
+ }
10264
+ EVT WideVT = EVT::getIntegerVT (*DAG.getContext (), VT.getSizeInBits () * 2 );
10265
+ forceExpandWideMUL (DAG, dl, Signed, WideVT, LHS, HiLHS, RHS, HiRHS, Lo, Hi);
10266
+ }
10267
+
10152
10268
SDValue
10153
10269
TargetLowering::expandFixedPointMul (SDNode *Node, SelectionDAG &DAG) const {
10154
10270
assert ((Node->getOpcode () == ISD::SMULFIX ||
@@ -10223,7 +10339,7 @@ TargetLowering::expandFixedPointMul(SDNode *Node, SelectionDAG &DAG) const {
10223
10339
} else if (VT.isVector ()) {
10224
10340
return SDValue ();
10225
10341
} else {
10226
- report_fatal_error ( " Unable to expand fixed point multiplication. " );
10342
+ forceExpandWideMUL (DAG, dl, Signed, LHS, RHS, Lo, Hi );
10227
10343
}
10228
10344
10229
10345
if (Scale == VTSize)
@@ -10522,69 +10638,7 @@ bool TargetLowering::expandMULO(SDNode *Node, SDValue &Result,
10522
10638
if (VT.isVector ())
10523
10639
return false ;
10524
10640
10525
- // We can fall back to a libcall with an illegal type for the MUL if we
10526
- // have a libcall big enough.
10527
- // Also, we can fall back to a division in some cases, but that's a big
10528
- // performance hit in the general case.
10529
- RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
10530
- if (WideVT == MVT::i16 )
10531
- LC = RTLIB::MUL_I16;
10532
- else if (WideVT == MVT::i32 )
10533
- LC = RTLIB::MUL_I32;
10534
- else if (WideVT == MVT::i64 )
10535
- LC = RTLIB::MUL_I64;
10536
- else if (WideVT == MVT::i128 )
10537
- LC = RTLIB::MUL_I128;
10538
- assert (LC != RTLIB::UNKNOWN_LIBCALL && " Cannot expand this operation!" );
10539
-
10540
- SDValue HiLHS;
10541
- SDValue HiRHS;
10542
- if (isSigned) {
10543
- // The high part is obtained by SRA'ing all but one of the bits of low
10544
- // part.
10545
- unsigned LoSize = VT.getFixedSizeInBits ();
10546
- HiLHS =
10547
- DAG.getNode (ISD::SRA, dl, VT, LHS,
10548
- DAG.getConstant (LoSize - 1 , dl,
10549
- getPointerTy (DAG.getDataLayout ())));
10550
- HiRHS =
10551
- DAG.getNode (ISD::SRA, dl, VT, RHS,
10552
- DAG.getConstant (LoSize - 1 , dl,
10553
- getPointerTy (DAG.getDataLayout ())));
10554
- } else {
10555
- HiLHS = DAG.getConstant (0 , dl, VT);
10556
- HiRHS = DAG.getConstant (0 , dl, VT);
10557
- }
10558
-
10559
- // Here we're passing the 2 arguments explicitly as 4 arguments that are
10560
- // pre-lowered to the correct types. This all depends upon WideVT not
10561
- // being a legal type for the architecture and thus has to be split to
10562
- // two arguments.
10563
- SDValue Ret;
10564
- TargetLowering::MakeLibCallOptions CallOptions;
10565
- CallOptions.setSExt (isSigned);
10566
- CallOptions.setIsPostTypeLegalization (true );
10567
- if (shouldSplitFunctionArgumentsAsLittleEndian (DAG.getDataLayout ())) {
10568
- // Halves of WideVT are packed into registers in different order
10569
- // depending on platform endianness. This is usually handled by
10570
- // the C calling convention, but we can't defer to it in
10571
- // the legalizer.
10572
- SDValue Args[] = { LHS, HiLHS, RHS, HiRHS };
10573
- Ret = makeLibCall (DAG, LC, WideVT, Args, CallOptions, dl).first ;
10574
- } else {
10575
- SDValue Args[] = { HiLHS, LHS, HiRHS, RHS };
10576
- Ret = makeLibCall (DAG, LC, WideVT, Args, CallOptions, dl).first ;
10577
- }
10578
- assert (Ret.getOpcode () == ISD::MERGE_VALUES &&
10579
- " Ret value is a collection of constituent nodes holding result." );
10580
- if (DAG.getDataLayout ().isLittleEndian ()) {
10581
- // Same as above.
10582
- BottomHalf = Ret.getOperand (0 );
10583
- TopHalf = Ret.getOperand (1 );
10584
- } else {
10585
- BottomHalf = Ret.getOperand (1 );
10586
- TopHalf = Ret.getOperand (0 );
10587
- }
10641
+ forceExpandWideMUL (DAG, dl, isSigned, LHS, RHS, BottomHalf, TopHalf);
10588
10642
}
10589
10643
10590
10644
Result = BottomHalf;
0 commit comments