forked from OSchip/llvm-project
Fix libcall expansion creating DAG nodes with invalid type post type legalization.
If we are lowering a libcall after legalization, we'll split the return type into a pair of legal values. Patch by Jatin Bhateja and Eli Friedman. Differential Revision: https://reviews.llvm.org/D34240 llvm-svn: 307207
This commit is contained in:
parent
d0494046c7
commit
e6f76558c7
|
@ -2827,6 +2827,9 @@ public:
|
|||
// TargetLowering::LowerCall that perform tail call conversions.
|
||||
bool IsTailCall = false;
|
||||
|
||||
// Is Call lowering done post SelectionDAG type legalization.
|
||||
bool IsPostTypeLegalization = false;
|
||||
|
||||
unsigned NumFixedArgs = -1;
|
||||
CallingConv::ID CallConv = CallingConv::C;
|
||||
SDValue Callee;
|
||||
|
@ -2949,6 +2952,11 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
CallLoweringInfo &setIsPostTypeLegalization(bool Value=true) {
|
||||
IsPostTypeLegalization = Value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ArgListTy &getArgs() {
|
||||
return Args;
|
||||
}
|
||||
|
|
|
@ -1991,7 +1991,8 @@ SDValue SelectionDAGLegalize::ExpandLibCall(RTLIB::Libcall LC, SDNode *Node,
|
|||
std::move(Args))
|
||||
.setTailCall(isTailCall)
|
||||
.setSExtResult(isSigned)
|
||||
.setZExtResult(!isSigned);
|
||||
.setZExtResult(!isSigned)
|
||||
.setIsPostTypeLegalization(true);
|
||||
|
||||
std::pair<SDValue, SDValue> CallInfo = TLI.LowerCallTo(CLI);
|
||||
|
||||
|
@ -2029,7 +2030,8 @@ SDValue SelectionDAGLegalize::ExpandLibCall(RTLIB::Libcall LC, EVT RetVT,
|
|||
.setLibCallee(TLI.getLibcallCallingConv(LC), RetTy, Callee,
|
||||
std::move(Args))
|
||||
.setSExtResult(isSigned)
|
||||
.setZExtResult(!isSigned);
|
||||
.setZExtResult(!isSigned)
|
||||
.setIsPostTypeLegalization(true);
|
||||
|
||||
std::pair<SDValue,SDValue> CallInfo = TLI.LowerCallTo(CLI);
|
||||
|
||||
|
@ -3565,16 +3567,10 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
|
|||
SDValue Args[] = { HiLHS, LHS, HiRHS, RHS };
|
||||
Ret = ExpandLibCall(LC, WideVT, Args, 4, isSigned, dl);
|
||||
}
|
||||
BottomHalf = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, VT, Ret,
|
||||
DAG.getIntPtrConstant(0, dl));
|
||||
TopHalf = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, VT, Ret,
|
||||
DAG.getIntPtrConstant(1, dl));
|
||||
// Ret is a node with an illegal type. Because such things are not
|
||||
// generally permitted during this phase of legalization, make sure the
|
||||
// node has no more uses. The above EXTRACT_ELEMENT nodes should have been
|
||||
// folded.
|
||||
assert(Ret->use_empty() &&
|
||||
"Unexpected uses of illegally type from expanded lib call.");
|
||||
assert(Ret.getOpcode() == ISD::MERGE_VALUES &&
|
||||
"Ret value is a collection of constituent nodes holding result.");
|
||||
BottomHalf = Ret.getOperand(0);
|
||||
TopHalf = Ret.getOperand(1);
|
||||
}
|
||||
|
||||
if (isSigned) {
|
||||
|
|
|
@ -7842,6 +7842,22 @@ TargetLowering::LowerCallTo(TargetLowering::CallLoweringInfo &CLI) const {
|
|||
auto &DL = CLI.DAG.getDataLayout();
|
||||
ComputeValueVTs(*this, DL, CLI.RetTy, RetTys, &Offsets);
|
||||
|
||||
if (CLI.IsPostTypeLegalization) {
|
||||
// If we are lowering a libcall after legalization, split the return type.
|
||||
SmallVector<EVT, 4> OldRetTys = std::move(RetTys);
|
||||
SmallVector<uint64_t, 4> OldOffsets = std::move(Offsets);
|
||||
for (size_t i = 0, e = OldRetTys.size(); i != e; ++i) {
|
||||
EVT RetVT = OldRetTys[i];
|
||||
uint64_t Offset = OldOffsets[i];
|
||||
MVT RegisterVT = getRegisterType(CLI.RetTy->getContext(), RetVT);
|
||||
unsigned NumRegs = getNumRegisters(CLI.RetTy->getContext(), RetVT);
|
||||
unsigned RegisterVTSize = RegisterVT.getSizeInBits();
|
||||
RetTys.append(NumRegs, RegisterVT);
|
||||
for (unsigned j = 0; j != NumRegs; ++j)
|
||||
Offsets.push_back(Offset + j * RegisterVTSize);
|
||||
}
|
||||
}
|
||||
|
||||
SmallVector<ISD::OutputArg, 4> Outs;
|
||||
GetReturnInfo(CLI.RetTy, getReturnAttrs(CLI), Outs, *this, DL);
|
||||
|
||||
|
@ -7924,6 +7940,7 @@ TargetLowering::LowerCallTo(TargetLowering::CallLoweringInfo &CLI) const {
|
|||
for (unsigned i = 0, e = Args.size(); i != e; ++i) {
|
||||
SmallVector<EVT, 4> ValueVTs;
|
||||
ComputeValueVTs(*this, DL, Args[i].Ty, ValueVTs);
|
||||
// FIXME: Split arguments if CLI.IsPostTypeLegalization
|
||||
Type *FinalType = Args[i].Ty;
|
||||
if (Args[i].IsByVal)
|
||||
FinalType = cast<PointerType>(Args[i].Ty)->getElementType();
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
; RUN: llc < %s -asm-verbose=false | FileCheck %s
|
||||
; Test that UMULO works correctly on 64-bit operands.
|
||||
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
|
||||
target triple = "wasm32-unknown-emscripten"
|
||||
|
||||
; CHECK-LABEL: _ZN4core3num21_$LT$impl$u20$u64$GT$15overflowing_mul17h07be88b4cbac028fE:
|
||||
; CHECK: __multi3
|
||||
; Function Attrs: inlinehint
|
||||
define void @"_ZN4core3num21_$LT$impl$u20$u64$GT$15overflowing_mul17h07be88b4cbac028fE"(i64, i64) unnamed_addr #0 {
|
||||
start:
|
||||
%2 = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %0, i64 %1)
|
||||
%3 = extractvalue { i64, i1 } %2, 0
|
||||
store i64 %3, i64* undef
|
||||
unreachable
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind readnone speculatable
|
||||
declare { i64, i1 } @llvm.umul.with.overflow.i64(i64, i64) #1
|
||||
|
||||
attributes #0 = { inlinehint }
|
||||
attributes #1 = { nounwind readnone speculatable }
|
Loading…
Reference in New Issue