llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang-codegen @llvm/pr-subscribers-clang Author: Antonio Frighetto (antoniofrighetto) <details> <summary>Changes</summary> Per C11 6.5.16.2p1, when the left operand of operator `+=` has atomic type, the right shall have arithmetic type. Do not try the `atomicrmw` fast-path when FP conversion, arithmetic and truncation are required, as a single atomic operation may not correctly capture the combined semantics. Fixes: https://github.com/llvm/llvm-project/issues/208997. --- Full diff: https://github.com/llvm/llvm-project/pull/209114.diff 2 Files Affected: - (modified) clang/lib/CodeGen/CGExprScalar.cpp (+17-5) - (modified) clang/test/CodeGen/c11atomics.c (+19) ``````````diff diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 6f7b7e7d6840e..81016d3d5d308 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -4091,12 +4091,24 @@ LValue ScalarExprEmitter::EmitCompoundAssignLValue( llvm::PHINode *atomicPHI = nullptr; if (const AtomicType *atomicTy = LHSTy->getAs<AtomicType>()) { - QualType type = atomicTy->getValueType(); - if (!type->isBooleanType() && type->isIntegerType() && - !(type->isUnsignedIntegerType() && + // Type wrapped by _Atomic. + QualType AtomicValueTy = atomicTy->getValueType(); + // Type resulting from FP conversion / integer promotion of the compound + // assignment operands. + QualType ResultTy = E->getComputationResultType(); + // Do not try the atomicrmw op fast-path when the compound assignment may + // involve FP conversions, as the correct semantics would require promoting + // the loaded integer to double, performing FP arithmetics, and truncation + // back as a single atomic operation. Integer promotion is still + // semantically safe. + bool CanEmitAtomicRMW = + !AtomicValueTy->isBooleanType() && AtomicValueTy->isIntegerType() && + ResultTy->isIntegerType() && + !(AtomicValueTy->isUnsignedIntegerType() && CGF.SanOpts.has(SanitizerKind::UnsignedIntegerOverflow)) && CGF.getLangOpts().getSignedOverflowBehavior() != - LangOptions::SOB_Trapping) { + LangOptions::SOB_Trapping; + if (CanEmitAtomicRMW) { llvm::AtomicRMWInst::BinOp AtomicOp = llvm::AtomicRMWInst::BAD_BINOP; llvm::Instruction::BinaryOps Op; switch (OpInfo.Opcode) { @@ -4149,7 +4161,7 @@ LValue ScalarExprEmitter::EmitCompoundAssignLValue( llvm::BasicBlock *startBB = Builder.GetInsertBlock(); llvm::BasicBlock *opBB = CGF.createBasicBlock("atomic_op", CGF.CurFn); OpInfo.LHS = EmitLoadOfLValue(LHSLV, E->getExprLoc()); - OpInfo.LHS = CGF.EmitToMemory(OpInfo.LHS, type); + OpInfo.LHS = CGF.EmitToMemory(OpInfo.LHS, AtomicValueTy); Builder.CreateBr(opBB); Builder.SetInsertPoint(opBB); atomicPHI = Builder.CreatePHI(OpInfo.LHS->getType(), 2); diff --git a/clang/test/CodeGen/c11atomics.c b/clang/test/CodeGen/c11atomics.c index 6a66cd8cbae89..9f17c3b1c0bf9 100644 --- a/clang/test/CodeGen/c11atomics.c +++ b/clang/test/CodeGen/c11atomics.c @@ -152,6 +152,25 @@ void testandeq(void) l &= 42; s &= 42; } +// CHECK: testaddeq_fp +void testaddeq_fp(void) +{ + // CHECK: [[CONV:%.*]] = uitofp i32 [[TMP0:%.*]] to double + // CHECK-NEXT: [[FADD:%.*]] = fadd double [[CONV]], -5.000000e-01 + // CHECK-NEXT: [[CONV1:%.*]] = fptosi double [[FADD]] to i32 + // CHECK-NEXT: store i32 [[TMP0]], ptr {{%.*}}, align 4 + // CHECK-NEXT: store i32 [[CONV1]], ptr {{%.*}}, align 4 + // CHECK-NEXT: call arm_aapcscc zeroext i1 @__atomic_compare_exchange(i32 noundef 4, ptr noundef @i, ptr noundef {{%.*}}, ptr noundef {{%.*}}, i32 noundef 5, i32 noundef 5) + i += -0.5; + + // CHECK: [[CONV2:%.*]] = uitofp i32 [[TMP1:%.*]] to double + // CHECK-NEXT: [[FADD1:%.*]] = fadd double [[CONV2]], -2.500000e+00 + // CHECK-NEXT: [[CONV3:%.*]] = fptosi double [[FADD1]] to i32 + // CHECK-NEXT: store i32 [[TMP1]], ptr {{%.*}}, align 4 + // CHECK-NEXT: store i32 [[CONV3]], ptr {{%.*}}, align 4 + // CHECK-NEXT: call arm_aapcscc zeroext i1 @__atomic_compare_exchange(i32 noundef 4, ptr noundef @i, ptr noundef {{%.*}}, ptr noundef {{%.*}}, i32 noundef 5, i32 noundef 5) + i += -2.5; +} // CHECK-LABEL: define{{.*}} arm_aapcscc void @testFloat(ptr void testFloat(_Atomic(float) *fp) { `````````` </details> https://github.com/llvm/llvm-project/pull/209114 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
