yaxunl updated this revision to Diff 247688.
yaxunl marked 2 inline comments as done.
yaxunl added a comment.

revised by John's comments.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D75423/new/

https://reviews.llvm.org/D75423

Files:
  clang/lib/CodeGen/CGDeclCXX.cpp
  clang/lib/CodeGen/CGExpr.cpp
  clang/lib/CodeGen/CGExprScalar.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/test/CodeGenOpenCL/invariant.cl
  clang/test/CodeGenOpenCL/printf.cl

Index: clang/test/CodeGenOpenCL/printf.cl
===================================================================
--- clang/test/CodeGenOpenCL/printf.cl
+++ clang/test/CodeGenOpenCL/printf.cl
@@ -12,25 +12,25 @@
 
 
 // ALL-LABEL: @test_printf_float2(
-// FP64: %call = call spir_func i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* getelementptr inbounds ([7 x i8], [7 x i8] addrspace(2)* @.str, i32 0, i32 0), <2 x float> %0)
+// FP64: %call = call spir_func i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* getelementptr inbounds ([7 x i8], [7 x i8] addrspace(2)* @.str, i32 0, i32 0), <2 x float>
 
 
-// NOFP64:  call spir_func i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* getelementptr inbounds ([7 x i8], [7 x i8] addrspace(2)* @.str, i32 0, i32 0), <2 x float> %0)
+// NOFP64:  call spir_func i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* getelementptr inbounds ([7 x i8], [7 x i8] addrspace(2)* @.str, i32 0, i32 0), <2 x float>
 kernel void test_printf_float2(float2 arg) {
   printf("%v2hlf", arg);
 }
 
 // ALL-LABEL: @test_printf_half2(
-// FP64:  %call = call spir_func i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* getelementptr inbounds ([6 x i8], [6 x i8] addrspace(2)* @.str.1, i32 0, i32 0), <2 x half> %0)
+// FP64:  %call = call spir_func i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* getelementptr inbounds ([6 x i8], [6 x i8] addrspace(2)* @.str.1, i32 0, i32 0), <2 x half>
 
-// NOFP64:  %call = call spir_func i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* getelementptr inbounds ([6 x i8], [6 x i8] addrspace(2)* @.str.1, i32 0, i32 0), <2 x half> %0)
+// NOFP64:  %call = call spir_func i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* getelementptr inbounds ([6 x i8], [6 x i8] addrspace(2)* @.str.1, i32 0, i32 0), <2 x half>
 kernel void test_printf_half2(half2 arg) {
   printf("%v2hf", arg);
 }
 
 #ifdef cl_khr_fp64
 // FP64-LABEL: @test_printf_double2(
-// FP64: call spir_func i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* getelementptr inbounds ([6 x i8], [6 x i8] addrspace(2)* @.str.2, i32 0, i32 0), <2 x double> %0)
+// FP64: call spir_func i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* getelementptr inbounds ([6 x i8], [6 x i8] addrspace(2)* @.str.2, i32 0, i32 0), <2 x double>
 kernel void test_printf_double2(double2 arg) {
   printf("%v2lf", arg);
 }
Index: clang/test/CodeGenOpenCL/invariant.cl
===================================================================
--- /dev/null
+++ clang/test/CodeGenOpenCL/invariant.cl
@@ -0,0 +1,38 @@
+// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -O3 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple spir -O3 -emit-llvm -o - %s | FileCheck %s
+
+typedef struct {
+  int a;
+  char b;
+} X;
+
+constant X x = {0, 'a'};
+
+constant char* constant p = &(x.b);
+
+constant X* foo();
+
+// CHECK-LABEL: test1
+// CHECK: llvm.invariant.start
+char test1() {
+  return x.b;
+}
+
+// CHECK-LABEL: test2
+// CHECK: llvm.invariant.start
+char test2() {
+  return *p;
+}
+
+// CHECK-LABEL: test3
+// CHECK: llvm.invariant.start
+char test3(constant X *x) {
+  constant char *p = &(x->b);
+  return *p;
+}
+
+// CHECK-LABEL: test4
+// CHECK: llvm.invariant.start
+char test4() {
+  return foo()->b;
+}
Index: clang/lib/CodeGen/CodeGenFunction.h
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.h
+++ clang/lib/CodeGen/CodeGenFunction.h
@@ -4070,7 +4070,7 @@
                                 llvm::GlobalVariable *GV);
 
   // Emit an @llvm.invariant.start call for the given memory region.
-  void EmitInvariantStart(llvm::Constant *Addr, CharUnits Size);
+  void EmitInvariantStart(llvm::Value *Addr, CharUnits Size);
 
   /// EmitCXXGlobalVarDeclInit - Create the initializer for a C++
   /// variable with global storage.
Index: clang/lib/CodeGen/CGExprScalar.cpp
===================================================================
--- clang/lib/CodeGen/CGExprScalar.cpp
+++ clang/lib/CodeGen/CGExprScalar.cpp
@@ -262,7 +262,17 @@
                       const BinOpInfo &Info);
 
   Value *EmitLoadOfLValue(LValue LV, SourceLocation Loc) {
-    return CGF.EmitLoadOfLValue(LV, Loc).getScalarVal();
+    auto *V = CGF.EmitLoadOfLValue(LV, Loc).getScalarVal();
+    // Mark a pointer to OpenCL constant address space as invariant.
+    auto QT = LV.getType();
+    if (QT->isPointerType()) {
+      auto PointeeTy = QT->getPointeeType();
+      if (PointeeTy.getAddressSpace() == LangAS::opencl_constant) {
+        CGF.EmitInvariantStart(V,
+                               CGF.getContext().getTypeSizeInChars(PointeeTy));
+      }
+    }
+    return V;
   }
 
   void EmitLValueAlignmentAssumption(const Expr *E, Value *V) {
Index: clang/lib/CodeGen/CGExpr.cpp
===================================================================
--- clang/lib/CodeGen/CGExpr.cpp
+++ clang/lib/CodeGen/CGExpr.cpp
@@ -1252,62 +1252,88 @@
 ///
 LValue CodeGenFunction::EmitLValue(const Expr *E) {
   ApplyDebugLocation DL(*this, E);
+  LValue Ret;
   switch (E->getStmtClass()) {
-  default: return EmitUnsupportedLValue(E, "l-value expression");
+  default:
+    Ret = EmitUnsupportedLValue(E, "l-value expression");
+    break;
 
   case Expr::ObjCPropertyRefExprClass:
     llvm_unreachable("cannot emit a property reference directly");
+    break;
 
   case Expr::ObjCSelectorExprClass:
-    return EmitObjCSelectorLValue(cast<ObjCSelectorExpr>(E));
+    Ret = EmitObjCSelectorLValue(cast<ObjCSelectorExpr>(E));
+    break;
   case Expr::ObjCIsaExprClass:
-    return EmitObjCIsaExpr(cast<ObjCIsaExpr>(E));
+    Ret = EmitObjCIsaExpr(cast<ObjCIsaExpr>(E));
+    break;
   case Expr::BinaryOperatorClass:
-    return EmitBinaryOperatorLValue(cast<BinaryOperator>(E));
+    Ret = EmitBinaryOperatorLValue(cast<BinaryOperator>(E));
+    break;
   case Expr::CompoundAssignOperatorClass: {
     QualType Ty = E->getType();
     if (const AtomicType *AT = Ty->getAs<AtomicType>())
       Ty = AT->getValueType();
     if (!Ty->isAnyComplexType())
-      return EmitCompoundAssignmentLValue(cast<CompoundAssignOperator>(E));
-    return EmitComplexCompoundAssignmentLValue(cast<CompoundAssignOperator>(E));
+      Ret = EmitCompoundAssignmentLValue(cast<CompoundAssignOperator>(E));
+    else
+      Ret =
+          EmitComplexCompoundAssignmentLValue(cast<CompoundAssignOperator>(E));
+    break;
   }
   case Expr::CallExprClass:
   case Expr::CXXMemberCallExprClass:
   case Expr::CXXOperatorCallExprClass:
   case Expr::UserDefinedLiteralClass:
-    return EmitCallExprLValue(cast<CallExpr>(E));
+    Ret = EmitCallExprLValue(cast<CallExpr>(E));
+    break;
   case Expr::CXXRewrittenBinaryOperatorClass:
-    return EmitLValue(cast<CXXRewrittenBinaryOperator>(E)->getSemanticForm());
+    Ret = EmitLValue(cast<CXXRewrittenBinaryOperator>(E)->getSemanticForm());
+    break;
   case Expr::VAArgExprClass:
-    return EmitVAArgExprLValue(cast<VAArgExpr>(E));
+    Ret = EmitVAArgExprLValue(cast<VAArgExpr>(E));
+    break;
   case Expr::DeclRefExprClass:
-    return EmitDeclRefLValue(cast<DeclRefExpr>(E));
+    Ret = EmitDeclRefLValue(cast<DeclRefExpr>(E));
+    break;
   case Expr::ConstantExprClass:
-    return EmitLValue(cast<ConstantExpr>(E)->getSubExpr());
+    Ret = EmitLValue(cast<ConstantExpr>(E)->getSubExpr());
+    break;
   case Expr::ParenExprClass:
-    return EmitLValue(cast<ParenExpr>(E)->getSubExpr());
+    Ret = EmitLValue(cast<ParenExpr>(E)->getSubExpr());
+    break;
   case Expr::GenericSelectionExprClass:
-    return EmitLValue(cast<GenericSelectionExpr>(E)->getResultExpr());
+    Ret = EmitLValue(cast<GenericSelectionExpr>(E)->getResultExpr());
+    break;
   case Expr::PredefinedExprClass:
-    return EmitPredefinedLValue(cast<PredefinedExpr>(E));
+    Ret = EmitPredefinedLValue(cast<PredefinedExpr>(E));
+    break;
   case Expr::StringLiteralClass:
-    return EmitStringLiteralLValue(cast<StringLiteral>(E));
+    Ret = EmitStringLiteralLValue(cast<StringLiteral>(E));
+    break;
   case Expr::ObjCEncodeExprClass:
-    return EmitObjCEncodeExprLValue(cast<ObjCEncodeExpr>(E));
+    Ret = EmitObjCEncodeExprLValue(cast<ObjCEncodeExpr>(E));
+    break;
   case Expr::PseudoObjectExprClass:
-    return EmitPseudoObjectLValue(cast<PseudoObjectExpr>(E));
+    Ret = EmitPseudoObjectLValue(cast<PseudoObjectExpr>(E));
+    break;
   case Expr::InitListExprClass:
-    return EmitInitListLValue(cast<InitListExpr>(E));
+    Ret = EmitInitListLValue(cast<InitListExpr>(E));
+    break;
   case Expr::CXXTemporaryObjectExprClass:
   case Expr::CXXConstructExprClass:
-    return EmitCXXConstructLValue(cast<CXXConstructExpr>(E));
+    Ret = EmitCXXConstructLValue(cast<CXXConstructExpr>(E));
+    break;
   case Expr::CXXBindTemporaryExprClass:
-    return EmitCXXBindTemporaryLValue(cast<CXXBindTemporaryExpr>(E));
+    Ret = EmitCXXBindTemporaryLValue(cast<CXXBindTemporaryExpr>(E));
+    break;
   case Expr::CXXUuidofExprClass:
-    return EmitCXXUuidofLValue(cast<CXXUuidofExpr>(E));
+    Ret = EmitCXXUuidofLValue(cast<CXXUuidofExpr>(E));
+    break;
   case Expr::LambdaExprClass:
-    return EmitAggExprToLValue(E);
+    Ret = EmitAggExprToLValue(E);
+    break;
 
   case Expr::ExprWithCleanupsClass: {
     const auto *cleanups = cast<ExprWithCleanups>(E);
@@ -1319,55 +1345,74 @@
       // cleanups.
       llvm::Value *V = LV.getPointer(*this);
       Scope.ForceCleanup({&V});
-      return LValue::MakeAddr(Address(V, LV.getAlignment()), LV.getType(),
-                              getContext(), LV.getBaseInfo(), LV.getTBAAInfo());
+      Ret = LValue::MakeAddr(Address(V, LV.getAlignment()), LV.getType(),
+                             getContext(), LV.getBaseInfo(), LV.getTBAAInfo());
     }
     // FIXME: Is it possible to create an ExprWithCleanups that produces a
     // bitfield lvalue or some other non-simple lvalue?
-    return LV;
+    else
+      Ret = LV;
+    break;
   }
 
   case Expr::CXXDefaultArgExprClass: {
     auto *DAE = cast<CXXDefaultArgExpr>(E);
     CXXDefaultArgExprScope Scope(*this, DAE);
-    return EmitLValue(DAE->getExpr());
+    Ret = EmitLValue(DAE->getExpr());
+    break;
   }
   case Expr::CXXDefaultInitExprClass: {
     auto *DIE = cast<CXXDefaultInitExpr>(E);
     CXXDefaultInitExprScope Scope(*this, DIE);
-    return EmitLValue(DIE->getExpr());
+    Ret = EmitLValue(DIE->getExpr());
+    break;
   }
   case Expr::CXXTypeidExprClass:
-    return EmitCXXTypeidLValue(cast<CXXTypeidExpr>(E));
+    Ret = EmitCXXTypeidLValue(cast<CXXTypeidExpr>(E));
+    break;
 
   case Expr::ObjCMessageExprClass:
-    return EmitObjCMessageExprLValue(cast<ObjCMessageExpr>(E));
+    Ret = EmitObjCMessageExprLValue(cast<ObjCMessageExpr>(E));
+    break;
   case Expr::ObjCIvarRefExprClass:
-    return EmitObjCIvarRefLValue(cast<ObjCIvarRefExpr>(E));
+    Ret = EmitObjCIvarRefLValue(cast<ObjCIvarRefExpr>(E));
+    break;
   case Expr::StmtExprClass:
-    return EmitStmtExprLValue(cast<StmtExpr>(E));
+    Ret = EmitStmtExprLValue(cast<StmtExpr>(E));
+    break;
   case Expr::UnaryOperatorClass:
-    return EmitUnaryOpLValue(cast<UnaryOperator>(E));
+    Ret = EmitUnaryOpLValue(cast<UnaryOperator>(E));
+    break;
   case Expr::ArraySubscriptExprClass:
-    return EmitArraySubscriptExpr(cast<ArraySubscriptExpr>(E));
+    Ret = EmitArraySubscriptExpr(cast<ArraySubscriptExpr>(E));
+    break;
   case Expr::OMPArraySectionExprClass:
-    return EmitOMPArraySectionExpr(cast<OMPArraySectionExpr>(E));
+    Ret = EmitOMPArraySectionExpr(cast<OMPArraySectionExpr>(E));
+    break;
   case Expr::ExtVectorElementExprClass:
-    return EmitExtVectorElementExpr(cast<ExtVectorElementExpr>(E));
+    Ret = EmitExtVectorElementExpr(cast<ExtVectorElementExpr>(E));
+    break;
   case Expr::MemberExprClass:
-    return EmitMemberExpr(cast<MemberExpr>(E));
+    Ret = EmitMemberExpr(cast<MemberExpr>(E));
+    break;
   case Expr::CompoundLiteralExprClass:
-    return EmitCompoundLiteralLValue(cast<CompoundLiteralExpr>(E));
+    Ret = EmitCompoundLiteralLValue(cast<CompoundLiteralExpr>(E));
+    break;
   case Expr::ConditionalOperatorClass:
-    return EmitConditionalOperatorLValue(cast<ConditionalOperator>(E));
+    Ret = EmitConditionalOperatorLValue(cast<ConditionalOperator>(E));
+    break;
   case Expr::BinaryConditionalOperatorClass:
-    return EmitConditionalOperatorLValue(cast<BinaryConditionalOperator>(E));
+    Ret = EmitConditionalOperatorLValue(cast<BinaryConditionalOperator>(E));
+    break;
   case Expr::ChooseExprClass:
-    return EmitLValue(cast<ChooseExpr>(E)->getChosenSubExpr());
+    Ret = EmitLValue(cast<ChooseExpr>(E)->getChosenSubExpr());
+    break;
   case Expr::OpaqueValueExprClass:
-    return EmitOpaqueValueLValue(cast<OpaqueValueExpr>(E));
+    Ret = EmitOpaqueValueLValue(cast<OpaqueValueExpr>(E));
+    break;
   case Expr::SubstNonTypeTemplateParmExprClass:
-    return EmitLValue(cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement());
+    Ret = EmitLValue(cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement());
+    break;
   case Expr::ImplicitCastExprClass:
   case Expr::CStyleCastExprClass:
   case Expr::CXXFunctionalCastExprClass:
@@ -1376,16 +1421,30 @@
   case Expr::CXXReinterpretCastExprClass:
   case Expr::CXXConstCastExprClass:
   case Expr::ObjCBridgedCastExprClass:
-    return EmitCastLValue(cast<CastExpr>(E));
+    Ret = EmitCastLValue(cast<CastExpr>(E));
+    break;
 
   case Expr::MaterializeTemporaryExprClass:
-    return EmitMaterializeTemporaryExpr(cast<MaterializeTemporaryExpr>(E));
+    Ret = EmitMaterializeTemporaryExpr(cast<MaterializeTemporaryExpr>(E));
+    break;
 
   case Expr::CoawaitExprClass:
-    return EmitCoawaitLValue(cast<CoawaitExpr>(E));
+    Ret = EmitCoawaitLValue(cast<CoawaitExpr>(E));
+    break;
   case Expr::CoyieldExprClass:
-    return EmitCoyieldLValue(cast<CoyieldExpr>(E));
+    Ret = EmitCoyieldLValue(cast<CoyieldExpr>(E));
+    break;
   }
+
+  // Mark a pointer to OpenCL constant memory as invariant.
+  // ToDo: Currently we only handle simple l-value. We should also handle other
+  // l-values.
+  if (Ret.getAddressSpace() == LangAS::opencl_constant && Ret.isSimple()) {
+    EmitInvariantStart(Ret.getPointer(*this),
+                       getContext().getTypeSizeInChars(Ret.getType()));
+  }
+
+  return Ret;
 }
 
 /// Given an object of the given canonical type, can we safely copy a
@@ -4159,6 +4218,7 @@
   }
 
   unsigned RecordCVR = base.getVRQualifiers();
+  auto RecordAddrSpace = base.getAddressSpace();
   if (rec->isUnion()) {
     // For unions, there is no pointer adjustment.
     if (CGM.getCodeGenOpts().StrictVTablePointers &&
@@ -4217,6 +4277,7 @@
 
   LValue LV = MakeAddrLValue(addr, FieldType, FieldBaseInfo, FieldTBAAInfo);
   LV.getQuals().addCVRQualifiers(RecordCVR);
+  LV.getQuals().setAddressSpace(RecordAddrSpace);
 
   // __weak attribute on a field is ignored.
   if (LV.getQuals().getObjCGCAttr() == Qualifiers::Weak)
Index: clang/lib/CodeGen/CGDeclCXX.cpp
===================================================================
--- clang/lib/CodeGen/CGDeclCXX.cpp
+++ clang/lib/CodeGen/CGDeclCXX.cpp
@@ -153,7 +153,7 @@
       Addr, CGF.getContext().getTypeSizeInChars(D.getType()));
 }
 
-void CodeGenFunction::EmitInvariantStart(llvm::Constant *Addr, CharUnits Size) {
+void CodeGenFunction::EmitInvariantStart(llvm::Value *Addr, CharUnits Size) {
   // Do not emit the intrinsic if we're not optimizing.
   if (!CGM.getCodeGenOpts().OptimizationLevel)
     return;
@@ -161,14 +161,14 @@
   // Grab the llvm.invariant.start intrinsic.
   llvm::Intrinsic::ID InvStartID = llvm::Intrinsic::invariant_start;
   // Overloaded address space type.
-  llvm::Type *ObjectPtr[1] = {Int8PtrTy};
+  llvm::Type *ObjectPtr[1] = {
+      Int8Ty->getPointerTo(Addr->getType()->getPointerAddressSpace())};
   llvm::Function *InvariantStart = CGM.getIntrinsic(InvStartID, ObjectPtr);
 
   // Emit a call with the size in bytes of the object.
-  uint64_t Width = Size.getQuantity();
-  llvm::Value *Args[2] = { llvm::ConstantInt::getSigned(Int64Ty, Width),
-                           llvm::ConstantExpr::getBitCast(Addr, Int8PtrTy)};
-  Builder.CreateCall(InvariantStart, Args);
+  Builder.CreateCall(InvariantStart,
+                     {llvm::ConstantInt::getSigned(Int64Ty, Size.getQuantity()),
+                      Builder.CreateBitCast(Addr, ObjectPtr[0])});
 }
 
 void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to