aeubanks updated this revision to Diff 406077. aeubanks added a comment. fix more issues, ready to review I've split the OpenCL change out into D119011 <https://reviews.llvm.org/D119011>, will rebase once that's submitted
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D118744/new/ https://reviews.llvm.org/D118744 Files: clang/lib/CodeGen/CGBuilder.h clang/lib/CodeGen/CGCall.cpp clang/lib/CodeGen/CGOpenCLRuntime.cpp clang/lib/CodeGen/CGOpenCLRuntime.h clang/lib/CodeGen/CodeGenTypes.cpp clang/test/CodeGenCXX/type-cache-2.cpp clang/test/CodeGenCXX/type-cache-3.cpp clang/test/CodeGenCXX/type-cache.cpp
Index: clang/test/CodeGenCXX/type-cache.cpp =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/type-cache.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -mllvm -verify-type-cache -emit-llvm %s -o - -triple i386-pc-windows-msvc19.16.0 | FileCheck %s +// REQUIRES: asserts, x86-registered-target + +// CHECK: call {}* @"?f@@YA?AUz@@XZ"() + +struct z { + z (*p)(); +}; + +z f(); + +void g() { + f(); +} Index: clang/test/CodeGenCXX/type-cache-3.cpp =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/type-cache-3.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -mllvm -verify-type-cache -emit-llvm %s -o - -triple i386-pc-windows-msvc19.16.0 | FileCheck %s +// REQUIRES: asserts, x86-registered-target + +// CHECK-LABEL: define {{.*}}@"?f@@YAXXZ"( +// CHECK: call void @"?dc@z@@SAXU1@@Z" + +// CHECK-LABEL: define {{.*}}@"?dc@z@@SAXU1@@Z"( +// CHECK: store void ({}*)* %{{.*}}, void ({}*)** %{{.*}} +struct z { + static void dc(z) {} + void (*p)(z); +}; + +void f() { + z::dc({}); +} Index: clang/test/CodeGenCXX/type-cache-2.cpp =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/type-cache-2.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -mllvm -verify-type-cache -emit-llvm %s -o - -triple i386-pc-windows-msvc19.16.0 | FileCheck %s +// REQUIRES: asserts, x86-registered-target + +// CHECK: call void @"?dc@z@@SAXU1@@Z" +struct z { + static void dc(z); + void (*p)(z); +}; + +void f() { + z::dc({}); +} Index: clang/lib/CodeGen/CodeGenTypes.cpp =================================================================== --- clang/lib/CodeGen/CodeGenTypes.cpp +++ clang/lib/CodeGen/CodeGenTypes.cpp @@ -25,9 +25,20 @@ #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Module.h" + using namespace clang; using namespace CodeGen; +#ifndef NDEBUG +#include "llvm/Support/CommandLine.h" +// TODO: turn on by default when defined(EXPENSIVE_CHECKS) once check-clang is +// -verify-type-cache clean. +static llvm::cl::opt<bool> VerifyTypeCache( + "verify-type-cache", + llvm::cl::desc("Verify that the type cache matches the computed type"), + llvm::cl::init(false), llvm::cl::Hidden); +#endif + CodeGenTypes::CodeGenTypes(CodeGenModule &cgm) : CGM(cgm), Context(cgm.getContext()), TheModule(cgm.getModule()), Target(cgm.getTarget()), TheCXXABI(cgm.getCXXABI()), @@ -382,9 +393,6 @@ RecordsBeingLaidOut.erase(Ty); - if (SkippedLayout) - TypeCache.clear(); - if (RecordsBeingLaidOut.empty()) while (!DeferredRecords.empty()) ConvertRecordDeclType(DeferredRecords.pop_back_val()); @@ -415,11 +423,29 @@ if (const RecordType *RT = dyn_cast<RecordType>(Ty)) return ConvertRecordDeclType(RT->getDecl()); - // See if type is already cached. - llvm::DenseMap<const Type *, llvm::Type *>::iterator TCI = TypeCache.find(Ty); - // If type is found in map then use it. Otherwise, convert type T. - if (TCI != TypeCache.end()) - return TCI->second; + // The LLVM type we return for a given Clang type may not always be the same, + // most notably when dealing with recursive structs. We mark these potential + // cases with ShouldUseCache below. Builtin types cannot be recursive. + // TODO: when clang uses LLVM opaque pointers we won't be able to represent + // recursive types with LLVM types, making this logic much simpler. + llvm::Type *CachedType = nullptr; + bool ShouldUseCache = + Ty->isBuiltinType() || + (noRecordsBeingLaidOut() && FunctionsBeingProcessed.empty()); + if (ShouldUseCache) { + llvm::DenseMap<const Type *, llvm::Type *>::iterator TCI = + TypeCache.find(Ty); + if (TCI != TypeCache.end()) + CachedType = TCI->second; + if (CachedType) { +#ifndef NDEBUG + if (!VerifyTypeCache) + return CachedType; +#else + return CachedType; +#endif + } + } // If we don't have it in the cache, convert it now. llvm::Type *ResultType = nullptr; @@ -797,7 +823,15 @@ assert(ResultType && "Didn't convert a type?"); - TypeCache[Ty] = ResultType; +#ifndef NDEBUG + if (CachedType) { + assert(CachedType == ResultType && + "Cached type doesn't match computed type"); + } +#endif + + if (ShouldUseCache) + TypeCache[Ty] = ResultType; return ResultType; } Index: clang/lib/CodeGen/CGOpenCLRuntime.h =================================================================== --- clang/lib/CodeGen/CGOpenCLRuntime.h +++ clang/lib/CodeGen/CGOpenCLRuntime.h @@ -18,6 +18,7 @@ #include "clang/AST/Expr.h" #include "clang/AST/Type.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringMap.h" #include "llvm/IR/Type.h" #include "llvm/IR/Value.h" @@ -38,6 +39,7 @@ llvm::Type *PipeROTy; llvm::Type *PipeWOTy; llvm::PointerType *SamplerTy; + llvm::StringMap<llvm::PointerType *> Tys; /// Structure for enqueued block information. struct EnqueuedBlockInfo { @@ -50,6 +52,7 @@ virtual llvm::Type *getPipeType(const PipeType *T, StringRef Name, llvm::Type *&PipeTy); + llvm::PointerType *getType(const Type *T, StringRef Name); public: CGOpenCLRuntime(CodeGenModule &CGM) : CGM(CGM), Index: clang/lib/CodeGen/CGOpenCLRuntime.cpp =================================================================== --- clang/lib/CodeGen/CGOpenCLRuntime.cpp +++ clang/lib/CodeGen/CGOpenCLRuntime.cpp @@ -34,41 +34,45 @@ assert(T->isOpenCLSpecificType() && "Not an OpenCL specific type!"); - llvm::LLVMContext& Ctx = CGM.getLLVMContext(); - uint32_t AddrSpc = CGM.getContext().getTargetAddressSpace( - CGM.getContext().getOpenCLTypeAddrSpace(T)); switch (cast<BuiltinType>(T)->getKind()) { default: llvm_unreachable("Unexpected opencl builtin type!"); return nullptr; -#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ - case BuiltinType::Id: \ - return llvm::PointerType::get( \ - llvm::StructType::create(Ctx, "opencl." #ImgType "_" #Suffix "_t"), \ - AddrSpc); +#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ + case BuiltinType::Id: \ + return getType(T, "opencl." #ImgType "_" #Suffix "_t"); #include "clang/Basic/OpenCLImageTypes.def" case BuiltinType::OCLSampler: return getSamplerType(T); case BuiltinType::OCLEvent: - return llvm::PointerType::get( - llvm::StructType::create(Ctx, "opencl.event_t"), AddrSpc); + return getType(T, "opencl.event_t"); case BuiltinType::OCLClkEvent: - return llvm::PointerType::get( - llvm::StructType::create(Ctx, "opencl.clk_event_t"), AddrSpc); + return getType(T, "opencl.clk_event_t"); case BuiltinType::OCLQueue: - return llvm::PointerType::get( - llvm::StructType::create(Ctx, "opencl.queue_t"), AddrSpc); + return getType(T, "opencl.queue_t"); case BuiltinType::OCLReserveID: - return llvm::PointerType::get( - llvm::StructType::create(Ctx, "opencl.reserve_id_t"), AddrSpc); -#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ - case BuiltinType::Id: \ - return llvm::PointerType::get( \ - llvm::StructType::create(Ctx, "opencl." #ExtType), AddrSpc); + return getType(T, "opencl.reserve_id_t"); +#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ + case BuiltinType::Id: \ + return getType(T, "opencl." #ExtType); #include "clang/Basic/OpenCLExtensionTypes.def" } } +llvm::PointerType *CGOpenCLRuntime::getType(const Type *T, StringRef Name) { + auto I = Tys.find(Name); + if (I != Tys.end()) + return I->second; + + llvm::LLVMContext &Ctx = CGM.getLLVMContext(); + uint32_t AddrSpc = CGM.getContext().getTargetAddressSpace( + CGM.getContext().getOpenCLTypeAddrSpace(T)); + auto *PTy = + llvm::PointerType::get(llvm::StructType::create(Ctx, Name), AddrSpc); + Tys[Name] = PTy; + return PTy; +} + llvm::Type *CGOpenCLRuntime::getPipeType(const PipeType *T) { if (T->isReadOnly()) return getPipeType(T, "opencl.pipe_ro_t", PipeROTy); Index: clang/lib/CodeGen/CGCall.cpp =================================================================== --- clang/lib/CodeGen/CGCall.cpp +++ clang/lib/CodeGen/CGCall.cpp @@ -38,6 +38,7 @@ #include "llvm/IR/InlineAsm.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Intrinsics.h" +#include "llvm/IR/Type.h" #include "llvm/Transforms/Utils/Local.h" using namespace clang; using namespace CodeGen; @@ -1056,10 +1057,19 @@ // Call EmitStoreOfScalar except when the lvalue is a bitfield to emit a // primitive store. assert(isa<NoExpansion>(Exp.get())); - if (LV.isBitField()) - EmitStoreThroughLValue(RValue::get(&*AI++), LV); - else - EmitStoreOfScalar(&*AI++, LV); + llvm::Value *Arg = &*AI++; + if (LV.isBitField()) { + EmitStoreThroughLValue(RValue::get(Arg), LV); + } else { + // TODO: currently there are some places are inconsistent in what LLVM + // pointer type they use (see D118744). Once clang uses opaque pointers + // all LLVM pointer types will be the same and we can remove this check. + if (Arg->getType()->isPointerTy()) { + Address Addr = LV.getAddress(*this); + Arg = Builder.CreateBitCast(Arg, Addr.getElementType()); + } + EmitStoreOfScalar(Arg, LV); + } } } Index: clang/lib/CodeGen/CGBuilder.h =================================================================== --- clang/lib/CodeGen/CGBuilder.h +++ clang/lib/CodeGen/CGBuilder.h @@ -9,10 +9,11 @@ #ifndef LLVM_CLANG_LIB_CODEGEN_CGBUILDER_H #define LLVM_CLANG_LIB_CODEGEN_CGBUILDER_H -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/IRBuilder.h" #include "Address.h" #include "CodeGenTypeCache.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Type.h" namespace clang { namespace CodeGen {
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits