[clang] 2641d9b - Propagate the volatile qualifier of exp to store /load operations .

Kishan Parmar via cfe-commits cfe-commits at lists.llvm.org
Sat Sep 23 07:10:30 PDT 2023


Author: Umesh Kalappa
Date: 2023-09-23T19:40:24+05:30
New Revision: 2641d9b2807ded4b712f4dca809d63c138c91361

URL: https://github.com/llvm/llvm-project/commit/2641d9b2807ded4b712f4dca809d63c138c91361
DIFF: https://github.com/llvm/llvm-project/commit/2641d9b2807ded4b712f4dca809d63c138c91361.diff

LOG: Propagate the volatile qualifier of exp  to  store /load operations .

This changes to address the PR : 55207

We update the volatility  on the LValue by looking at the LHS cast operation qualifier and propagate the RValue volatile-ness   from  the CGF data structure .

Reviewed By: rjmccall

Differential Revision: https://reviews.llvm.org/D157890

Added: 
    clang/test/CodeGen/volatile.cpp

Modified: 
    clang/include/clang/AST/Expr.h
    clang/lib/CodeGen/CGExpr.cpp
    clang/lib/CodeGen/CGExprComplex.cpp
    clang/lib/CodeGen/CGExprScalar.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index fe20a84216d1f11..1c717b520dd87c6 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -3608,6 +3608,19 @@ class CastExpr : public Expr {
     return FPOptionsOverride();
   }
 
+  /// Return
+  //  True : if this conversion changes the volatile-ness of a gl-value.
+  //         Qualification conversions on gl-values currently use CK_NoOp, but
+  //         it's important to recognize volatile-changing conversions in
+  //         clients code generation that normally eagerly peephole loads. Note
+  //         that the query is answering for this specific node; Sema may
+  //         produce multiple cast nodes for any particular conversion sequence.
+  //  False : Otherwise.
+  bool changesVolatileQualification() const {
+    return (isGLValue() && (getType().isVolatileQualified() !=
+                            getSubExpr()->getType().isVolatileQualified()));
+  }
+
   static const FieldDecl *getTargetFieldForToUnionCast(QualType unionType,
                                                        QualType opType);
   static const FieldDecl *getTargetFieldForToUnionCast(const RecordDecl *RD,

diff  --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 76bbeba468db643..86239d5e89fcc4d 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -4802,6 +4802,9 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
     // bound and change the IR type.
     // FIXME: Once pointee types are removed from IR, remove this.
     LValue LV = EmitLValue(E->getSubExpr());
+    // Propagate the volatile qualifer to LValue, if exist in E.
+    if (E->changesVolatileQualification())
+      LV.getQuals() = E->getType().getQualifiers();
     if (LV.isSimple()) {
       Address V = LV.getAddress(*this);
       if (V.isValid()) {

diff  --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp
index 2dd1a991ec97199..f3cbd1d0451ebe4 100644
--- a/clang/lib/CodeGen/CGExprComplex.cpp
+++ b/clang/lib/CodeGen/CGExprComplex.cpp
@@ -177,11 +177,15 @@ class ComplexExprEmitter
   ComplexPairTy VisitImplicitCastExpr(ImplicitCastExpr *E) {
     // Unlike for scalars, we don't have to worry about function->ptr demotion
     // here.
+    if (E->changesVolatileQualification())
+      return EmitLoadOfLValue(E);
     return EmitCast(E->getCastKind(), E->getSubExpr(), E->getType());
   }
   ComplexPairTy VisitCastExpr(CastExpr *E) {
     if (const auto *ECE = dyn_cast<ExplicitCastExpr>(E))
       CGF.CGM.EmitExplicitCastExprType(ECE, &CGF);
+    if (E->changesVolatileQualification())
+       return EmitLoadOfLValue(E);
     return EmitCast(E->getCastKind(), E->getSubExpr(), E->getType());
   }
   ComplexPairTy VisitCallExpr(const CallExpr *E);

diff  --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index a71b7057bb523a9..d76ce15b41ac570 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -2225,7 +2225,9 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
     return Visit(const_cast<Expr*>(E));
 
   case CK_NoOp: {
-    llvm::Value *V = Visit(const_cast<Expr *>(E));
+    llvm::Value *V = CE->changesVolatileQualification()
+                         ? EmitLoadOfLValue(CE)
+                         : Visit(const_cast<Expr *>(E));
     if (V) {
       // CK_NoOp can model a pointer qualification conversion, which can remove
       // an array bound and change the IR type.

diff  --git a/clang/test/CodeGen/volatile.cpp b/clang/test/CodeGen/volatile.cpp
new file mode 100644
index 000000000000000..38724659ad8a355
--- /dev/null
+++ b/clang/test/CodeGen/volatile.cpp
@@ -0,0 +1,43 @@
+// RUN: %clang_cc1 -O2 -triple=x86_64-unknown-linux-gnu -emit-llvm %s -o -  | FileCheck %s -check-prefix CHECK
+struct agg 
+{
+int a ;
+int b ;
+} t;
+struct agg a;
+int vt=10;
+_Complex float cf;
+int volatile vol =10;
+void f0() {
+    const_cast<volatile _Complex float &>(cf) = const_cast<volatile _Complex float&>(cf) + 1;
+//  CHECK: %cf.real = load volatile float, ptr @cf
+//  CHECK: %cf.imag = load volatile float, ptr getelementptr
+//  CHECK: %add.r = fadd float %cf.real, 1.000000e+00
+//  CHECK: %add.i = fadd float %cf.imag, 0.000000e+00
+//  CHECK: store volatile float %add.r
+//  CHECK: store volatile float %add.i, ptr getelementptr
+      static_cast<volatile _Complex float &>(cf) = static_cast<volatile _Complex float&>(cf) + 1;
+//  CHECK: %cf.real1 = load volatile float, ptr @cf
+//  CHECK: %cf.imag2 = load volatile float, ptr getelementptr
+//  CHECK: %add.r3 = fadd float %cf.real1, 1.000000e+00
+//  CHECK: %add.i4 = fadd float %cf.imag2, 0.000000e+00
+//  CHECK: store volatile float %add.r3, ptr @cf
+//  CHECK: store volatile float %add.i4, ptr getelementptr
+    const_cast<volatile  int  &>(a.a) = const_cast<volatile int &>(t.a) ;
+//  CHECK: %0 = load volatile i32, ptr @t
+//  CHECK: store volatile i32 %0, ptr @a
+    static_cast<volatile  int  &>(a.b) = static_cast<volatile int  &>(t.a) ;
+//  CHECK: %1 = load volatile i32, ptr @t
+//  CHECK: store volatile i32 %1, ptr getelementptr
+    const_cast<volatile int&>(vt) = const_cast<volatile int&>(vt) + 1;
+//  CHECK: %2 = load volatile i32, ptr @vt
+//  CHECK: %add = add nsw i32 %2, 1
+//  CHECK: store volatile i32 %add, ptr @vt
+     static_cast<volatile int&>(vt) = static_cast<volatile int&>(vt) + 1;
+//  CHECK: %3 = load volatile i32, ptr @vt
+//  CHECK: %add5 = add nsw i32 %3, 1
+//  CHECK: store volatile i32 %add5, ptr @vt
+    vt = const_cast<int&>(vol);
+//  %4 = load i32, ptr @vol
+//  store i32 %4, ptr @vt
+}


        


More information about the cfe-commits mailing list