mirror of
https://github.com/RPCS3/llvm.git
synced 2025-05-13 08:56:04 +00:00
[mips] Improve genConstMult() to work with arbitrary precision
APInt is now used instead of uint64_t in function genConstMult() allowing multiplication optimizations with constants of arbitrary length. Patch by Milos Stojanovic. Differential Revision: https://reviews.llvm.org/D38130 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@318296 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
b3380b5cf4
commit
9c8398490b
@ -701,11 +701,8 @@ static SDValue performORCombine(SDNode *N, SelectionDAG &DAG,
|
||||
return SDValue();
|
||||
}
|
||||
|
||||
static SDValue genConstMult(SDValue X, uint64_t C, const SDLoc &DL, EVT VT,
|
||||
static SDValue genConstMult(SDValue X, APInt C, const SDLoc &DL, EVT VT,
|
||||
EVT ShiftTy, SelectionDAG &DAG) {
|
||||
// Clear the upper (64 - VT.sizeInBits) bits.
|
||||
C &= ((uint64_t)-1) >> (64 - VT.getSizeInBits());
|
||||
|
||||
// Return 0.
|
||||
if (C == 0)
|
||||
return DAG.getConstant(0, DL, VT);
|
||||
@ -715,18 +712,19 @@ static SDValue genConstMult(SDValue X, uint64_t C, const SDLoc &DL, EVT VT,
|
||||
return X;
|
||||
|
||||
// If c is power of 2, return (shl x, log2(c)).
|
||||
if (isPowerOf2_64(C))
|
||||
if (C.isPowerOf2())
|
||||
return DAG.getNode(ISD::SHL, DL, VT, X,
|
||||
DAG.getConstant(Log2_64(C), DL, ShiftTy));
|
||||
DAG.getConstant(C.logBase2(), DL, ShiftTy));
|
||||
|
||||
unsigned Log2Ceil = Log2_64_Ceil(C);
|
||||
uint64_t Floor = 1LL << Log2_64(C);
|
||||
uint64_t Ceil = Log2Ceil == 64 ? 0LL : 1LL << Log2Ceil;
|
||||
unsigned BitWidth = C.getBitWidth();
|
||||
APInt Floor = APInt(BitWidth, 1) << C.logBase2();
|
||||
APInt Ceil = C.isNegative() ? APInt(BitWidth, 0) :
|
||||
APInt(BitWidth, 1) << C.ceilLogBase2();
|
||||
|
||||
// If |c - floor_c| <= |c - ceil_c|,
|
||||
// where floor_c = pow(2, floor(log2(c))) and ceil_c = pow(2, ceil(log2(c))),
|
||||
// return (add constMult(x, floor_c), constMult(x, c - floor_c)).
|
||||
if (C - Floor <= Ceil - C) {
|
||||
if ((C - Floor).ule(Ceil - C)) {
|
||||
SDValue Op0 = genConstMult(X, Floor, DL, VT, ShiftTy, DAG);
|
||||
SDValue Op1 = genConstMult(X, C - Floor, DL, VT, ShiftTy, DAG);
|
||||
return DAG.getNode(ISD::ADD, DL, VT, Op0, Op1);
|
||||
@ -746,7 +744,7 @@ static SDValue performMULCombine(SDNode *N, SelectionDAG &DAG,
|
||||
|
||||
if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1)))
|
||||
if (!VT.isVector())
|
||||
return genConstMult(N->getOperand(0), C->getZExtValue(), SDLoc(N), VT,
|
||||
return genConstMult(N->getOperand(0), C->getAPIntValue(), SDLoc(N), VT,
|
||||
TL->getScalarShiftAmountTy(DAG.getDataLayout(), VT),
|
||||
DAG);
|
||||
|
||||
|
@ -46,3 +46,48 @@ entry:
|
||||
%mul = mul nsw i64 %a, -9223372036854775805
|
||||
ret i64 %mul
|
||||
}
|
||||
|
||||
; CHECK64-LABEL: muln170141183460469231731687303715884105725_128:
|
||||
; CHECK64-DAG: dsrl $[[R0:[0-9]+]], $4, 63
|
||||
; CHECK64-DAG: dsll $[[R1:[0-9]+]], $5, 1
|
||||
; CHECK64-DAG: or $[[R2:[0-9]+]], $[[R1]], $[[R0]]
|
||||
; CHECK64-DAG: daddu $[[R3:[0-9]+]], $[[R2]], $5
|
||||
; CHECK64-DAG: dsll $[[R4:[0-9]+]], $4, 1
|
||||
; CHECK64-DAG: daddu $[[R5:[0-9]+]], $[[R4]], $4
|
||||
; CHECK64-DAG: sltu $[[R6:[0-9]+]], $[[R5]], $[[R4]]
|
||||
; CHECK64-DAG: dsll $[[R7:[0-9]+]], $[[R6]], 32
|
||||
; CHECK64-DAG: dsrl $[[R8:[0-9]+]], $[[R7]], 32
|
||||
; CHECK64-DAG: daddu $[[R9:[0-9]+]], $[[R3]], $[[R8]]
|
||||
; CHECK64-DAG: dsll $[[R10:[0-9]+]], $4, 63
|
||||
; CHECK64: daddu ${{[0-9]+}}, $[[R10]], $[[R9]]
|
||||
|
||||
define i128 @muln170141183460469231731687303715884105725_128(i128 signext %a) {
|
||||
entry:
|
||||
%mul = mul nsw i128 %a, -170141183460469231731687303715884105725
|
||||
ret i128 %mul
|
||||
}
|
||||
|
||||
; CHECK64-LABEL: mul170141183460469231731687303715884105723_128:
|
||||
; CHECK64-DAG: dsrl $[[R0:[0-9]+]], $4, 62
|
||||
; CHECK64-DAG: dsll $[[R1:[0-9]+]], $5, 2
|
||||
; CHECK64-DAG: or $[[R2:[0-9]+]], $[[R1]], $[[R0]]
|
||||
; CHECK64-DAG: daddu $[[R3:[0-9]+]], $[[R2]], $5
|
||||
; CHECK64-DAG: dsll $[[R4:[0-9]+]], $4, 2
|
||||
; CHECK64-DAG: daddu $[[R5:[0-9]+]], $[[R4]], $4
|
||||
; CHECK64-DAG: sltu $[[R6:[0-9]+]], $[[R5]], $[[R4]]
|
||||
; CHECK64-DAG: dsll $[[R7:[0-9]+]], $[[R6]], 32
|
||||
; CHECK64-DAG: dsrl $[[R8:[0-9]+]], $[[R7]], 32
|
||||
; CHECK64-DAG: daddu $[[R9:[0-9]+]], $[[R3]], $[[R8]]
|
||||
; CHECK64-DAG: dsll $[[R10:[0-9]+]], $4, 63
|
||||
; CHECK64-DAG: dsubu $[[R11:[0-9]+]], $[[R10]], $[[R9]]
|
||||
; CHECK64-DAG: sltu $[[R12:[0-9]+]], $zero, $[[R5]]
|
||||
; CHECK64-DAG: dsll $[[R13:[0-9]+]], $[[R12]], 32
|
||||
; CHECK64-DAG: dsrl $[[R14:[0-9]+]], $[[R13]], 32
|
||||
; CHECK64-DAG: dsubu $[[R15:[0-9]+]], $[[R11]], $[[R14]]
|
||||
; CHECK64: dnegu ${{[0-9]+}}, $[[R5]]
|
||||
|
||||
define i128 @mul170141183460469231731687303715884105723_128(i128 signext %a) {
|
||||
entry:
|
||||
%mul = mul nsw i128 %a, 170141183460469231731687303715884105723
|
||||
ret i128 %mul
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user