Skip to content

Commit

Permalink
Fix libcall expansion creating DAG nodes with invalid type post type …
Browse files Browse the repository at this point in the history
…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



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@307207 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
vadimcn committed Jul 5, 2017
1 parent 8b70926 commit a671f7f
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 12 deletions.
8 changes: 8 additions & 0 deletions include/llvm/Target/TargetLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -2827,6 +2827,9 @@ class TargetLowering : public TargetLoweringBase {
// 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;
Expand Down Expand Up @@ -2949,6 +2952,11 @@ class TargetLowering : public TargetLoweringBase {
return *this;
}

CallLoweringInfo &setIsPostTypeLegalization(bool Value=true) {
IsPostTypeLegalization = Value;
return *this;
}

ArgListTy &getArgs() {
return Args;
}
Expand Down
20 changes: 8 additions & 12 deletions lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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) {
Expand Down
17 changes: 17 additions & 0 deletions lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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();
Expand Down
21 changes: 21 additions & 0 deletions test/CodeGen/WebAssembly/umulo-i64.ll
Original file line number Diff line number Diff line change
@@ -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 }

0 comments on commit a671f7f

Please sign in to comment.