Skip to content

Commit 0808fab

Browse files
committed
[CIR][CodeGen] String literals for OpenCL
1 parent f429d5c commit 0808fab

File tree

6 files changed

+117
-29
lines changed

6 files changed

+117
-29
lines changed

clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -398,14 +398,18 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
398398
return createAlloca(loc, addrType, type, name, alignmentIntAttr);
399399
}
400400

401-
mlir::Value createGetGlobal(mlir::cir::GlobalOp global,
401+
mlir::Value createGetGlobal(mlir::Location loc, mlir::cir::GlobalOp global,
402402
bool threadLocal = false) {
403403
return create<mlir::cir::GetGlobalOp>(
404-
global.getLoc(),
405-
getPointerTo(global.getSymType(), global.getAddrSpaceAttr()),
404+
loc, getPointerTo(global.getSymType(), global.getAddrSpaceAttr()),
406405
global.getName(), threadLocal);
407406
}
408407

408+
mlir::Value createGetGlobal(mlir::cir::GlobalOp global,
409+
bool threadLocal = false) {
410+
return createGetGlobal(global.getLoc(), global, threadLocal);
411+
}
412+
409413
/// Create a copy with inferred length.
410414
mlir::cir::CopyOp createCopy(mlir::Value dst, mlir::Value src,
411415
bool isVolatile = false) {

clang/lib/CIR/CodeGen/CIRGenExpr.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1849,12 +1849,9 @@ LValue CIRGenFunction::buildStringLiteralLValue(const StringLiteral *E) {
18491849
auto g = dyn_cast<mlir::cir::GlobalOp>(cstGlobal);
18501850
assert(g && "unaware of other symbol providers");
18511851

1852-
auto ptrTy = mlir::cir::PointerType::get(CGM.getBuilder().getContext(),
1853-
g.getSymType());
18541852
assert(g.getAlignment() && "expected alignment for string literal");
18551853
auto align = *g.getAlignment();
1856-
auto addr = builder.create<mlir::cir::GetGlobalOp>(
1857-
getLoc(E->getSourceRange()), ptrTy, g.getSymName());
1854+
auto addr = builder.createGetGlobal(getLoc(E->getSourceRange()), g);
18581855
return makeAddrLValue(
18591856
Address(addr, g.getSymType(), CharUnits::fromQuantity(align)),
18601857
E->getType(), AlignmentSource::Decl);

clang/lib/CIR/CodeGen/CIRGenModule.cpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1490,15 +1490,14 @@ static mlir::cir::GlobalOp
14901490
generateStringLiteral(mlir::Location loc, mlir::TypedAttr C,
14911491
mlir::cir::GlobalLinkageKind LT, CIRGenModule &CGM,
14921492
StringRef GlobalName, CharUnits Alignment) {
1493-
unsigned AddrSpace = CGM.getASTContext().getTargetAddressSpace(
1494-
CGM.getGlobalConstantAddressSpace());
1495-
assert((AddrSpace == 0 && !cir::MissingFeatures::addressSpaceInGlobalVar()) &&
1496-
"NYI");
1493+
mlir::cir::AddressSpaceAttr addrSpaceAttr =
1494+
CGM.getBuilder().getAddrSpaceAttr(CGM.getGlobalConstantAddressSpace());
14971495

14981496
// Create a global variable for this string
14991497
// FIXME(cir): check for insertion point in module level.
15001498
auto GV = CIRGenModule::createGlobalOp(CGM, loc, GlobalName, C.getType(),
1501-
!CGM.getLangOpts().WritableStrings);
1499+
!CGM.getLangOpts().WritableStrings,
1500+
addrSpaceAttr);
15021501

15031502
// Set up extra information and add to the module
15041503
GV.setAlignmentAttr(CGM.getSize(Alignment));
@@ -1570,7 +1569,7 @@ CIRGenModule::getAddrOfConstantStringFromLiteral(const StringLiteral *S,
15701569
auto ArrayTy = mlir::dyn_cast<mlir::cir::ArrayType>(GV.getSymType());
15711570
assert(ArrayTy && "String literal must be array");
15721571
auto PtrTy =
1573-
mlir::cir::PointerType::get(&getMLIRContext(), ArrayTy.getEltType());
1572+
getBuilder().getPointerTo(ArrayTy.getEltType(), GV.getAddrSpaceAttr());
15741573

15751574
return builder.getGlobalViewAttr(PtrTy, GV);
15761575
}

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,19 @@ void lowerAnnotationValue(
348348
}
349349
}
350350

351+
// Get addrspace by converting a pointer type.
352+
// TODO: The approach here is a little hacky. We should access the target info
353+
// directly to convert the address space of global op, similar to what we do
354+
// for type converter.
355+
unsigned getGlobalOpTargetAddrSpace(mlir::ConversionPatternRewriter &rewriter,
356+
const mlir::TypeConverter *converter,
357+
mlir::cir::GlobalOp op) {
358+
auto tempPtrTy = mlir::cir::PointerType::get(
359+
rewriter.getContext(), op.getSymType(), op.getAddrSpaceAttr());
360+
return cast<mlir::LLVM::LLVMPointerType>(converter->convertType(tempPtrTy))
361+
.getAddressSpace();
362+
}
363+
351364
} // namespace
352365

353366
//===----------------------------------------------------------------------===//
@@ -571,28 +584,36 @@ mlir::Value lowerCirAttrAsValue(mlir::Operation *parentOp,
571584
const mlir::TypeConverter *converter) {
572585
auto module = parentOp->getParentOfType<mlir::ModuleOp>();
573586
mlir::Type sourceType;
587+
unsigned sourceAddrSpace = 0;
574588
llvm::StringRef symName;
575589
auto *sourceSymbol =
576590
mlir::SymbolTable::lookupSymbolIn(module, globalAttr.getSymbol());
577591
if (auto llvmSymbol = dyn_cast<mlir::LLVM::GlobalOp>(sourceSymbol)) {
578592
sourceType = llvmSymbol.getType();
579593
symName = llvmSymbol.getSymName();
594+
sourceAddrSpace = llvmSymbol.getAddrSpace();
580595
} else if (auto cirSymbol = dyn_cast<mlir::cir::GlobalOp>(sourceSymbol)) {
581596
sourceType = converter->convertType(cirSymbol.getSymType());
582597
symName = cirSymbol.getSymName();
598+
sourceAddrSpace =
599+
getGlobalOpTargetAddrSpace(rewriter, converter, cirSymbol);
583600
} else if (auto llvmFun = dyn_cast<mlir::LLVM::LLVMFuncOp>(sourceSymbol)) {
584601
sourceType = llvmFun.getFunctionType();
585602
symName = llvmFun.getSymName();
603+
sourceAddrSpace = 0;
586604
} else if (auto fun = dyn_cast<mlir::cir::FuncOp>(sourceSymbol)) {
587605
sourceType = converter->convertType(fun.getFunctionType());
588606
symName = fun.getSymName();
607+
sourceAddrSpace = 0;
589608
} else {
590609
llvm_unreachable("Unexpected GlobalOp type");
591610
}
592611

593612
auto loc = parentOp->getLoc();
594613
mlir::Value addrOp = rewriter.create<mlir::LLVM::AddressOfOp>(
595-
loc, mlir::LLVM::LLVMPointerType::get(rewriter.getContext()), symName);
614+
loc,
615+
mlir::LLVM::LLVMPointerType::get(rewriter.getContext(), sourceAddrSpace),
616+
symName);
596617

597618
if (globalAttr.getIndices()) {
598619
llvm::SmallVector<mlir::LLVM::GEPArg> indices;
@@ -2349,18 +2370,6 @@ class CIRGlobalOpLowering
23492370
public:
23502371
using OpConversionPattern<mlir::cir::GlobalOp>::OpConversionPattern;
23512372

2352-
// Get addrspace by converting a pointer type.
2353-
// TODO: The approach here is a little hacky. We should access the target info
2354-
// directly to convert the address space of global op, similar to what we do
2355-
// for type converter.
2356-
unsigned getGlobalOpTargetAddrSpace(mlir::cir::GlobalOp op) const {
2357-
auto tempPtrTy = mlir::cir::PointerType::get(getContext(), op.getSymType(),
2358-
op.getAddrSpaceAttr());
2359-
return cast<mlir::LLVM::LLVMPointerType>(
2360-
typeConverter->convertType(tempPtrTy))
2361-
.getAddressSpace();
2362-
}
2363-
23642373
/// Replace CIR global with a region initialized LLVM global and update
23652374
/// insertion point to the end of the initializer block.
23662375
inline void setupRegionInitializedLLVMGlobalOp(
@@ -2371,7 +2380,7 @@ class CIRGlobalOpLowering
23712380
op, llvmType, op.getConstant(), convertLinkage(op.getLinkage()),
23722381
op.getSymName(), nullptr,
23732382
/*alignment*/ op.getAlignment().value_or(0),
2374-
/*addrSpace*/ getGlobalOpTargetAddrSpace(op),
2383+
/*addrSpace*/ getGlobalOpTargetAddrSpace(rewriter, typeConverter, op),
23752384
/*dsoLocal*/ false, /*threadLocal*/ (bool)op.getTlsModelAttr(),
23762385
/*comdat*/ mlir::SymbolRefAttr(), attributes);
23772386
newGlobalOp.getRegion().push_back(new mlir::Block());
@@ -2406,7 +2415,8 @@ class CIRGlobalOpLowering
24062415
if (!init.has_value()) {
24072416
rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
24082417
op, llvmType, isConst, linkage, symbol, mlir::Attribute(),
2409-
/*alignment*/ 0, /*addrSpace*/ getGlobalOpTargetAddrSpace(op),
2418+
/*alignment*/ 0,
2419+
/*addrSpace*/ getGlobalOpTargetAddrSpace(rewriter, typeConverter, op),
24102420
/*dsoLocal*/ isDsoLocal, /*threadLocal*/ (bool)op.getTlsModelAttr(),
24112421
/*comdat*/ mlir::SymbolRefAttr(), attributes);
24122422
return mlir::success();
@@ -2498,7 +2508,7 @@ class CIRGlobalOpLowering
24982508
auto llvmGlobalOp = rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
24992509
op, llvmType, isConst, linkage, symbol, init.value(),
25002510
/*alignment*/ op.getAlignment().value_or(0),
2501-
/*addrSpace*/ getGlobalOpTargetAddrSpace(op),
2511+
/*addrSpace*/ getGlobalOpTargetAddrSpace(rewriter, typeConverter, op),
25022512
/*dsoLocal*/ false, /*threadLocal*/ (bool)op.getTlsModelAttr(),
25032513
/*comdat*/ mlir::SymbolRefAttr(), attributes);
25042514

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// RUN: %clang_cc1 -fclangir -no-enable-noundef-analysis -cl-std=CL1.2 -cl-ext=-+cl_khr_fp64 -triple spirv64-unknown-unknown -disable-llvm-passes -emit-cir -fno-clangir-call-conv-lowering -o %t.12fp64.cir %s
2+
// RUN: FileCheck -input-file=%t.12fp64.cir -check-prefixes=CIR-FP64,CIR-ALL %s
3+
// RUN: %clang_cc1 -fclangir -no-enable-noundef-analysis -cl-std=CL1.2 -cl-ext=-cl_khr_fp64 -triple spirv64-unknown-unknown -disable-llvm-passes -emit-cir -fno-clangir-call-conv-lowering -o %t.12nofp64.cir %s
4+
// RUN: FileCheck -input-file=%t.12nofp64.cir -check-prefixes=CIR-NOFP64,CIR-ALL %s
5+
// RUN: %clang_cc1 -fclangir -no-enable-noundef-analysis -cl-std=CL3.0 -cl-ext=+__opencl_c_fp64,+cl_khr_fp64 -triple spirv64-unknown-unknown -disable-llvm-passes -emit-cir -fno-clangir-call-conv-lowering -o %t.30fp64.cir %s
6+
// RUN: FileCheck -input-file=%t.30fp64.cir -check-prefixes=CIR-FP64,CIR-ALL %s
7+
// RUN: %clang_cc1 -fclangir -no-enable-noundef-analysis -cl-std=CL3.0 -cl-ext=-__opencl_c_fp64,-cl_khr_fp64 -triple spirv64-unknown-unknown -disable-llvm-passes -emit-cir -fno-clangir-call-conv-lowering -o %t.30nofp64.cir %s
8+
// RUN: FileCheck -input-file=%t.30nofp64.cir -check-prefixes=CIR-NOFP64,CIR-ALL %s
9+
// RUN: %clang_cc1 -fclangir -no-enable-noundef-analysis -cl-std=CL1.2 -cl-ext=-+cl_khr_fp64 -triple spirv64-unknown-unknown -disable-llvm-passes -emit-llvm -fno-clangir-call-conv-lowering -o %t.12fp64.ll %s
10+
// RUN: FileCheck -input-file=%t.12fp64.ll -check-prefixes=LLVM-FP64,LLVM-ALL %s
11+
// RUN: %clang_cc1 -fclangir -no-enable-noundef-analysis -cl-std=CL1.2 -cl-ext=-cl_khr_fp64 -triple spirv64-unknown-unknown -disable-llvm-passes -emit-llvm -fno-clangir-call-conv-lowering -o %t.12nofp64.ll %s
12+
// RUN: FileCheck -input-file=%t.12nofp64.ll -check-prefixes=LLVM-NOFP64,LLVM-ALL %s
13+
// RUN: %clang_cc1 -fclangir -no-enable-noundef-analysis -cl-std=CL3.0 -cl-ext=+__opencl_c_fp64,+cl_khr_fp64 -triple spirv64-unknown-unknown -disable-llvm-passes -emit-llvm -fno-clangir-call-conv-lowering -o %t.30fp64.ll %s
14+
// RUN: FileCheck -input-file=%t.30fp64.ll -check-prefixes=LLVM-FP64,LLVM-ALL %s
15+
// RUN: %clang_cc1 -fclangir -no-enable-noundef-analysis -cl-std=CL3.0 -cl-ext=-__opencl_c_fp64,-cl_khr_fp64 -triple spirv64-unknown-unknown -disable-llvm-passes -emit-llvm -fno-clangir-call-conv-lowering -o %t.30nofp64.ll %s
16+
// RUN: FileCheck -input-file=%t.30nofp64.ll -check-prefixes=LLVM-NOFP64,LLVM-ALL %s
17+
18+
typedef __attribute__((ext_vector_type(2))) float float2;
19+
typedef __attribute__((ext_vector_type(2))) half half2;
20+
21+
#if defined(cl_khr_fp64) || defined(__opencl_c_fp64)
22+
typedef __attribute__((ext_vector_type(2))) double double2;
23+
#endif
24+
25+
int printf(__constant const char* st, ...) __attribute__((format(printf, 1, 2)));
26+
27+
kernel void test_printf_float2(float2 arg) {
28+
printf("%v2hlf", arg);
29+
}
30+
// CIR-ALL-LABEL: @test_printf_float2(
31+
// CIR-FP64: %{{.+}} = cir.call @printf(%{{.+}}, %{{.+}}) : (!cir.ptr<!s8i, addrspace(offload_constant)>, !cir.vector<!cir.float x 2>) -> !s32i cc(spir_function)
32+
// CIR-NOFP64:%{{.+}} = cir.call @printf(%{{.+}}, %{{.+}}) : (!cir.ptr<!s8i, addrspace(offload_constant)>, !cir.vector<!cir.float x 2>) -> !s32i cc(spir_function)
33+
// LLVM-ALL-LABEL: @test_printf_float2(
34+
// LLVM-FP64: %{{.+}} = call spir_func i32 (ptr addrspace(2), ...) @{{.*}}printf{{.*}}(ptr addrspace(2) @.str, <2 x float> %{{.*}})
35+
// LLVM-NOFP64: call spir_func i32 (ptr addrspace(2), ...) @{{.*}}printf{{.*}}(ptr addrspace(2) @.str, <2 x float> %{{.*}})
36+
37+
kernel void test_printf_half2(half2 arg) {
38+
printf("%v2hf", arg);
39+
}
40+
// CIR-ALL-LABEL: @test_printf_half2(
41+
// CIR-FP64: %{{.+}} = cir.call @printf(%{{.+}}, %{{.+}}) : (!cir.ptr<!s8i, addrspace(offload_constant)>, !cir.vector<!cir.f16 x 2>) -> !s32i cc(spir_function)
42+
// CIR-NOFP64:%{{.+}} = cir.call @printf(%{{.+}}, %{{.+}}) : (!cir.ptr<!s8i, addrspace(offload_constant)>, !cir.vector<!cir.f16 x 2>) -> !s32i cc(spir_function)
43+
// LLVM-ALL-LABEL: @test_printf_half2(
44+
// LLVM-FP64: %{{.+}} = call spir_func i32 (ptr addrspace(2), ...) @{{.*}}printf{{.*}}(ptr addrspace(2) @.str.1, <2 x half> %{{.*}})
45+
// LLVM-NOFP64: %{{.+}} = call spir_func i32 (ptr addrspace(2), ...) @{{.*}}printf{{.*}}(ptr addrspace(2) @.str.1, <2 x half> %{{.*}})
46+
47+
#if defined(cl_khr_fp64) || defined(__opencl_c_fp64)
48+
kernel void test_printf_double2(double2 arg) {
49+
printf("%v2lf", arg);
50+
}
51+
// CIR-FP64-LABEL: @test_printf_double2(
52+
// CIR-FP64: %{{.+}} = cir.call @printf(%{{.+}}, %{{.+}}) : (!cir.ptr<!s8i, addrspace(offload_constant)>, !cir.vector<!cir.double x 2>) -> !s32i cc(spir_function)
53+
// LLVM-FP64-LABEL: @test_printf_double2(
54+
// LLVM-FP64: call spir_func i32 (ptr addrspace(2), ...) @{{.*}}printf{{.*}}(ptr addrspace(2) @.str.2, <2 x double> %{{.*}})
55+
#endif
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: %clang_cc1 %s -fclangir -triple=spirv64-unknown-unknown -cl-opt-disable -emit-cir -o %t.cir -ffake-address-space-map
2+
// RUN: FileCheck -input-file=%t.cir -check-prefix=CIR %s
3+
// RUN: %clang_cc1 %s -fclangir -triple=spirv64-unknown-unknown -cl-opt-disable -emit-llvm -o %t.ll -ffake-address-space-map
4+
// RUN: FileCheck -input-file=%t.ll -check-prefix=LLVM %s
5+
6+
__constant char *__constant x = "hello world";
7+
__constant char *__constant y = "hello world";
8+
9+
// CIR: cir.global{{.*}} constant {{.*}}addrspace(offload_constant) @".str" = #cir.const_array<"hello world\00" : !cir.array<!s8i x 12>> : !cir.array<!s8i x 12>
10+
// CIR: cir.global{{.*}} constant {{.*}}addrspace(offload_constant) @x = #cir.global_view<@".str"> : !cir.ptr<!s8i, addrspace(offload_constant)>
11+
// CIR: cir.global{{.*}} constant {{.*}}addrspace(offload_constant) @y = #cir.global_view<@".str"> : !cir.ptr<!s8i, addrspace(offload_constant)>
12+
// CIR: cir.global{{.*}} constant {{.*}}addrspace(offload_constant) @".str.1" = #cir.const_array<"f\00" : !cir.array<!s8i x 2>> : !cir.array<!s8i x 2>
13+
// LLVM: addrspace(2) constant{{.*}}"hello world\00"
14+
// LLVM-NOT: addrspace(2) constant
15+
// LLVM: @x = {{(dso_local )?}}addrspace(2) constant ptr addrspace(2)
16+
// LLVM: @y = {{(dso_local )?}}addrspace(2) constant ptr addrspace(2)
17+
// LLVM: addrspace(2) constant{{.*}}"f\00"
18+
19+
void f() {
20+
// CIR: cir.store %{{.*}}, %{{.*}} : !cir.ptr<!s8i, addrspace(offload_constant)>, !cir.ptr<!cir.ptr<!s8i, addrspace(offload_constant)>, addrspace(offload_private)>
21+
// LLVM: store ptr addrspace(2) {{.*}}, ptr
22+
constant const char *f3 = __func__;
23+
}

0 commit comments

Comments
 (0)