32
32
#include "llvm/CodeGen/MachineRegisterInfo.h"
33
33
#include "llvm/CodeGen/SDPatternMatch.h"
34
34
#include "llvm/CodeGen/SelectionDAGAddressAnalysis.h"
35
+ #include "llvm/CodeGen/SelectionDAGNodes.h"
35
36
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
36
37
#include "llvm/CodeGen/ValueTypes.h"
37
38
#include "llvm/IR/DiagnosticInfo.h"
49
50
#include "llvm/Support/KnownBits.h"
50
51
#include "llvm/Support/MathExtras.h"
51
52
#include "llvm/Support/raw_ostream.h"
53
+ #include <cstdint>
52
54
#include <optional>
53
55
54
56
using namespace llvm;
@@ -15437,15 +15439,10 @@ static SDValue performXORCombine(SDNode *N, SelectionDAG &DAG,
15437
15439
return combineSelectAndUseCommutative(N, DAG, /*AllOnes*/ false, Subtarget);
15438
15440
}
15439
15441
15440
- // Try to expand a multiply to a sequence of shifts and add/subs,
15441
- // for a machine w/o native mul instruction.
15442
- static SDValue expandMulToBasicOps(SDNode *N, SelectionDAG &DAG,
15443
- uint64_t MulAmt) {
15444
- const uint64_t BitWidth = N->getValueType(0).getFixedSizeInBits();
15445
- SDLoc DL(N);
15446
-
15447
- if (MulAmt == 0)
15448
- return DAG.getConstant(0, DL, N->getValueType(0));
15442
+ static SDValue expandMulToNAFSequence(SDNode *N, SelectionDAG &DAG,
15443
+ const SDLoc &DL, uint64_t MulAmt) {
15444
+ EVT VT = N->getValueType(0);
15445
+ const uint64_t BitWidth = VT.getFixedSizeInBits();
15449
15446
15450
15447
// Find the Non-adjacent form of the multiplier.
15451
15448
llvm::SmallVector<std::pair<bool, uint64_t>> Sequence; // {isAdd, shamt}
@@ -15470,17 +15467,89 @@ static SDValue expandMulToBasicOps(SDNode *N, SelectionDAG &DAG,
15470
15467
SDValue ShiftVal;
15471
15468
if (Op.second > 0)
15472
15469
ShiftVal =
15473
- DAG.getNode(ISD::SHL, DL, N->getValueType(0), N0,
15474
- DAG.getConstant(Op.second, DL, N->getValueType(0)));
15470
+ DAG.getNode(ISD::SHL, DL, VT, N0, DAG.getConstant(Op.second, DL, VT));
15475
15471
else
15476
15472
ShiftVal = N0;
15477
15473
15478
15474
ISD::NodeType AddSubOp = Op.first ? ISD::ADD : ISD::SUB;
15479
- Result = DAG.getNode(AddSubOp, DL, N->getValueType(0) , Result, ShiftVal);
15475
+ Result = DAG.getNode(AddSubOp, DL, VT , Result, ShiftVal);
15480
15476
}
15481
-
15482
15477
return Result;
15483
15478
}
15479
+ // Try to expand a multiply to a sequence of shifts and add/subs,
15480
+ // for a machine w/o native mul instruction.
15481
+ static SDValue expandMulToBasicOps(SDNode *N, SelectionDAG &DAG,
15482
+ uint64_t MulAmt) {
15483
+ EVT VT = N->getValueType(0);
15484
+ const uint64_t BitWidth = VT.getFixedSizeInBits();
15485
+ SDLoc DL(N);
15486
+
15487
+ if (MulAmt == 0)
15488
+ return DAG.getConstant(0, DL, N->getValueType(0));
15489
+
15490
+ // Try to factorize into (2^N) * (2^M_1 +/- 1) + (2^M_2 +/- 1) + ...
15491
+ uint64_t E = MulAmt;
15492
+ uint64_t TrailingZeros = 0;
15493
+
15494
+ while (E > 0 && (E & 1) == 0) {
15495
+ E >>= 1;
15496
+ TrailingZeros++;
15497
+ }
15498
+
15499
+ llvm::SmallVector<std::pair<bool, uint64_t>> Factors; // {is_2^M+1, M}
15500
+
15501
+ while (E > 1) {
15502
+ bool Found = false;
15503
+ for (int64_t I = BitWidth - 1; I >= 2; --I) {
15504
+ uint64_t Factor = 1ULL << I;
15505
+
15506
+ if (E % (Factor - 1) == 0) {
15507
+ Factors.push_back({false, I});
15508
+ E /= Factor - 1;
15509
+ Found = true;
15510
+ break;
15511
+ }
15512
+
15513
+ if (E % (Factor + 1) == 0) {
15514
+ Factors.push_back({true, I});
15515
+ E /= Factor + 1;
15516
+ Found = true;
15517
+ break;
15518
+ }
15519
+ }
15520
+ if (!Found)
15521
+ break;
15522
+ }
15523
+
15524
+ SDValue Result;
15525
+ SDValue N0 = N->getOperand(0);
15526
+
15527
+ bool UseFactorization =
15528
+ !Factors.empty() && (E < MulAmt) && (Factors.size() < 5);
15529
+
15530
+ if (UseFactorization) {
15531
+ if (E == 1)
15532
+ Result = N0;
15533
+ else
15534
+ Result = expandMulToNAFSequence(N, DAG, DL, E);
15535
+
15536
+ for (const auto &F : Factors) {
15537
+ SDValue ShiftVal = DAG.getNode(ISD::SHL, DL, VT, Result,
15538
+ DAG.getConstant(F.second, DL, VT));
15539
+
15540
+ ISD::NodeType AddSubOp = F.first ? ISD::ADD : ISD::SUB;
15541
+ Result = DAG.getNode(AddSubOp, DL, N->getValueType(0), ShiftVal, Result);
15542
+ }
15543
+
15544
+ if (TrailingZeros > 0)
15545
+ Result = DAG.getNode(ISD::SHL, DL, VT, Result,
15546
+ DAG.getConstant(TrailingZeros, DL, VT));
15547
+
15548
+ return Result;
15549
+ }
15550
+
15551
+ return expandMulToNAFSequence(N, DAG, DL, MulAmt);
15552
+ }
15484
15553
15485
15554
// 2^N +/- 2^M -> (add/sub (shl X, C1), (shl X, C2))
15486
15555
static SDValue expandMulToAddOrSubOfShl(SDNode *N, SelectionDAG &DAG,
0 commit comments