summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Target/Sparc/SparcISelLowering.cpp52
-rw-r--r--llvm/lib/Target/Sparc/SparcISelLowering.h1
-rw-r--r--llvm/test/CodeGen/SPARC/cast-sret-func.ll17
-rw-r--r--llvm/test/CodeGen/SPARC/fp128.ll10
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) {
OpenPOWER on IntegriCloud