llvm.org GIT mirror llvm / 362fee9
Lower multiply with overflow checking to __mulo<mode> calls if we haven't been able to lower them any other way. Fixes rdar://9090077 and rdar://9210061 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133288 91177308-0d34-0410-b5e6-96231b3b80d8 Eric Christopher 9 years ago
5 changed file(s) with 113 addition(s) and 5 deletion(s). Raw diff Collapse all Expand all
2121 /// RTLIB::Libcall enum - This enum defines all of the runtime library calls
2222 /// the backend can emit. The various long double types cannot be merged,
2323 /// because 80-bit library functions use "xf" and 128-bit use "tf".
24 ///
24 ///
2525 /// When adding PPCF128 functions here, note that their names generally need
2626 /// to be overridden for Darwin with the xxx$LDBL128 form. See
2727 /// PPCISelLowering.cpp.
4545 MUL_I32,
4646 MUL_I64,
4747 MUL_I128,
48 MULO_I32,
49 MULO_I64,
50 MULO_I128,
4851 SDIV_I8,
4952 SDIV_I16,
5053 SDIV_I32,
1818 //===----------------------------------------------------------------------===//
1919
2020 #include "LegalizeTypes.h"
21 #include "llvm/DerivedTypes.h"
2122 #include "llvm/CodeGen/PseudoSourceValue.h"
2223 #include "llvm/Support/ErrorHandling.h"
2324 #include "llvm/Support/raw_ostream.h"
10711072 case ISD::SSUBO: ExpandIntRes_SADDSUBO(N, Lo, Hi); break;
10721073 case ISD::UADDO:
10731074 case ISD::USUBO: ExpandIntRes_UADDSUBO(N, Lo, Hi); break;
1075 case ISD::UMULO:
1076 case ISD::SMULO: ExpandIntRes_XMULO(N, Lo, Hi); break;
10741077 }
10751078
10761079 // If Lo/Hi is null, the sub-method took care of registering results etc.
21482151 ReplaceValueWith(SDValue(N, 1), Ofl);
21492152 }
21502153
2154 void DAGTypeLegalizer::ExpandIntRes_XMULO(SDNode *N,
2155 SDValue &Lo, SDValue &Hi) {
2156 EVT VT = N->getValueType(0);
2157 const Type *RetTy = VT.getTypeForEVT(*DAG.getContext());
2158 EVT PtrVT = TLI.getPointerTy();
2159 const Type *PtrTy = PtrVT.getTypeForEVT(*DAG.getContext());
2160 DebugLoc dl = N->getDebugLoc();
2161
2162 // Expand the result by simply replacing it with the equivalent
2163 // non-overflow-checking operation.
2164 RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
2165 if (VT == MVT::i32)
2166 LC = RTLIB::MULO_I32;
2167 else if (VT == MVT::i64)
2168 LC = RTLIB::MULO_I64;
2169 else if (VT == MVT::i128)
2170 LC = RTLIB::MULO_I128;
2171 assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported XMULO!");
2172
2173 SDValue Temp = DAG.CreateStackTemporary(PtrVT);
2174 // Temporary for the overflow value, default it to zero.
2175 SDValue Chain = DAG.getStore(DAG.getEntryNode(), dl,
2176 DAG.getConstant(0, PtrVT), Temp,
2177 MachinePointerInfo(), false, false, 0);
2178
2179 TargetLowering::ArgListTy Args;
2180 TargetLowering::ArgListEntry Entry;
2181 for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
2182 EVT ArgVT = N->getOperand(i).getValueType();
2183 const Type *ArgTy = ArgVT.getTypeForEVT(*DAG.getContext());
2184 Entry.Node = N->getOperand(i);
2185 Entry.Ty = ArgTy;
2186 Entry.isSExt = true;
2187 Entry.isZExt = false;
2188 Args.push_back(Entry);
2189 }
2190
2191 // Also pass the address of the overflow check.
2192 Entry.Node = Temp;
2193 Entry.Ty = PtrTy->getPointerTo();
2194 Entry.isSExt = true;
2195 Entry.isZExt = false;
2196 Args.push_back(Entry);
2197
2198 SDValue Func = DAG.getExternalSymbol(TLI.getLibcallName(LC), PtrVT);
2199 std::pair CallInfo =
2200 TLI.LowerCallTo(Chain, RetTy, true, false, false, false,
2201 0, TLI.getLibcallCallingConv(LC), false,
2202 true, Func, Args, DAG, dl);
2203
2204 SplitInteger(CallInfo.first, Lo, Hi);
2205 SDValue Temp2 = DAG.getLoad(PtrVT, dl, CallInfo.second, Temp,
2206 MachinePointerInfo(), false, false, 0);
2207 SDValue Ofl = DAG.getSetCC(dl, N->getValueType(1), Temp2,
2208 DAG.getConstant(0, PtrVT),
2209 ISD::SETNE);
2210 // Use the overflow from the libcall everywhere.
2211 ReplaceValueWith(SDValue(N, 1), Ofl);
2212 }
2213
21512214 void DAGTypeLegalizer::ExpandIntRes_UDIV(SDNode *N,
21522215 SDValue &Lo, SDValue &Hi) {
21532216 EVT VT = N->getValueType(0);
317317
318318 void ExpandIntRes_SADDSUBO (SDNode *N, SDValue &Lo, SDValue &Hi);
319319 void ExpandIntRes_UADDSUBO (SDNode *N, SDValue &Lo, SDValue &Hi);
320 void ExpandIntRes_XMULO (SDNode *N, SDValue &Lo, SDValue &Hi);
320321
321322 void ExpandShiftByConstant(SDNode *N, unsigned Amt,
322323 SDValue &Lo, SDValue &Hi);
8080 Names[RTLIB::MUL_I32] = "__mulsi3";
8181 Names[RTLIB::MUL_I64] = "__muldi3";
8282 Names[RTLIB::MUL_I128] = "__multi3";
83 Names[RTLIB::MULO_I32] = "__mulosi4";
84 Names[RTLIB::MULO_I64] = "__mulodi4";
85 Names[RTLIB::MULO_I128] = "__muloti4";
8386 Names[RTLIB::SDIV_I8] = "__divqi3";
8487 Names[RTLIB::SDIV_I16] = "__divhi3";
8588 Names[RTLIB::SDIV_I32] = "__divsi3";
19131916 // comparisons.
19141917 if (isa(N0.getNode()))
19151918 return DAG.getSetCC(dl, VT, N1, N0, ISD::getSetCCSwappedOperands(Cond));
1916
1919
19171920 if (ConstantSDNode *N1C = dyn_cast(N1.getNode())) {
19181921 const APInt &C1 = N1C->getAPIntValue();
19191922
26722675 std::string &Constraint,
26732676 std::vector &Ops,
26742677 SelectionDAG &DAG) const {
2675
2678
26762679 if (Constraint.length() > 1) return;
2677
2680
26782681 char ConstraintLetter = Constraint[0];
26792682 switch (ConstraintLetter) {
26802683 default: break;
28642867 report_fatal_error("Indirect operand for inline asm not a pointer!");
28652868 OpTy = PtrTy->getElementType();
28662869 }
2867
2870
28682871 // Look for vector wrapped in a struct. e.g. { <16 x i8> }.
28692872 if (const StructType *STy = dyn_cast(OpTy))
28702873 if (STy->getNumElements() == 1)
0 ; RUN: llc < %s -mtriple=x86_64-apple-darwin | FileCheck %s
1 %0 = type { i64, i64 }
2 %1 = type { i128, i1 }
3
4 @.str = private unnamed_addr constant [11 x i8] c"%llx %llx\0A\00", align 1
5
6 define %0 @x(i64 %a.coerce0, i64 %a.coerce1, i64 %b.coerce0, i64 %b.coerce1) nounwind uwtable ssp {
7 entry:
8 %tmp16 = zext i64 %a.coerce0 to i128
9 %tmp11 = zext i64 %a.coerce1 to i128
10 %tmp12 = shl nuw i128 %tmp11, 64
11 %ins14 = or i128 %tmp12, %tmp16
12 %tmp6 = zext i64 %b.coerce0 to i128
13 %tmp3 = zext i64 %b.coerce1 to i128
14 %tmp4 = shl nuw i128 %tmp3, 64
15 %ins = or i128 %tmp4, %tmp6
16 %0 = tail call %1 @llvm.smul.with.overflow.i128(i128 %ins14, i128 %ins)
17 ; CHECK: callq ___muloti4
18 %1 = extractvalue %1 %0, 0
19 %2 = extractvalue %1 %0, 1
20 br i1 %2, label %overflow, label %nooverflow
21
22 overflow: ; preds = %entry
23 tail call void @llvm.trap()
24 unreachable
25
26 nooverflow: ; preds = %entry
27 %tmp20 = trunc i128 %1 to i64
28 %tmp21 = insertvalue %0 undef, i64 %tmp20, 0
29 %tmp22 = lshr i128 %1, 64
30 %tmp23 = trunc i128 %tmp22 to i64
31 %tmp24 = insertvalue %0 %tmp21, i64 %tmp23, 1
32 ret %0 %tmp24
33 }
34
35 declare %1 @llvm.smul.with.overflow.i128(i128, i128) nounwind readnone
36
37 declare void @llvm.trap() nounwind