AMDGPU: Don't use report_fatal_error for unsupported call types
authorMatt Arsenault <Matthew.Arsenault@amd.com>
Thu, 3 Aug 2017 23:32:41 +0000 (23:32 +0000)
committerMatt Arsenault <Matthew.Arsenault@amd.com>
Thu, 3 Aug 2017 23:32:41 +0000 (23:32 +0000)
llvm-svn: 310004

llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
llvm/lib/Target/AMDGPU/AMDGPUISelLowering.h
llvm/lib/Target/AMDGPU/SIISelLowering.cpp
llvm/test/CodeGen/AMDGPU/call.ll [deleted file]
llvm/test/CodeGen/AMDGPU/promote-alloca-bitcast-function.ll
llvm/test/CodeGen/AMDGPU/unsupported-calls.ll [new file with mode: 0644]

index 4f65b40..6597f79 100644 (file)
@@ -1001,8 +1001,9 @@ CCAssignFn *AMDGPUTargetLowering::CCAssignFnForReturn(CallingConv::ID CC,
   return AMDGPUCallLowering::CCAssignFnForReturn(CC, IsVarArg);
 }
 
-SDValue AMDGPUTargetLowering::LowerCall(CallLoweringInfo &CLI,
-                                        SmallVectorImpl<SDValue> &InVals) const {
+SDValue AMDGPUTargetLowering::lowerUnhandledCall(CallLoweringInfo &CLI,
+                                                 SmallVectorImpl<SDValue> &InVals,
+                                                 StringRef Reason) const {
   SDValue Callee = CLI.Callee;
   SelectionDAG &DAG = CLI.DAG;
 
@@ -1016,7 +1017,7 @@ SDValue AMDGPUTargetLowering::LowerCall(CallLoweringInfo &CLI,
     FuncName = G->getGlobal()->getName();
 
   DiagnosticInfoUnsupported NoCalls(
-      Fn, "unsupported call to function " + FuncName, CLI.DL.getDebugLoc());
+    Fn, Reason + FuncName, CLI.DL.getDebugLoc());
   DAG.getContext()->diagnose(NoCalls);
 
   if (!CLI.IsTailCall) {
@@ -1027,6 +1028,11 @@ SDValue AMDGPUTargetLowering::LowerCall(CallLoweringInfo &CLI,
   return DAG.getEntryNode();
 }
 
+SDValue AMDGPUTargetLowering::LowerCall(CallLoweringInfo &CLI,
+                                        SmallVectorImpl<SDValue> &InVals) const {
+  return lowerUnhandledCall(CLI, InVals, "unsupported call to function ");
+}
+
 SDValue AMDGPUTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op,
                                                       SelectionDAG &DAG) const {
   const Function &Fn = *DAG.getMachineFunction().getFunction();
index 46c81f9..0a7d02e 100644 (file)
@@ -171,6 +171,10 @@ public:
                       const SmallVectorImpl<ISD::OutputArg> &Outs,
                       const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL,
                       SelectionDAG &DAG) const override;
+
+  SDValue lowerUnhandledCall(CallLoweringInfo &CLI,
+                             SmallVectorImpl<SDValue> &InVals,
+                             StringRef Reason) const;
   SDValue LowerCall(CallLoweringInfo &CLI,
                     SmallVectorImpl<SDValue> &InVals) const override;
 
index 68881ef..cec3abb 100644 (file)
@@ -1888,8 +1888,7 @@ void SITargetLowering::passSpecialInputs(
     return;
 
   const Function *CalleeFunc = CLI.CS.getCalledFunction();
-  if (!CalleeFunc)
-    report_fatal_error("indirect calls not handled");
+  assert(CalleeFunc);
 
   SelectionDAG &DAG = CLI.DAG;
   const SDLoc &DL = CLI.DL;
@@ -1976,13 +1975,24 @@ SDValue SITargetLowering::LowerCall(CallLoweringInfo &CLI,
   bool IsThisReturn = false;
   MachineFunction &MF = DAG.getMachineFunction();
 
-  // TODO: Implement tail calls.
-  IsTailCall = false;
+  if (IsVarArg) {
+    return lowerUnhandledCall(CLI, InVals,
+                              "unsupported call to variadic function ");
+  }
+
+  if (!CLI.CS.getCalledFunction()) {
+    return lowerUnhandledCall(CLI, InVals,
+                              "unsupported indirect call to function ");
+  }
 
-  if (IsVarArg || MF.getTarget().Options.GuaranteedTailCallOpt) {
-    report_fatal_error("varargs and tail calls not implemented");
+  if (IsTailCall && MF.getTarget().Options.GuaranteedTailCallOpt) {
+    return lowerUnhandledCall(CLI, InVals,
+                              "unsupported required tail call to function ");
   }
 
+  // TODO: Implement tail calls.
+  IsTailCall = false;
+
   if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Callee)) {
     // FIXME: Remove this hack for function pointer types.
     const GlobalValue *GV = GA->getGlobal();
diff --git a/llvm/test/CodeGen/AMDGPU/call.ll b/llvm/test/CodeGen/AMDGPU/call.ll
deleted file mode 100644 (file)
index 85c3792..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-; RUN: not llc -march=r600 -mcpu=cypress < %s 2>&1 | FileCheck %s
-
-; CHECK: in function test_call_external{{.*}}: unsupported call to function external_function
-; CHECK: in function test_call{{.*}}: unsupported call to function defined_function
-; CHECK: in function test_tail_call{{.*}}: unsupported call to function defined_function
-; CHECK: in function test_tail_call_bitcast_extern_variadic{{.*}}: unsupported call to function extern_variadic
-
-
-declare i32 @external_function(i32) nounwind
-
-define amdgpu_kernel void @test_call_external(i32 addrspace(1)* %out, i32 addrspace(1)* %in) {
-  %b_ptr = getelementptr i32, i32 addrspace(1)* %in, i32 1
-  %a = load i32, i32 addrspace(1)* %in
-  %b = load i32, i32 addrspace(1)* %b_ptr
-  %c = call i32 @external_function(i32 %b) nounwind
-  %result = add i32 %a, %c
-  store i32 %result, i32 addrspace(1)* %out
-  ret void
-}
-
-define i32 @defined_function(i32 %x) nounwind noinline {
-  %y = add i32 %x, 8
-  ret i32 %y
-}
-
-define amdgpu_kernel void @test_call(i32 addrspace(1)* %out, i32 addrspace(1)* %in) {
-  %b_ptr = getelementptr i32, i32 addrspace(1)* %in, i32 1
-  %a = load i32, i32 addrspace(1)* %in
-  %b = load i32, i32 addrspace(1)* %b_ptr
-  %c = call i32 @defined_function(i32 %b) nounwind
-  %result = add i32 %a, %c
-  store i32 %result, i32 addrspace(1)* %out
-  ret void
-}
-
-define amdgpu_kernel void @test_tail_call(i32 addrspace(1)* %out, i32 addrspace(1)* %in) {
-  %b_ptr = getelementptr i32, i32 addrspace(1)* %in, i32 1
-  %a = load i32, i32 addrspace(1)* %in
-  %b = load i32, i32 addrspace(1)* %b_ptr
-  %c = tail call i32 @defined_function(i32 %b) nounwind
-  %result = add i32 %a, %c
-  store i32 %result, i32 addrspace(1)* %out
-  ret void
-}
-
-define i32 @test_tail_call_ret() {
-  %call = call i32 @external_function(i32 10)
-  ret i32 %call
-}
-
-declare i32 @extern_variadic(...)
-
-define i32 @test_tail_call_bitcast_extern_variadic(<4 x float> %arg0, <4 x float> %arg1, i32 %arg2) {
-  %add = fadd <4 x float> %arg0, %arg1
-  %call = tail call i32 bitcast (i32 (...)* @extern_variadic to i32 (<4 x float>)*)(<4 x float> %add) #7
-  ret i32 %call
-}
index f880d21..b440efc 100644 (file)
@@ -1,6 +1,8 @@
 ; RUN: not llc -march=amdgcn < %s 2>&1 | FileCheck %s
 
-; CHECK: LLVM ERROR: indirect calls not handled
+; FIXME: Error is misleading because it's not an indirect call.
+
+; CHECK: error: <unknown>:0:0: in function crash_call_constexpr_cast void (): unsupported indirect call to function foo
 
 ; Make sure that AMDGPUPromoteAlloca doesn't crash if the called
 ; function is a constantexpr cast of a function.
diff --git a/llvm/test/CodeGen/AMDGPU/unsupported-calls.ll b/llvm/test/CodeGen/AMDGPU/unsupported-calls.ll
new file mode 100644 (file)
index 0000000..990b25e
--- /dev/null
@@ -0,0 +1,69 @@
+; RUN: not llc -march=amdgcn -tailcallopt < %s 2>&1 | FileCheck -check-prefix=GCN %s
+; RUN: not llc -march=r600 -mcpu=cypress -tailcallopt < %s 2>&1 | FileCheck -check-prefix=R600 %s
+
+declare i32 @external_function(i32) nounwind
+
+; GCN-NOT: error
+; R600: in function test_call_external{{.*}}: unsupported call to function external_function
+define amdgpu_kernel void @test_call_external(i32 addrspace(1)* %out, i32 addrspace(1)* %in) {
+  %b_ptr = getelementptr i32, i32 addrspace(1)* %in, i32 1
+  %a = load i32, i32 addrspace(1)* %in
+  %b = load i32, i32 addrspace(1)* %b_ptr
+  %c = call i32 @external_function(i32 %b) nounwind
+  %result = add i32 %a, %c
+  store i32 %result, i32 addrspace(1)* %out
+  ret void
+}
+
+define i32 @defined_function(i32 %x) nounwind noinline {
+  %y = add i32 %x, 8
+  ret i32 %y
+}
+
+; GCN-NOT: error
+; R600: in function test_call{{.*}}: unsupported call to function defined_function
+define amdgpu_kernel void @test_call(i32 addrspace(1)* %out, i32 addrspace(1)* %in) {
+  %b_ptr = getelementptr i32, i32 addrspace(1)* %in, i32 1
+  %a = load i32, i32 addrspace(1)* %in
+  %b = load i32, i32 addrspace(1)* %b_ptr
+  %c = call i32 @defined_function(i32 %b) nounwind
+  %result = add i32 %a, %c
+  store i32 %result, i32 addrspace(1)* %out
+  ret void
+}
+
+; GCN: error: <unknown>:0:0: in function test_tail_call i32 (i32 addrspace(1)*, i32 addrspace(1)*): unsupported required tail call to function defined_function
+; R600: in function test_tail_call{{.*}}: unsupported call to function defined_function
+define i32 @test_tail_call(i32 addrspace(1)* %out, i32 addrspace(1)* %in) {
+  %b_ptr = getelementptr i32, i32 addrspace(1)* %in, i32 1
+  %a = load i32, i32 addrspace(1)* %in
+  %b = load i32, i32 addrspace(1)* %b_ptr
+  %c = tail call i32 @defined_function(i32 %b)
+  ret i32 %c
+}
+
+declare void @external.varargs(i32, double, i64, ...)
+
+; GCN: error: <unknown>:0:0: in function test_call_varargs void (): unsupported call to variadic function external.varargs
+; R600: in function test_call_varargs{{.*}}: unsupported call to function external.varargs
+define void @test_call_varargs() {
+  call void (i32, double, i64, ...) @external.varargs(i32 42, double 1.0, i64 12, i8 3, i16 1, i32 4, float 1.0, double 2.0)
+  ret void
+}
+
+declare i32 @extern_variadic(...)
+
+; GCN: in function test_tail_call_bitcast_extern_variadic{{.*}}: unsupported indirect call to function extern_variadic
+; R600: in function test_tail_call_bitcast_extern_variadic{{.*}}: unsupported call to function extern_variadic
+define i32 @test_tail_call_bitcast_extern_variadic(<4 x float> %arg0, <4 x float> %arg1, i32 %arg2) {
+  %add = fadd <4 x float> %arg0, %arg1
+  %call = tail call i32 bitcast (i32 (...)* @extern_variadic to i32 (<4 x float>)*)(<4 x float> %add)
+  ret i32 %call
+}
+
+; GCN: :0:0: in function test_indirect_call void (void ()*): unsupported indirect call to function <unknown>
+; R600: in function test_indirect_call{{.*}}: unsupported call to function <unknown>
+define void @test_indirect_call(void()* %fptr) {
+  call void %fptr()
+  ret void
+}