#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"
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);
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);
--- /dev/null
+; 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
+; different 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
+}
+
+@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
+}
+
+@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
+}
+
+@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
+}
+
+@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
+}
+
+@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)
-; 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
+}
+
+@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
+}
+
+@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
+}
+
+@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
+}
+
+@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), ...)