diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 559bd4c60bcf..ad96d2e573dd 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -49,13 +49,13 @@ llvm::Value *CodeGenFunction::EvaluateExprAsBool(const Expr *E) { /// aggregate expression, the aggloc/agglocvolatile arguments indicate where /// the result should be returned. RValue CodeGenFunction::EmitAnyExpr(const Expr *E, llvm::Value *AggLoc, - bool isAggLocVolatile) { + bool isAggLocVolatile, bool IgnoreResult) { if (!hasAggregateLLVMType(E->getType())) return RValue::get(EmitScalarExpr(E)); else if (E->getType()->isAnyComplexType()) return RValue::getComplex(EmitComplexExpr(E)); - EmitAggExpr(E, AggLoc, isAggLocVolatile); + EmitAggExpr(E, AggLoc, isAggLocVolatile, IgnoreResult); return RValue::getAggregate(AggLoc, isAggLocVolatile); } diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index c558d137e2c8..2a3e21f806d2 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -34,10 +34,13 @@ class VISIBILITY_HIDDEN AggExprEmitter : public StmtVisitor { CGBuilderTy &Builder; llvm::Value *DestPtr; bool VolatileDest; + bool IgnoreResult; + public: - AggExprEmitter(CodeGenFunction &cgf, llvm::Value *destPtr, bool volatileDest) + AggExprEmitter(CodeGenFunction &cgf, llvm::Value *destPtr, bool volatileDest, + bool IgnoreResult) : CGF(cgf), Builder(CGF.Builder), - DestPtr(destPtr), VolatileDest(volatileDest) { + DestPtr(destPtr), VolatileDest(volatileDest), IgnoreResult(IgnoreResult) { } //===--------------------------------------------------------------------===// @@ -50,8 +53,8 @@ public: void EmitAggLoadOfLValue(const Expr *E); /// EmitFinalDestCopy - Perform the final copy to DestPtr, if desired. - void EmitFinalDestCopy(const Expr *E, LValue Src); - void EmitFinalDestCopy(const Expr *E, RValue Src); + void EmitFinalDestCopy(const Expr *E, LValue Src, bool Ignore = false); + void EmitFinalDestCopy(const Expr *E, RValue Src, bool Ignore = false); //===--------------------------------------------------------------------===// // Visitor Methods @@ -127,17 +130,16 @@ void AggExprEmitter::EmitAggLoadOfLValue(const Expr *E) { } /// EmitFinalDestCopy - Perform the final copy to DestPtr, if desired. -void AggExprEmitter::EmitFinalDestCopy(const Expr *E, RValue Src) { +void AggExprEmitter::EmitFinalDestCopy(const Expr *E, RValue Src, bool Ignore) { assert(Src.isAggregate() && "value must be aggregate value!"); // If the result is ignored, don't copy from the value. if (DestPtr == 0) { - if (Src.isVolatileQualified()) - // If the source is volatile, we must read from it; to do that, we need - // some place to put it. - DestPtr = CGF.CreateTempAlloca(CGF.ConvertType(E->getType()), "agg.tmp"); - else + if (!Src.isVolatileQualified() || (IgnoreResult && Ignore)) return; + // If the source is volatile, we must read from it; to do that, we need + // some place to put it. + DestPtr = CGF.CreateTempAlloca(CGF.ConvertType(E->getType()), "agg.tmp"); } // If the result of the assignment is used, copy the LHS there also. @@ -149,11 +151,12 @@ void AggExprEmitter::EmitFinalDestCopy(const Expr *E, RValue Src) { } /// EmitFinalDestCopy - Perform the final copy to DestPtr, if desired. -void AggExprEmitter::EmitFinalDestCopy(const Expr *E, LValue Src) { +void AggExprEmitter::EmitFinalDestCopy(const Expr *E, LValue Src, bool Ignore) { assert(Src.isSimple() && "Can't have aggregate bitfield, vector, etc"); EmitFinalDestCopy(E, RValue::getAggregate(Src.getAddress(), - Src.isVolatileQualified())); + Src.isVolatileQualified()), + Ignore); } //===----------------------------------------------------------------------===// @@ -244,7 +247,7 @@ void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) { } else { // Codegen the RHS so that it stores directly into the LHS. CGF.EmitAggExpr(E->getRHS(), LHS.getAddress(), LHS.isVolatileQualified()); - EmitFinalDestCopy(E, LHS); + EmitFinalDestCopy(E, LHS, true); } } @@ -470,13 +473,14 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { /// the value of the aggregate expression is not needed. If VolatileDest is /// true, DestPtr cannot be 0. void CodeGenFunction::EmitAggExpr(const Expr *E, llvm::Value *DestPtr, - bool VolatileDest) { + bool VolatileDest, bool IgnoreResult) { assert(E && hasAggregateLLVMType(E->getType()) && "Invalid aggregate expression to emit"); assert ((DestPtr != 0 || VolatileDest == false) && "volatile aggregate can't be 0"); - AggExprEmitter(*this, DestPtr, VolatileDest).Visit(const_cast(E)); + AggExprEmitter(*this, DestPtr, VolatileDest, IgnoreResult) + .Visit(const_cast(E)); } void CodeGenFunction::EmitAggregateClear(llvm::Value *DestPtr, QualType Ty) { @@ -522,9 +526,8 @@ void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr, // a = b; // } // - // either, we need to use a differnt call here, or the backend needs to be - // taught to not do this. We use isVolatile to indicate when either the - // source or the destination is volatile. + // we need to use a differnt call here. We use isVolatile to indicate when + // either the source or the destination is volatile. Builder.CreateCall4(CGM.getMemCpyFn(), DestPtr, SrcPtr, // TypeInfo.first describes size in bits. diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index da586b1d74c9..b13b9e529d3c 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -58,7 +58,7 @@ void CodeGenFunction::EmitStmt(const Stmt *S) { // Must be an expression in a stmt context. Emit the value (to get // side-effects) and ignore the result. if (const Expr *E = dyn_cast(S)) { - EmitAnyExpr(E); + EmitAnyExpr(E, 0, false, true); } else { ErrorUnsupported(S, "statement"); } diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 9a9ca0576867..d87fbcdeb5d3 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -407,8 +407,10 @@ public: /// any type. The result is returned as an RValue struct. If this is an /// aggregate expression, the aggloc/agglocvolatile arguments indicate where /// the result should be returned. + /// + /// \param IgnoreResult - True if the resulting value isn't used. RValue EmitAnyExpr(const Expr *E, llvm::Value *AggLoc = 0, - bool isAggLocVolatile = false); + bool isAggLocVolatile = false, bool IgnoreResult = false); // EmitVAListRef - Emit a "reference" to a va_list; this is either the address // or the value of the expression, depending on how va_list is defined. @@ -741,7 +743,8 @@ public: /// EmitAggExpr - Emit the computation of the specified expression of /// aggregate type. The result is computed into DestPtr. Note that if /// DestPtr is null, the value of the aggregate expression is not needed. - void EmitAggExpr(const Expr *E, llvm::Value *DestPtr, bool VolatileDest); + void EmitAggExpr(const Expr *E, llvm::Value *DestPtr, bool VolatileDest, + bool IgnoreResult = false); /// EmitComplexExpr - Emit the computation of the specified expression of /// complex type, returning the result. diff --git a/clang/test/CodeGen/volatile.c b/clang/test/CodeGen/volatile.c index 9ee4de601cef..c89a72bfeff5 100644 --- a/clang/test/CodeGen/volatile.c +++ b/clang/test/CodeGen/volatile.c @@ -1,4 +1,6 @@ -// RUN: clang-cc -emit-llvm < %s | grep volatile | count 25 +// RUN: clang-cc -emit-llvm < %s -o %t && +// RUN: grep volatile %t | count 25 && +// RUN: grep memcpy %t | count 5 // The number 26 comes from the current codegen for volatile loads; // if this number changes, it's not necessarily something wrong, but @@ -85,4 +87,7 @@ void main() { ++vS; i+=S; i+=vS; + (void)vF2; + vF2 = vF2; + vF2 = vF2 = vF2; }