llvm.org GIT mirror llvm / abbbfbd
Rewrite the expander for umulo/smulo to remember to sign extend the input manually and pass all (now) 4 arguments to the mul libcall. Add a new ExpandLibCall for just this (copied gratuitously from type legalization). Fixes rdar://9292577 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@129842 91177308-0d34-0410-b5e6-96231b3b80d8 Eric Christopher 9 years ago
2 changed file(s) with 86 addition(s) and 11 deletion(s). Raw diff Collapse all Expand all
141141 DebugLoc dl);
142142
143143 SDValue ExpandLibCall(RTLIB::Libcall LC, SDNode *Node, bool isSigned);
144 SDValue ExpandLibCall(RTLIB::Libcall LC, EVT RetVT, const SDValue *Ops,
145 unsigned NumOps, bool isSigned, DebugLoc dl);
146
144147 std::pair ExpandChainLibCall(RTLIB::Libcall LC,
145148 SDNode *Node, bool isSigned);
146149 SDValue ExpandFPLibCall(SDNode *Node, RTLIB::Libcall Call_F32,
20552058 return CallInfo.first;
20562059 }
20572060
2061 /// ExpandLibCall - Generate a libcall taking the given operands as arguments
2062 /// and returning a result of type RetVT.
2063 SDValue SelectionDAGLegalize::ExpandLibCall(RTLIB::Libcall LC, EVT RetVT,
2064 const SDValue *Ops, unsigned NumOps,
2065 bool isSigned, DebugLoc dl) {
2066 TargetLowering::ArgListTy Args;
2067 Args.reserve(NumOps);
2068
2069 TargetLowering::ArgListEntry Entry;
2070 for (unsigned i = 0; i != NumOps; ++i) {
2071 Entry.Node = Ops[i];
2072 Entry.Ty = Entry.Node.getValueType().getTypeForEVT(*DAG.getContext());
2073 Entry.isSExt = isSigned;
2074 Entry.isZExt = !isSigned;
2075 Args.push_back(Entry);
2076 }
2077 SDValue Callee = DAG.getExternalSymbol(TLI.getLibcallName(LC),
2078 TLI.getPointerTy());
2079
2080 const Type *RetTy = RetVT.getTypeForEVT(*DAG.getContext());
2081 std::pair CallInfo =
2082 TLI.LowerCallTo(DAG.getEntryNode(), RetTy, isSigned, !isSigned, false,
2083 false, 0, TLI.getLibcallCallingConv(LC), false,
2084 /*isReturnValueUsed=*/true,
2085 Callee, Args, DAG, dl);
2086
2087 // Legalize the call sequence, starting with the chain. This will advance
2088 // the LastCALLSEQ_END to the legalized version of the CALLSEQ_END node that
2089 // was added by LowerCallTo (guaranteeing proper serialization of calls).
2090 LegalizeOp(CallInfo.second);
2091
2092 return CallInfo.first;
2093 }
2094
20582095 // ExpandChainLibCall - Expand a node into a call to a libcall. Similar to
20592096 // ExpandLibCall except that the first operand is the in-chain.
20602097 std::pair
33543391 case ISD::UMULO:
33553392 case ISD::SMULO: {
33563393 EVT VT = Node->getValueType(0);
3394 EVT WideVT = EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits() * 2);
33573395 SDValue LHS = Node->getOperand(0);
33583396 SDValue RHS = Node->getOperand(1);
33593397 SDValue BottomHalf;
33713409 TopHalf = BottomHalf.getValue(1);
33723410 } else if (TLI.isTypeLegal(EVT::getIntegerVT(*DAG.getContext(),
33733411 VT.getSizeInBits() * 2))) {
3374 EVT WideVT = EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits() * 2);
33753412 LHS = DAG.getNode(Ops[isSigned][2], dl, WideVT, LHS);
33763413 RHS = DAG.getNode(Ops[isSigned][2], dl, WideVT, RHS);
33773414 Tmp1 = DAG.getNode(ISD::MUL, dl, WideVT, LHS, RHS);
33843421 // have a libcall big enough.
33853422 // Also, we can fall back to a division in some cases, but that's a big
33863423 // performance hit in the general case.
3387 EVT WideVT = EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits() * 2);
33883424 RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
33893425 if (WideVT == MVT::i16)
33903426 LC = RTLIB::MUL_I16;
33953431 else if (WideVT == MVT::i128)
33963432 LC = RTLIB::MUL_I128;
33973433 assert(LC != RTLIB::UNKNOWN_LIBCALL && "Cannot expand this operation!");
3398 LHS = DAG.getNode(Ops[isSigned][2], dl, WideVT, LHS);
3399 RHS = DAG.getNode(Ops[isSigned][2], dl, WideVT, RHS);
3400
3401 SDValue Ret = ExpandLibCall(LC, Node, isSigned);
3402 BottomHalf = DAG.getNode(ISD::TRUNCATE, dl, VT, Ret);
3403 TopHalf = DAG.getNode(ISD::SRL, dl, Ret.getValueType(), Ret,
3404 DAG.getConstant(VT.getSizeInBits(), TLI.getPointerTy()));
3405 TopHalf = DAG.getNode(ISD::TRUNCATE, dl, VT, TopHalf);
3406 }
3434
3435 // The high part is obtained by SRA'ing all but one of the bits of low
3436 // part.
3437 unsigned LoSize = VT.getSizeInBits();
3438 SDValue HiLHS = DAG.getNode(ISD::SRA, dl, VT, RHS,
3439 DAG.getConstant(LoSize-1, TLI.getPointerTy()));
3440 SDValue HiRHS = DAG.getNode(ISD::SRA, dl, VT, LHS,
3441 DAG.getConstant(LoSize-1, TLI.getPointerTy()));
3442
3443 // Here we're passing the 2 arguments explicitly as 4 arguments that are
3444 // pre-lowered to the correct types. This all depends upon WideVT not
3445 // being a legal type for the architecture and thus has to be split to
3446 // two arguments.
3447 SDValue Args[] = { LHS, HiLHS, RHS, HiRHS };
3448 SDValue Ret = ExpandLibCall(LC, WideVT, Args, 4, isSigned, dl);
3449 BottomHalf = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, VT, Ret,
3450 DAG.getIntPtrConstant(0));
3451 TopHalf = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, VT, Ret,
3452 DAG.getIntPtrConstant(1));
3453 }
3454
34073455 if (isSigned) {
34083456 Tmp1 = DAG.getConstant(VT.getSizeInBits() - 1,
34093457 TLI.getShiftAmountTy(BottomHalf.getValueType()));
1111 }
1212
1313 declare %umul.ty @llvm.umul.with.overflow.i32(i32, i32) nounwind readnone
14
15 define i32 @f(i32 %argc, i8** %argv) ssp {
16 ; CHECK: func
17 ; CHECK: str r0
18 ; CHECK: movs r2
19 ; CHECK: mov r1
20 ; CHECK: mov r3
21 ; CHECK: muldi3
22 %1 = alloca i32, align 4
23 %2 = alloca i32, align 4
24 %3 = alloca i8**, align 4
25 %m_degree = alloca i32, align 4
26 store i32 0, i32* %1
27 store i32 %argc, i32* %2, align 4
28 store i8** %argv, i8*** %3, align 4
29 store i32 10, i32* %m_degree, align 4
30 %4 = load i32* %m_degree, align 4
31 %5 = call %umul.ty @llvm.umul.with.overflow.i32(i32 %4, i32 8)
32 %6 = extractvalue %umul.ty %5, 1
33 %7 = extractvalue %umul.ty %5, 0
34 %8 = select i1 %6, i32 -1, i32 %7
35 %9 = call noalias i8* @_Znam(i32 %8)
36 %10 = bitcast i8* %9 to double*
37 ret i32 0
38 }
39
40 declare noalias i8* @_Znam(i32)