diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -170,6 +170,21 @@ return V; } +static llvm::Value *CheckAtomicAlignment(CodeGenFunction &CGF, + const CallExpr *E) { + ASTContext &Ctx = CGF.getContext(); + Address Ptr = CGF.EmitPointerWithAlignment(E->getArg(0)); + unsigned Bytes = Ptr.getElementType()->isPointerTy() + ? Ctx.getTypeSizeInChars(Ctx.VoidPtrTy).getQuantity() + : Ptr.getElementType()->getScalarSizeInBits() / 8; + unsigned Align = Ptr.getAlignment().getQuantity(); + if (Align % Bytes != 0) { + DiagnosticsEngine &Diags = CGF.CGM.getDiags(); + Diags.Report(E->getBeginLoc(), diag::warn_sync_op_misaligned); + } + return Ptr.getPointer(); +} + /// Utility to insert an atomic instruction based on Intrinsic::ID /// and the expression node. static Value *MakeBinaryAtomicValue( @@ -182,7 +197,7 @@ E->getArg(0)->getType()->getPointeeType())); assert(CGF.getContext().hasSameUnqualifiedType(T, E->getArg(1)->getType())); - llvm::Value *DestPtr = CGF.EmitScalarExpr(E->getArg(0)); + llvm::Value *DestPtr = CheckAtomicAlignment(CGF, E); unsigned AddrSpace = DestPtr->getType()->getPointerAddressSpace(); llvm::IntegerType *IntType = @@ -224,23 +239,9 @@ return CGF.EmitLoadOfScalar(LV, E->getExprLoc()); } -static void CheckAtomicAlignment(CodeGenFunction &CGF, const CallExpr *E) { - ASTContext &Ctx = CGF.getContext(); - Address Ptr = CGF.EmitPointerWithAlignment(E->getArg(0)); - unsigned Bytes = Ptr.getElementType()->isPointerTy() - ? Ctx.getTypeSizeInChars(Ctx.VoidPtrTy).getQuantity() - : Ptr.getElementType()->getScalarSizeInBits() / 8; - unsigned Align = Ptr.getAlignment().getQuantity(); - if (Align % Bytes != 0) { - DiagnosticsEngine &Diags = CGF.CGM.getDiags(); - Diags.Report(E->getBeginLoc(), diag::warn_sync_op_misaligned); - } -} - static RValue EmitBinaryAtomic(CodeGenFunction &CGF, llvm::AtomicRMWInst::BinOp Kind, const CallExpr *E) { - CheckAtomicAlignment(CGF, E); return RValue::get(MakeBinaryAtomicValue(CGF, Kind, E)); } @@ -252,14 +253,13 @@ const CallExpr *E, Instruction::BinaryOps Op, bool Invert = false) { - CheckAtomicAlignment(CGF, E); QualType T = E->getType(); assert(E->getArg(0)->getType()->isPointerType()); assert(CGF.getContext().hasSameUnqualifiedType(T, E->getArg(0)->getType()->getPointeeType())); assert(CGF.getContext().hasSameUnqualifiedType(T, E->getArg(1)->getType())); - llvm::Value *DestPtr = CGF.EmitScalarExpr(E->getArg(0)); + llvm::Value *DestPtr = CheckAtomicAlignment(CGF, E); unsigned AddrSpace = DestPtr->getType()->getPointerAddressSpace(); llvm::IntegerType *IntType = @@ -300,9 +300,8 @@ /// invoke the function EmitAtomicCmpXchgForMSIntrin. static Value *MakeAtomicCmpXchgValue(CodeGenFunction &CGF, const CallExpr *E, bool ReturnBool) { - CheckAtomicAlignment(CGF, E); QualType T = ReturnBool ? E->getArg(1)->getType() : E->getType(); - llvm::Value *DestPtr = CGF.EmitScalarExpr(E->getArg(0)); + llvm::Value *DestPtr = CheckAtomicAlignment(CGF, E); unsigned AddrSpace = DestPtr->getType()->getPointerAddressSpace(); llvm::IntegerType *IntType = llvm::IntegerType::get( @@ -4045,8 +4044,7 @@ case Builtin::BI__sync_lock_release_4: case Builtin::BI__sync_lock_release_8: case Builtin::BI__sync_lock_release_16: { - CheckAtomicAlignment(*this, E); - Value *Ptr = EmitScalarExpr(E->getArg(0)); + Value *Ptr = CheckAtomicAlignment(*this, E); QualType ElTy = E->getArg(0)->getType()->getPointeeType(); CharUnits StoreSize = getContext().getTypeSizeInChars(ElTy); llvm::Type *ITy = llvm::IntegerType::get(getLLVMContext(), diff --git a/clang/test/CodeGen/SystemZ/sync-builtins-i128-16Al.c b/clang/test/CodeGen/SystemZ/sync-builtins-i128-16Al.c --- a/clang/test/CodeGen/SystemZ/sync-builtins-i128-16Al.c +++ b/clang/test/CodeGen/SystemZ/sync-builtins-i128-16Al.c @@ -204,3 +204,16 @@ __int128 f17() { return __sync_swap(&Ptr, Val); } + +// Test that a statement expression compiles. +// CHECK-LABEL: @f18( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[T_ADDR:%.*]] = alloca i128, align 8 +// CHECK-NEXT: [[T:%.*]] = load i128, ptr [[TMP0:%.*]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: store i128 [[T]], ptr [[T_ADDR]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP1:%.*]] = cmpxchg ptr [[T_ADDR]], i128 [[T]], i128 [[T]] seq_cst seq_cst, align 16 +// CHECK-NEXT: ret void +// +void f18(__int128 t) { + __sync_bool_compare_and_swap(({int x = 1; &t;}), t, t); +}