[llvm] 7b922fc - AMDGPU: Fix broken and permissive handling of printf format strings

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 5 06:18:52 PST 2023


Author: Matt Arsenault
Date: 2023-01-05T09:18:00-05:00
New Revision: 7b922fc0c3f1e12a1e34508f50c1c52dad762916

URL: https://github.com/llvm/llvm-project/commit/7b922fc0c3f1e12a1e34508f50c1c52dad762916
DIFF: https://github.com/llvm/llvm-project/commit/7b922fc0c3f1e12a1e34508f50c1c52dad762916.diff

LOG: AMDGPU: Fix broken and permissive handling of printf format strings

This was completely broken with opaque pointers because it was
specifically looking for a constant expression with the global
variable as the first operand. Strip casts like normal, and properly
validate all of the restrictions rather than silently ignoring any
unhandled cases. Also be stricter that we aren't calling into some
unresolved or non-constant format string.

Also converts the test to opaque pointers and generated tests. There's
more broken initializer handling for strings inside the format string
processing too, but there's just no test coverage for this at all.

Added: 
    llvm/test/CodeGen/AMDGPU/opencl-printf-unsupported.ll

Modified: 
    llvm/lib/Target/AMDGPU/AMDGPUPrintfRuntimeBinding.cpp
    llvm/test/CodeGen/AMDGPU/opencl-printf.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/AMDGPU/AMDGPUPrintfRuntimeBinding.cpp b/llvm/lib/Target/AMDGPU/AMDGPUPrintfRuntimeBinding.cpp
index 92fd7bc87716..e5259e5b8586 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUPrintfRuntimeBinding.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUPrintfRuntimeBinding.cpp
@@ -22,6 +22,7 @@
 #include "llvm/ADT/Triple.h"
 #include "llvm/Analysis/InstructionSimplify.h"
 #include "llvm/Analysis/TargetLibraryInfo.h"
+#include "llvm/IR/DiagnosticInfo.h"
 #include "llvm/IR/Dominators.h"
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/Instructions.h"
@@ -145,6 +146,15 @@ bool AMDGPUPrintfRuntimeBindingImpl::shouldPrintAsStr(char Specifier,
   return ElemIType->getBitWidth() == 8;
 }
 
+static void diagnoseInvalidFormatString(const CallBase *CI) {
+  DiagnosticInfoUnsupported UnsupportedFormatStr(
+      *CI->getParent()->getParent(),
+      "printf format string must be a trivially resolved constant string "
+      "global variable",
+      CI->getDebugLoc());
+  CI->getContext().diagnose(UnsupportedFormatStr);
+}
+
 bool AMDGPUPrintfRuntimeBindingImpl::lowerPrintfForGpu(Module &M) {
   LLVMContext &Ctx = M.getContext();
   IRBuilder<> Builder(Ctx);
@@ -176,30 +186,32 @@ bool AMDGPUPrintfRuntimeBindingImpl::lowerPrintfForGpu(Module &M) {
         Op = Op_simplified;
     }
 
-    ConstantExpr *ConstExpr = dyn_cast<ConstantExpr>(Op);
-    if (!ConstExpr) {
+    Value *Stripped = Op->stripPointerCasts();
+    if (isa<UndefValue>(Stripped) || isa<ConstantPointerNull>(Stripped))
+      continue;
+
+    GlobalVariable *GVar = dyn_cast<GlobalVariable>(Stripped);
+    if (!GVar || !GVar->hasDefinitiveInitializer() || !GVar->isConstant()) {
+      diagnoseInvalidFormatString(CI);
       continue;
     }
 
-    GlobalVariable *GVar = dyn_cast<GlobalVariable>(ConstExpr->getOperand(0));
+    auto *Init = GVar->getInitializer();
+    if (isa<UndefValue>(Init) || isa<ConstantAggregateZero>(Init))
+      continue;
 
-    StringRef Str("unknown");
-    if (GVar && GVar->hasInitializer()) {
-      auto *Init = GVar->getInitializer();
-      if (auto *CA = dyn_cast<ConstantDataArray>(Init)) {
-        if (CA->isString())
-          Str = CA->getAsCString();
-      } else if (isa<ConstantAggregateZero>(Init)) {
-        Str = "";
-      }
-      //
-      // we need this call to ascertain
-      // that we are printing a string
-      // or a pointer. It takes out the
-      // specifiers and fills up the first
-      // arg
-      getConversionSpecifiers(OpConvSpecifiers, Str, NumOps - 1);
+    auto *CA = dyn_cast<ConstantDataArray>(Init);
+    if (!CA || !CA->isString()) {
+      diagnoseInvalidFormatString(CI);
+      continue;
     }
+
+    StringRef Str(CA->getAsCString());
+
+    // We need this call to ascertain that we are printing a string or a
+    // pointer. It takes out the specifiers and fills up the first arg.
+    getConversionSpecifiers(OpConvSpecifiers, Str, NumOps - 1);
+
     // Add metadata for the string
     std::string AStreamHolder;
     raw_string_ostream Sizes(AStreamHolder);

diff  --git a/llvm/test/CodeGen/AMDGPU/opencl-printf-unsupported.ll b/llvm/test/CodeGen/AMDGPU/opencl-printf-unsupported.ll
new file mode 100644
index 000000000000..805bf0decab1
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/opencl-printf-unsupported.ll
@@ -0,0 +1,90 @@
+; RUN: not llc -mtriple=amdgcn-- -mcpu=gfx900 -filetype=null %s 2>&1 | FileCheck --strict-whitespace %s
+
+; FIXME: Should be adequate to run just
+; -passes=amdgpu-printf-runtime-binding, but llc and opt have
+; 
diff erent behavior on error diagnostics. opt uses the default error
+; handler which immediately exits, and llc does not. We want to report
+; errors for all functions in the module.
+
+
+; CHECK: error: foo.cl:1:42: in function test_inttoptr_argument void (i32): printf format string must be a trivially resolved constant string global variable
+define amdgpu_kernel void @test_inttoptr_argument(i32 %n) {
+  %str = alloca [9 x i8], align 1, addrspace(5)
+  %call1 = call i32 (ptr addrspace(4), ...) @printf(ptr addrspace(4) inttoptr (i64 1234 to ptr addrspace(4)), ptr addrspace(5) %str, i32 %n), !dbg !4
+  ret void
+}
+
+; CHECK: error: foo.cl:1:42: in function test_formatstr_argument void (ptr addrspace(4), i32): printf format string must be a trivially resolved constant string global variable
+define amdgpu_kernel void @test_formatstr_argument(ptr addrspace(4) %format.str, i32 %n) {
+  %str = alloca [9 x i8], align 1, addrspace(5)
+  %call1 = call i32 (ptr addrspace(4), ...) @printf(ptr addrspace(4) %format.str, ptr addrspace(5) %str, i32 %n), !dbg !4
+  ret void
+}
+
+; CHECK: error: foo.cl:1:42: in function test_formatstr_instruction void (ptr addrspace(4), i32): printf format string must be a trivially resolved constant string global variable
+define amdgpu_kernel void @test_formatstr_instruction(ptr addrspace(4) %kernarg, i32 %n) {
+  %str = alloca [9 x i8], align 1, addrspace(5)
+  %format.str = load ptr addrspace(4), ptr addrspace(4) %kernarg
+  %call1 = call i32 (ptr addrspace(4), ...) @printf(ptr addrspace(4) %format.str, ptr addrspace(5) %str, i32 %n), !dbg !4
+  ret void
+}
+
+ at no.initializer = external hidden addrspace(4) constant [6 x i8]
+
+; CHECK: error: foo.cl:1:42: in function test_no_initializer_gv void (i32): printf format string must be a trivially resolved constant string global variable
+define amdgpu_kernel void @test_no_initializer_gv(i32 %n) {
+  %str = alloca [9 x i8], align 1, addrspace(5)
+  %call1 = call i32 (ptr addrspace(4), ...) @printf(ptr addrspace(4) @no.initializer, ptr addrspace(5) %str, i32 %n), !dbg !4
+  ret void
+}
+
+ at interposable.initializer = weak unnamed_addr addrspace(4) constant [6 x i8] c"%s:%d\00"
+
+; CHECK: error: foo.cl:1:42: in function poison_interposable_initializer_gv void (i32): printf format string must be a trivially resolved constant string global variable
+define amdgpu_kernel void @poison_interposable_initializer_gv(i32 %n) {
+  %str = alloca [9 x i8], align 1, addrspace(5)
+  %call1 = call i32 (ptr addrspace(4), ...) @printf(ptr addrspace(4) @interposable.initializer, ptr addrspace(5) %str, i32 %n), !dbg !4
+  ret void
+}
+
+ at not.constant = private unnamed_addr addrspace(4) global [6 x i8] c"%s:%d\00", align 1
+
+
+; CHECK: error: <unknown>:0:0: in function not_constant_gv void (i32): printf format string must be a trivially resolved constant string global variable
+define amdgpu_kernel void @not_constant_gv(i32 %n) {
+entry:
+  %str = alloca [9 x i8], align 1, addrspace(5)
+  %arraydecay = getelementptr inbounds [9 x i8], [9 x i8] addrspace(5)* %str, i32 0, i32 0
+  %call1 = call i32 (i8 addrspace(4)*, ...) @printf(i8 addrspace(4)* getelementptr inbounds ([6 x i8], [6 x i8] addrspace(4)* @not.constant, i32 0, i32 0), i8 addrspace(5)* %arraydecay, i32 %n)
+  ret void
+}
+
+ at struct = private unnamed_addr addrspace(4) constant { [6 x i8] } { [6 x i8] [i8 1, i8 2, i8 3, i8 4, i8 5, i8 6] }
+
+; CHECK: error: <unknown>:0:0: in function test_format_struct void (i32): printf format string must be a trivially resolved constant string global variable
+define amdgpu_kernel void @test_format_struct(i32 %n) {
+  %str = alloca [9 x i8], align 1, addrspace(5)
+  %call1 = call i32 (ptr addrspace(4), ...) @printf(ptr addrspace(4) @struct, ptr addrspace(5) %str, i32 %n)
+  ret void
+}
+
+ at array.i16 = private unnamed_addr addrspace(4) constant [6 x i16] [i16 1, i16 2, i16 3, i16 4, i16 5, i16 6]
+
+; CHECK: error: <unknown>:0:0: in function test_format_array_i16 void (i32): printf format string must be a trivially resolved constant string global variable
+define amdgpu_kernel void @test_format_array_i16(i32 %n) {
+  %str = alloca [9 x i8], align 1, addrspace(5)
+  %call1 = call i32 (ptr addrspace(4), ...) @printf(ptr addrspace(4) @array.i16, ptr addrspace(5) %str, i32 %n)
+  ret void
+}
+
+declare i32 @printf(ptr addrspace(4), ...)
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_OpenCL, file: !1, isOptimized: false, runtimeVersion: 0, emissionKind: NoDebug)
+!1 = !DIFile(filename: "foo.cl", directory: ".")
+!2 = !{i32 2, !"Dwarf Version", i32 4}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !DILocation(line: 1, column: 42, scope: !5)
+!5 = distinct !DISubprogram(name: "arst", scope: null, file: !1, line: 1, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: false, unit: !0)

diff  --git a/llvm/test/CodeGen/AMDGPU/opencl-printf.ll b/llvm/test/CodeGen/AMDGPU/opencl-printf.ll
index f9c23be1296a..be5b25aaa5d2 100644
--- a/llvm/test/CodeGen/AMDGPU/opencl-printf.ll
+++ b/llvm/test/CodeGen/AMDGPU/opencl-printf.ll
@@ -1,35 +1,181 @@
-; RUN: opt -mtriple=r600-- -passes=amdgpu-printf-runtime-binding -mcpu=r600 -S < %s | FileCheck --check-prefix=FUNC --check-prefix=R600 %s
-; RUN: opt -mtriple=amdgcn-- -passes=amdgpu-printf-runtime-binding -mcpu=fiji -S < %s | FileCheck --check-prefix=FUNC --check-prefix=GCN %s
-; RUN: opt -mtriple=amdgcn--amdhsa -passes=amdgpu-printf-runtime-binding -mcpu=fiji -S < %s | FileCheck --check-prefix=FUNC --check-prefix=GCN %s
-; RUN: opt -mtriple=amdgcn--amdhsa -passes=amdgpu-printf-runtime-binding -mcpu=fiji -S < %s | FileCheck --check-prefix=FUNC --check-prefix=GCN %s
-
-; FUNC-LABEL: @test_kernel(
-; R600-LABEL: entry
-; R600-NOT: call i8 addrspace(1)* @__printf_alloc
-; R600: call i32 (i8 addrspace(4)*, ...) @printf(i8 addrspace(4)* getelementptr inbounds ([6 x i8], [6 x i8] addrspace(4)* @.str, i32 0, i32 0), i8 addrspace(5)* %arraydecay, i32 %n)
-; GCN-LABEL: entry
-; GCN: call i8 addrspace(1)* @__printf_alloc
-; GCN-LABEL: entry.split
-; GCN: icmp ne i8 addrspace(1)* %printf_alloc_fn, null
-; GCN: %PrintBuffID = getelementptr i8, i8 addrspace(1)* %printf_alloc_fn, i32 0
-; GCN: %PrintBuffIdCast = bitcast i8 addrspace(1)* %PrintBuffID to i32 addrspace(1)*
-; GCN: store i32 1, i32 addrspace(1)* %PrintBuffIdCast
-; GCN: %PrintBuffGep = getelementptr i8, i8 addrspace(1)* %printf_alloc_fn, i32 4
-; GCN: %PrintArgPtr = ptrtoint i8 addrspace(5)* %arraydecay to i64
-; GCN: %PrintBuffPtrCast = bitcast i8 addrspace(1)* %PrintBuffGep to i64 addrspace(1)*
-; GCN: store i64 %PrintArgPtr, i64 addrspace(1)* %PrintBuffPtrCast
-; GCN: %PrintBuffNextPtr = getelementptr i8, i8 addrspace(1)* %PrintBuffGep, i32 8
-; GCN: %PrintBuffPtrCast1 = bitcast i8 addrspace(1)* %PrintBuffNextPtr to i32 addrspace(1)*
-; GCN: store i32 %n, i32 addrspace(1)* %PrintBuffPtrCast1
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -mtriple=r600-- -passes=amdgpu-printf-runtime-binding -mcpu=r600 -S < %s | FileCheck --check-prefix=R600 %s
+; RUN: opt -mtriple=amdgcn-- -passes=amdgpu-printf-runtime-binding -mcpu=fiji -S < %s | FileCheck --check-prefix=GCN %s
+; RUN: opt -mtriple=amdgcn--amdhsa -passes=amdgpu-printf-runtime-binding -mcpu=fiji -S < %s | FileCheck --check-prefix=GCN %s
 
 @.str = private unnamed_addr addrspace(4) constant [6 x i8] c"%s:%d\00", align 1
 
 define amdgpu_kernel void @test_kernel(i32 %n) {
+; R600-LABEL: @test_kernel(
+; R600-NEXT:  entry:
+; R600-NEXT:    [[STR:%.*]] = alloca [9 x i8], align 1, addrspace(5)
+; R600-NEXT:    [[CALL1:%.*]] = call i32 (ptr addrspace(4), ...) @printf(ptr addrspace(4) @.str, ptr addrspace(5) [[STR]], i32 [[N:%.*]])
+; R600-NEXT:    ret void
+;
+; GCN-LABEL: @test_kernel(
+; GCN-NEXT:  entry:
+; GCN-NEXT:    [[STR:%.*]] = alloca [9 x i8], align 1, addrspace(5)
+; GCN-NEXT:    [[PRINTF_ALLOC_FN:%.*]] = call ptr addrspace(1) @__printf_alloc(i32 16)
+; GCN-NEXT:    br label [[ENTRY_SPLIT:%.*]]
+; GCN:       entry.split:
+; GCN-NEXT:    [[TMP0:%.*]] = icmp ne ptr addrspace(1) [[PRINTF_ALLOC_FN]], null
+; GCN-NEXT:    br i1 [[TMP0]], label [[TMP1:%.*]], label [[TMP2:%.*]]
+; GCN:       1:
+; GCN-NEXT:    [[PRINTBUFFID:%.*]] = getelementptr i8, ptr addrspace(1) [[PRINTF_ALLOC_FN]], i32 0
+; GCN-NEXT:    [[PRINTBUFFIDCAST:%.*]] = bitcast ptr addrspace(1) [[PRINTBUFFID]] to ptr addrspace(1)
+; GCN-NEXT:    store i32 1, ptr addrspace(1) [[PRINTBUFFIDCAST]], align 4
+; GCN-NEXT:    [[PRINTBUFFGEP:%.*]] = getelementptr i8, ptr addrspace(1) [[PRINTF_ALLOC_FN]], i32 4
+; GCN-NEXT:    [[PRINTARGPTR:%.*]] = ptrtoint ptr addrspace(5) [[STR]] to i64
+; GCN-NEXT:    [[PRINTBUFFPTRCAST:%.*]] = bitcast ptr addrspace(1) [[PRINTBUFFGEP]] to ptr addrspace(1)
+; GCN-NEXT:    store i64 [[PRINTARGPTR]], ptr addrspace(1) [[PRINTBUFFPTRCAST]], align 4
+; GCN-NEXT:    [[PRINTBUFFNEXTPTR:%.*]] = getelementptr i8, ptr addrspace(1) [[PRINTBUFFGEP]], i32 8
+; GCN-NEXT:    [[PRINTBUFFPTRCAST1:%.*]] = bitcast ptr addrspace(1) [[PRINTBUFFNEXTPTR]] to ptr addrspace(1)
+; GCN-NEXT:    store i32 [[N:%.*]], ptr addrspace(1) [[PRINTBUFFPTRCAST1]], align 4
+; GCN-NEXT:    br label [[TMP2]]
+; GCN:       2:
+; GCN-NEXT:    ret void
+;
+entry:
+  %str = alloca [9 x i8], align 1, addrspace(5)
+  %call1 = call i32 (ptr addrspace(4), ...) @printf(ptr addrspace(4) @.str, ptr addrspace(5) %str, i32 %n)
+  ret void
+}
+
+ at str.as1 = private unnamed_addr addrspace(1) constant [6 x i8] c"%s:%d\00", align 1
+
+define amdgpu_kernel void @test_kernel_addrspacecasted_format_str(i32 %n) {
+; R600-LABEL: @test_kernel_addrspacecasted_format_str(
+; R600-NEXT:  entry:
+; R600-NEXT:    [[STR:%.*]] = alloca [9 x i8], align 1, addrspace(5)
+; R600-NEXT:    [[ARRAYDECAY:%.*]] = getelementptr inbounds [9 x i8], ptr addrspace(5) [[STR]], i32 0, i32 0
+; R600-NEXT:    [[CALL1:%.*]] = call i32 (ptr addrspace(4), ...) @printf(ptr addrspace(4) addrspacecast (ptr addrspace(1) @str.as1 to ptr addrspace(4)), ptr addrspace(5) [[ARRAYDECAY]], i32 [[N:%.*]])
+; R600-NEXT:    ret void
+;
+; GCN-LABEL: @test_kernel_addrspacecasted_format_str(
+; GCN-NEXT:  entry:
+; GCN-NEXT:    [[STR:%.*]] = alloca [9 x i8], align 1, addrspace(5)
+; GCN-NEXT:    [[ARRAYDECAY:%.*]] = getelementptr inbounds [9 x i8], ptr addrspace(5) [[STR]], i32 0, i32 0
+; GCN-NEXT:    [[PRINTF_ALLOC_FN:%.*]] = call ptr addrspace(1) @__printf_alloc(i32 16)
+; GCN-NEXT:    br label [[ENTRY_SPLIT:%.*]]
+; GCN:       entry.split:
+; GCN-NEXT:    [[TMP0:%.*]] = icmp ne ptr addrspace(1) [[PRINTF_ALLOC_FN]], null
+; GCN-NEXT:    br i1 [[TMP0]], label [[TMP1:%.*]], label [[TMP2:%.*]]
+; GCN:       1:
+; GCN-NEXT:    [[PRINTBUFFID:%.*]] = getelementptr i8, ptr addrspace(1) [[PRINTF_ALLOC_FN]], i32 0
+; GCN-NEXT:    [[PRINTBUFFIDCAST:%.*]] = bitcast ptr addrspace(1) [[PRINTBUFFID]] to ptr addrspace(1)
+; GCN-NEXT:    store i32 2, ptr addrspace(1) [[PRINTBUFFIDCAST]], align 4
+; GCN-NEXT:    [[PRINTBUFFGEP:%.*]] = getelementptr i8, ptr addrspace(1) [[PRINTF_ALLOC_FN]], i32 4
+; GCN-NEXT:    [[PRINTARGPTR:%.*]] = ptrtoint ptr addrspace(5) [[ARRAYDECAY]] to i64
+; GCN-NEXT:    [[PRINTBUFFPTRCAST:%.*]] = bitcast ptr addrspace(1) [[PRINTBUFFGEP]] to ptr addrspace(1)
+; GCN-NEXT:    store i64 [[PRINTARGPTR]], ptr addrspace(1) [[PRINTBUFFPTRCAST]], align 4
+; GCN-NEXT:    [[PRINTBUFFNEXTPTR:%.*]] = getelementptr i8, ptr addrspace(1) [[PRINTBUFFGEP]], i32 8
+; GCN-NEXT:    [[PRINTBUFFPTRCAST1:%.*]] = bitcast ptr addrspace(1) [[PRINTBUFFNEXTPTR]] to ptr addrspace(1)
+; GCN-NEXT:    store i32 [[N:%.*]], ptr addrspace(1) [[PRINTBUFFPTRCAST1]], align 4
+; GCN-NEXT:    br label [[TMP2]]
+; GCN:       2:
+; GCN-NEXT:    ret void
+;
 entry:
   %str = alloca [9 x i8], align 1, addrspace(5)
   %arraydecay = getelementptr inbounds [9 x i8], [9 x i8] addrspace(5)* %str, i32 0, i32 0
-  %call1 = call i32 (i8 addrspace(4)*, ...) @printf(i8 addrspace(4)* getelementptr inbounds ([6 x i8], [6 x i8] addrspace(4)* @.str, i32 0, i32 0), i8 addrspace(5)* %arraydecay, i32 %n)
+  %call1 = call i32 (ptr addrspace(4), ...) @printf(ptr addrspace(4) addrspacecast (i8 addrspace(1)* getelementptr inbounds ([6 x i8], ptr addrspace(1) @str.as1, i32 0, i32 0) to ptr addrspace(4)), ptr addrspace(5) %arraydecay, i32 %n)
+  ret void
+}
+
+define amdgpu_kernel void @test_undef_argument(i32 %n) {
+; R600-LABEL: @test_undef_argument(
+; R600-NEXT:    [[STR:%.*]] = alloca [9 x i8], align 1, addrspace(5)
+; R600-NEXT:    [[CALL1:%.*]] = call i32 (ptr addrspace(4), ...) @printf(ptr addrspace(4) undef, ptr addrspace(5) [[STR]], i32 [[N:%.*]])
+; R600-NEXT:    ret void
+;
+; GCN-LABEL: @test_undef_argument(
+; GCN-NEXT:    [[STR:%.*]] = alloca [9 x i8], align 1, addrspace(5)
+; GCN-NEXT:    ret void
+;
+  %str = alloca [9 x i8], align 1, addrspace(5)
+  %call1 = call i32 (ptr addrspace(4), ...) @printf(ptr addrspace(4) undef, ptr addrspace(5) %str, i32 %n)
+  ret void
+}
+
+define amdgpu_kernel void @test_poison_argument(i32 %n) {
+; R600-LABEL: @test_poison_argument(
+; R600-NEXT:    [[STR:%.*]] = alloca [9 x i8], align 1, addrspace(5)
+; R600-NEXT:    [[CALL1:%.*]] = call i32 (ptr addrspace(4), ...) @printf(ptr addrspace(4) poison, ptr addrspace(5) [[STR]], i32 [[N:%.*]])
+; R600-NEXT:    ret void
+;
+; GCN-LABEL: @test_poison_argument(
+; GCN-NEXT:    [[STR:%.*]] = alloca [9 x i8], align 1, addrspace(5)
+; GCN-NEXT:    ret void
+;
+  %str = alloca [9 x i8], align 1, addrspace(5)
+  %call1 = call i32 (ptr addrspace(4), ...) @printf(ptr addrspace(4) poison, ptr addrspace(5) %str, i32 %n)
+  ret void
+}
+
+define amdgpu_kernel void @test_null_argument(i32 %n) {
+; R600-LABEL: @test_null_argument(
+; R600-NEXT:    [[STR:%.*]] = alloca [9 x i8], align 1, addrspace(5)
+; R600-NEXT:    [[CALL1:%.*]] = call i32 (ptr addrspace(4), ...) @printf(ptr addrspace(4) null, ptr addrspace(5) [[STR]], i32 [[N:%.*]])
+; R600-NEXT:    ret void
+;
+; GCN-LABEL: @test_null_argument(
+; GCN-NEXT:    [[STR:%.*]] = alloca [9 x i8], align 1, addrspace(5)
+; GCN-NEXT:    ret void
+;
+  %str = alloca [9 x i8], align 1, addrspace(5)
+  %call1 = call i32 (ptr addrspace(4), ...) @printf(ptr addrspace(4) null, ptr addrspace(5) %str, i32 %n)
+  ret void
+}
+
+ at undef.initializer = private unnamed_addr addrspace(4) constant [6 x i8] undef
+
+define amdgpu_kernel void @undef_initializer_gv(i32 %n) {
+; R600-LABEL: @undef_initializer_gv(
+; R600-NEXT:    [[STR:%.*]] = alloca [9 x i8], align 1, addrspace(5)
+; R600-NEXT:    [[CALL1:%.*]] = call i32 (ptr addrspace(4), ...) @printf(ptr addrspace(4) @poison.initializer, ptr addrspace(5) [[STR]], i32 [[N:%.*]])
+; R600-NEXT:    ret void
+;
+; GCN-LABEL: @undef_initializer_gv(
+; GCN-NEXT:    [[STR:%.*]] = alloca [9 x i8], align 1, addrspace(5)
+; GCN-NEXT:    ret void
+;
+  %str = alloca [9 x i8], align 1, addrspace(5)
+  %call1 = call i32 (ptr addrspace(4), ...) @printf(ptr addrspace(4) @poison.initializer, ptr addrspace(5) %str, i32 %n)
+  ret void
+}
+
+ at poison.initializer = private unnamed_addr addrspace(4) constant [6 x i8] poison
+
+define amdgpu_kernel void @poison_initializer_gv(i32 %n) {
+; R600-LABEL: @poison_initializer_gv(
+; R600-NEXT:    [[STR:%.*]] = alloca [9 x i8], align 1, addrspace(5)
+; R600-NEXT:    [[CALL1:%.*]] = call i32 (ptr addrspace(4), ...) @printf(ptr addrspace(4) @poison.initializer, ptr addrspace(5) [[STR]], i32 [[N:%.*]])
+; R600-NEXT:    ret void
+;
+; GCN-LABEL: @poison_initializer_gv(
+; GCN-NEXT:    [[STR:%.*]] = alloca [9 x i8], align 1, addrspace(5)
+; GCN-NEXT:    ret void
+;
+  %str = alloca [9 x i8], align 1, addrspace(5)
+  %call1 = call i32 (ptr addrspace(4), ...) @printf(ptr addrspace(4) @poison.initializer, ptr addrspace(5) %str, i32 %n)
+  ret void
+}
+
+ at zero.initializer = private unnamed_addr addrspace(4) constant [6 x i8] zeroinitializer
+
+define amdgpu_kernel void @zero_initializer_gv(i32 %n) {
+; R600-LABEL: @zero_initializer_gv(
+; R600-NEXT:    [[STR:%.*]] = alloca [9 x i8], align 1, addrspace(5)
+; R600-NEXT:    [[CALL1:%.*]] = call i32 (ptr addrspace(4), ...) @printf(ptr addrspace(4) @poison.initializer, ptr addrspace(5) [[STR]], i32 [[N:%.*]])
+; R600-NEXT:    ret void
+;
+; GCN-LABEL: @zero_initializer_gv(
+; GCN-NEXT:    [[STR:%.*]] = alloca [9 x i8], align 1, addrspace(5)
+; GCN-NEXT:    ret void
+;
+  %str = alloca [9 x i8], align 1, addrspace(5)
+  %call1 = call i32 (ptr addrspace(4), ...) @printf(ptr addrspace(4) @poison.initializer, ptr addrspace(5) %str, i32 %n)
   ret void
 }
 
-declare i32 @printf(i8 addrspace(4)*, ...)
+declare i32 @printf(ptr addrspace(4), ...)


        


More information about the llvm-commits mailing list