Index: lib/Target/Mips/MipsSEISelLowering.cpp =================================================================== --- lib/Target/Mips/MipsSEISelLowering.cpp +++ lib/Target/Mips/MipsSEISelLowering.cpp @@ -701,11 +701,8 @@ 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 @@ 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 @@ if (ConstantSDNode *C = dyn_cast(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); Index: test/CodeGen/Mips/const-mult.ll =================================================================== --- test/CodeGen/Mips/const-mult.ll +++ test/CodeGen/Mips/const-mult.ll @@ -46,3 +46,48 @@ %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 +} \ No newline at end of file