diff options
-rw-r--r-- | llvm/lib/Target/Sparc/SparcISelLowering.cpp | 52 | ||||
-rw-r--r-- | llvm/lib/Target/Sparc/SparcISelLowering.h | 1 | ||||
-rw-r--r-- | llvm/test/CodeGen/SPARC/cast-sret-func.ll | 17 | ||||
-rw-r--r-- | llvm/test/CodeGen/SPARC/fp128.ll | 10 |
4 files changed, 33 insertions, 47 deletions
diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp index 9a4f67e0ee8..ab1cc7caaaa 100644 --- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp +++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp @@ -780,6 +780,7 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI, const unsigned StackOffset = 92; bool hasStructRetAttr = false; + unsigned SRetArgSize = 0; // Walk the register/memloc assignments, inserting copies/loads. for (unsigned i = 0, realArgIdx = 0, byvalArgIdx = 0, e = ArgLocs.size(); i != e; @@ -824,6 +825,11 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI, MemOpChains.push_back( DAG.getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo())); hasStructRetAttr = true; + // sret only allowed on first argument + assert(Outs[realArgIdx].OrigArgIndex == 0); + PointerType *Ty = cast<PointerType>(CLI.getArgs()[0].Ty); + Type *ElementTy = Ty->getElementType(); + SRetArgSize = DAG.getDataLayout().getTypeAllocSize(ElementTy); continue; } @@ -932,7 +938,6 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI, InFlag = Chain.getValue(1); } - unsigned SRetArgSize = (hasStructRetAttr)? getSRetArgSize(DAG, Callee):0; bool hasReturnsTwice = hasReturnsTwiceAttr(DAG, Callee, CLI.CS); // If the callee is a GlobalAddress node (quite common, every direct call is) @@ -1032,51 +1037,6 @@ unsigned SparcTargetLowering::getRegisterByName(const char* RegName, EVT VT, report_fatal_error("Invalid register name global variable"); } -// This functions returns true if CalleeName is a ABI function that returns -// a long double (fp128). -static bool isFP128ABICall(const char *CalleeName) -{ - static const char *const ABICalls[] = - { "_Q_add", "_Q_sub", "_Q_mul", "_Q_div", - "_Q_sqrt", "_Q_neg", - "_Q_itoq", "_Q_stoq", "_Q_dtoq", "_Q_utoq", - "_Q_lltoq", "_Q_ulltoq", - nullptr - }; - for (const char * const *I = ABICalls; *I != nullptr; ++I) - if (strcmp(CalleeName, *I) == 0) - return true; - return false; -} - -unsigned -SparcTargetLowering::getSRetArgSize(SelectionDAG &DAG, SDValue Callee) const -{ - const Function *CalleeFn = nullptr; - if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) { - CalleeFn = dyn_cast<Function>(G->getGlobal()); - } else if (ExternalSymbolSDNode *E = - dyn_cast<ExternalSymbolSDNode>(Callee)) { - const Function &F = DAG.getMachineFunction().getFunction(); - const Module *M = F.getParent(); - const char *CalleeName = E->getSymbol(); - CalleeFn = M->getFunction(CalleeName); - if (!CalleeFn && isFP128ABICall(CalleeName)) - return 16; // Return sizeof(fp128) - } - - if (!CalleeFn) - return 0; - - // It would be nice to check for the sret attribute on CalleeFn here, - // but since it is not part of the function type, any check will misfire. - - PointerType *Ty = cast<PointerType>(CalleeFn->arg_begin()->getType()); - Type *ElementTy = Ty->getElementType(); - return DAG.getDataLayout().getTypeAllocSize(ElementTy); -} - - // Fixup floating point arguments in the ... part of a varargs call. // // The SPARC v9 ABI requires that floating point arguments are treated the same diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.h b/llvm/lib/Target/Sparc/SparcISelLowering.h index 0cbbda78788..9741674cbfe 100644 --- a/llvm/lib/Target/Sparc/SparcISelLowering.h +++ b/llvm/lib/Target/Sparc/SparcISelLowering.h @@ -176,7 +176,6 @@ namespace llvm { SDValue LowerEH_SJLJ_LONGJMP(SDValue Op, SelectionDAG &DAG, const SparcTargetLowering &TLI) const ; - unsigned getSRetArgSize(SelectionDAG &DAG, SDValue Callee) const; SDValue withTargetFlags(SDValue Op, unsigned TF, SelectionDAG &DAG) const; SDValue makeHiLoPair(SDValue Op, unsigned HiTF, unsigned LoTF, SelectionDAG &DAG) const; diff --git a/llvm/test/CodeGen/SPARC/cast-sret-func.ll b/llvm/test/CodeGen/SPARC/cast-sret-func.ll new file mode 100644 index 00000000000..1503e278c7d --- /dev/null +++ b/llvm/test/CodeGen/SPARC/cast-sret-func.ll @@ -0,0 +1,17 @@ +; RUN: llc < %s -march=sparc + +; CHECK: call func +; CHECK: st %i0, [%sp+64] +; CHECK: unimp 8 + +%struct = type { i32, i32 } + +define void @test() nounwind { +entry: + %tmp = alloca %struct, align 4 + call void bitcast (void ()* @func to void (%struct*)*) + (%struct* nonnull sret %tmp) + ret void +} + +declare void @func() diff --git a/llvm/test/CodeGen/SPARC/fp128.ll b/llvm/test/CodeGen/SPARC/fp128.ll index bcc013b7357..535f0ef60c4 100644 --- a/llvm/test/CodeGen/SPARC/fp128.ll +++ b/llvm/test/CodeGen/SPARC/fp128.ll @@ -14,9 +14,13 @@ ; HARD: fmulq [[R4]], [[R5:.+]], [[R6:.+]] ; HARD: fdivq [[R6]], [[R2]] ; SOFT: call _Q_add +; SOFT: unimp 16 ; SOFT: call _Q_sub +; SOFT: unimp 16 ; SOFT: call _Q_mul +; SOFT: unimp 16 ; SOFT: call _Q_div +; SOFT: unimp 16 ; CHECK: std ; CHECK: std @@ -101,6 +105,7 @@ declare fp128 @llvm.fabs.f128(fp128) nounwind readonly ; CHECK-LABEL: int_to_f128: ; HARD: fitoq ; SOFT: _Q_itoq +; SOFT: unimp 16 define void @int_to_f128(fp128* noalias sret %scalar.result, i32 %i) { entry: @@ -113,6 +118,7 @@ entry: ; CHECK: ldub ; HARD: faddq ; SOFT: call _Q_add +; SOFT: unimp 16 ; CHECK: stb ; CHECK: ret @@ -128,6 +134,7 @@ entry: ; CHECK-LABEL: uint_to_f128: ; HARD: fdtoq ; SOFT: _Q_utoq +; SOFT: unimp 16 define void @uint_to_f128(fp128* noalias sret %scalar.result, i32 %i) { entry: @@ -159,8 +166,10 @@ entry: ; HARD-DAG: fitoq ; HARD-DAG: fqtoi ; SOFT-DAG: call _Q_lltoq +; SOFT-DAG: unimp 16 ; SOFT-DAG: call _Q_qtoll ; SOFT-DAG: call _Q_itoq +; SOFT-DAG: unimp 16 ; SOFT-DAG: call _Q_qtoi define void @test_itoq_qtoi(i64 %a, i32 %b, fp128* %c, fp128* %d, i64* %ptr0, fp128* %ptr1) { @@ -185,6 +194,7 @@ entry: ; HARD-DAG: fdtoq ; HARD-DAG: fqtoi ; SOFT-DAG: call _Q_utoq +; SOFT-DAG: unimp 16 ; SOFT-DAG: call _Q_qtou define void @test_utoq_qtou(i64 %a, i32 %b, fp128* %c, fp128* %d, i64* %ptr0, fp128* %ptr1) { |