llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang-codegen Author: Lukacma <details> <summary>Changes</summary> This patch lowers fp atomic compound stmts into atomicrmw when not in strictfp environment as exception handling and status flags updates can be ignored. This should improve final assembly. Co-authored-by: Amina Chabane <amina.chabane@<!-- -->arm.com> --- Full diff: https://github.com/llvm/llvm-project/pull/216033.diff 2 Files Affected: - (modified) clang/lib/CodeGen/CGExprScalar.cpp (+18-7) - (added) clang/test/CodeGen/aarch64-lsfe-atomics.c (+269) ``````````diff diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 8783b43846434..106d39bc5a4e2 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -4089,6 +4089,7 @@ LValue ScalarExprEmitter::EmitCompoundAssignLValue( // Load/convert the LHS. LValue LHSLV = EmitCheckedLValue(E->getLHS(), CodeGenFunction::TCK_Store); + CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, OpInfo.FPFeatures); llvm::PHINode *atomicPHI = nullptr; if (const AtomicType *atomicTy = LHSTy->getAs<AtomicType>()) { // Type wrapped by _Atomic. @@ -4101,14 +4102,21 @@ LValue ScalarExprEmitter::EmitCompoundAssignLValue( // the loaded integer to double, performing FP arithmetics, and truncation // back as a single atomic operation. Integer promotion is still // semantically safe. - bool CanEmitAtomicRMW = + bool CanEmitIntegerRMW = !AtomicValueTy->isBooleanType() && AtomicValueTy->isIntegerType() && ResultTy->isIntegerType() && !(AtomicValueTy->isUnsignedIntegerType() && CGF.SanOpts.has(SanitizerKind::UnsignedIntegerOverflow)) && CGF.getLangOpts().getSignedOverflowBehavior() != LangOptions::SOB_Trapping; - if (CanEmitAtomicRMW) { + bool CanEmitFloatingRMW = false; + if (!Builder.getIsFPConstrained() && AtomicValueTy->isFloatingType() && + CGF.getContext().hasSameUnqualifiedType(AtomicValueTy, ResultTy)) { + llvm::Type *IRTy = CGF.ConvertType(AtomicValueTy); + uint64_t StoreBits = CGF.CGM.getDataLayout().getTypeStoreSizeInBits(IRTy); + CanEmitFloatingRMW = llvm::isPowerOf2_64(StoreBits); + } + if (CanEmitIntegerRMW || CanEmitFloatingRMW) { llvm::AtomicRMWInst::BinOp AtomicOp = llvm::AtomicRMWInst::BAD_BINOP; llvm::Instruction::BinaryOps Op; switch (OpInfo.Opcode) { @@ -4119,12 +4127,16 @@ LValue ScalarExprEmitter::EmitCompoundAssignLValue( case BO_ShrAssign: break; case BO_AddAssign: - AtomicOp = llvm::AtomicRMWInst::Add; - Op = llvm::Instruction::Add; + AtomicOp = CanEmitFloatingRMW ? llvm::AtomicRMWInst::FAdd + : llvm::AtomicRMWInst::Add; + Op = CanEmitFloatingRMW ? llvm::Instruction::FAdd + : llvm::Instruction::Add; break; case BO_SubAssign: - AtomicOp = llvm::AtomicRMWInst::Sub; - Op = llvm::Instruction::Sub; + AtomicOp = CanEmitFloatingRMW ? llvm::AtomicRMWInst::FSub + : llvm::AtomicRMWInst::Sub; + Op = CanEmitFloatingRMW ? llvm::Instruction::FSub + : llvm::Instruction::Sub; break; case BO_AndAssign: AtomicOp = llvm::AtomicRMWInst::And; @@ -4171,7 +4183,6 @@ LValue ScalarExprEmitter::EmitCompoundAssignLValue( else OpInfo.LHS = EmitLoadOfLValue(LHSLV, E->getExprLoc()); - CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, OpInfo.FPFeatures); SourceLocation Loc = E->getExprLoc(); if (!PromotionTypeLHS.isNull()) OpInfo.LHS = EmitScalarConversion(OpInfo.LHS, LHSTy, PromotionTypeLHS, diff --git a/clang/test/CodeGen/aarch64-lsfe-atomics.c b/clang/test/CodeGen/aarch64-lsfe-atomics.c new file mode 100644 index 0000000000000..df7422f856d57 --- /dev/null +++ b/clang/test/CodeGen/aarch64-lsfe-atomics.c @@ -0,0 +1,269 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6 +// RUN: %clang_cc1 %s -emit-llvm -o - -triple=aarch64-linux-gnu | FileCheck %s --check-prefix=CHECK-C +// RUN: %clang_cc1 -x c++ -std=c++11 %s -emit-llvm -o - -triple=aarch64-linux-gnu | FileCheck %s --check-prefix=CHECK-CPP + +_Atomic(float) f; +_Atomic(double) d; +_Atomic(__bf16) bf; +_Atomic(_Float16) h; + +// CHECK-C-LABEL: define dso_local void @test_float_add( +// CHECK-C-SAME: float noundef [[VAL:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-C-NEXT: [[ENTRY:.*:]] +// CHECK-C-NEXT: [[VAL_ADDR:%.*]] = alloca float, align 4 +// CHECK-C-NEXT: store float [[VAL]], ptr [[VAL_ADDR]], align 4 +// CHECK-C-NEXT: [[TMP0:%.*]] = load float, ptr [[VAL_ADDR]], align 4 +// CHECK-C-NEXT: [[TMP1:%.*]] = atomicrmw fadd ptr @f, float [[TMP0]] seq_cst, align 4 +// CHECK-C-NEXT: [[TMP2:%.*]] = fadd float [[TMP1]], [[TMP0]] +// CHECK-C-NEXT: ret void +// +// CHECK-CPP-LABEL: define dso_local void @_Z14test_float_addf( +// CHECK-CPP-SAME: float noundef [[VAL:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-CPP-NEXT: [[ENTRY:.*:]] +// CHECK-CPP-NEXT: [[VAL_ADDR:%.*]] = alloca float, align 4 +// CHECK-CPP-NEXT: store float [[VAL]], ptr [[VAL_ADDR]], align 4 +// CHECK-CPP-NEXT: [[TMP0:%.*]] = load float, ptr [[VAL_ADDR]], align 4 +// CHECK-CPP-NEXT: [[TMP1:%.*]] = atomicrmw fadd ptr @f, float [[TMP0]] seq_cst, align 4 +// CHECK-CPP-NEXT: [[TMP2:%.*]] = fadd float [[TMP1]], [[TMP0]] +// CHECK-CPP-NEXT: ret void +// +void test_float_add(float val) { + f += val; +} + +// CHECK-C-LABEL: define dso_local void @test_float_compound_add( +// CHECK-C-SAME: float [[VAL:%.*]]) #[[ATTR0]] { +// CHECK-C-NEXT: [[ENTRY:.*:]] +// CHECK-C-NEXT: [[VAL_ADDR:%.*]] = alloca float, align 4 +// CHECK-C-NEXT: store float [[VAL]], ptr [[VAL_ADDR]], align 4 +// CHECK-C-NEXT: [[ATOMIC_LOAD:%.*]] = load atomic float, ptr [[VAL_ADDR]] seq_cst, align 4 +// CHECK-C-NEXT: [[TMP0:%.*]] = atomicrmw fadd ptr @f, float [[ATOMIC_LOAD]] seq_cst, align 4 +// CHECK-C-NEXT: [[TMP1:%.*]] = fadd float [[TMP0]], [[ATOMIC_LOAD]] +// CHECK-C-NEXT: ret void +// +// CHECK-CPP-LABEL: define dso_local void @_Z23test_float_compound_addU7_Atomicf( +// CHECK-CPP-SAME: float [[VAL:%.*]]) #[[ATTR0]] { +// CHECK-CPP-NEXT: [[ENTRY:.*:]] +// CHECK-CPP-NEXT: [[VAL_ADDR:%.*]] = alloca float, align 4 +// CHECK-CPP-NEXT: store float [[VAL]], ptr [[VAL_ADDR]], align 4 +// CHECK-CPP-NEXT: [[ATOMIC_LOAD:%.*]] = load atomic float, ptr [[VAL_ADDR]] seq_cst, align 4 +// CHECK-CPP-NEXT: [[TMP0:%.*]] = atomicrmw fadd ptr @f, float [[ATOMIC_LOAD]] seq_cst, align 4 +// CHECK-CPP-NEXT: [[TMP1:%.*]] = fadd float [[TMP0]], [[ATOMIC_LOAD]] +// CHECK-CPP-NEXT: ret void +// +void test_float_compound_add(_Atomic(float) val){ + f += val; +} + +// CHECK-C-LABEL: define dso_local void @test_float_read_add( +// CHECK-C-SAME: float [[VAL:%.*]]) #[[ATTR0]] { +// CHECK-C-NEXT: [[ENTRY:.*:]] +// CHECK-C-NEXT: [[VAL_ADDR:%.*]] = alloca float, align 4 +// CHECK-C-NEXT: store float [[VAL]], ptr [[VAL_ADDR]], align 4 +// CHECK-C-NEXT: [[ATOMIC_LOAD:%.*]] = load atomic float, ptr @f seq_cst, align 4 +// CHECK-C-NEXT: [[ATOMIC_LOAD1:%.*]] = load atomic float, ptr [[VAL_ADDR]] seq_cst, align 4 +// CHECK-C-NEXT: [[ADD:%.*]] = fadd float [[ATOMIC_LOAD]], [[ATOMIC_LOAD1]] +// CHECK-C-NEXT: store atomic float [[ADD]], ptr @f seq_cst, align 4 +// CHECK-C-NEXT: ret void +// +// CHECK-CPP-LABEL: define dso_local void @_Z19test_float_read_addU7_Atomicf( +// CHECK-CPP-SAME: float [[VAL:%.*]]) #[[ATTR0]] { +// CHECK-CPP-NEXT: [[ENTRY:.*:]] +// CHECK-CPP-NEXT: [[VAL_ADDR:%.*]] = alloca float, align 4 +// CHECK-CPP-NEXT: store float [[VAL]], ptr [[VAL_ADDR]], align 4 +// CHECK-CPP-NEXT: [[ATOMIC_LOAD:%.*]] = load atomic float, ptr @f seq_cst, align 4 +// CHECK-CPP-NEXT: [[ATOMIC_LOAD1:%.*]] = load atomic float, ptr [[VAL_ADDR]] seq_cst, align 4 +// CHECK-CPP-NEXT: [[ADD:%.*]] = fadd float [[ATOMIC_LOAD]], [[ATOMIC_LOAD1]] +// CHECK-CPP-NEXT: store atomic float [[ADD]], ptr @f seq_cst, align 4 +// CHECK-CPP-NEXT: ret void +// +void test_float_read_add(_Atomic(float) val){ + f = f + val; +} + +// CHECK-C-LABEL: define dso_local void @test_double_add( +// CHECK-C-SAME: double noundef [[VAL:%.*]]) #[[ATTR0]] { +// CHECK-C-NEXT: [[ENTRY:.*:]] +// CHECK-C-NEXT: [[VAL_ADDR:%.*]] = alloca double, align 8 +// CHECK-C-NEXT: store double [[VAL]], ptr [[VAL_ADDR]], align 8 +// CHECK-C-NEXT: [[TMP0:%.*]] = load double, ptr [[VAL_ADDR]], align 8 +// CHECK-C-NEXT: [[TMP1:%.*]] = atomicrmw fadd ptr @d, double [[TMP0]] seq_cst, align 8 +// CHECK-C-NEXT: [[TMP2:%.*]] = fadd double [[TMP1]], [[TMP0]] +// CHECK-C-NEXT: ret void +// +// CHECK-CPP-LABEL: define dso_local void @_Z15test_double_addd( +// CHECK-CPP-SAME: double noundef [[VAL:%.*]]) #[[ATTR0]] { +// CHECK-CPP-NEXT: [[ENTRY:.*:]] +// CHECK-CPP-NEXT: [[VAL_ADDR:%.*]] = alloca double, align 8 +// CHECK-CPP-NEXT: store double [[VAL]], ptr [[VAL_ADDR]], align 8 +// CHECK-CPP-NEXT: [[TMP0:%.*]] = load double, ptr [[VAL_ADDR]], align 8 +// CHECK-CPP-NEXT: [[TMP1:%.*]] = atomicrmw fadd ptr @d, double [[TMP0]] seq_cst, align 8 +// CHECK-CPP-NEXT: [[TMP2:%.*]] = fadd double [[TMP1]], [[TMP0]] +// CHECK-CPP-NEXT: ret void +// +void test_double_add(double val) { + d += val; +} + +// CHECK-LLVM-LABEL: define dso_local void @test_bf16_add( +// CHECK-LLVM-SAME: bfloat noundef [[VAL:%.*]]) #[[ATTR0]] { +// CHECK-LLVM-NEXT: [[ENTRY:.*:]] +// CHECK-LLVM-NEXT: [[VAL_ADDR:%.*]] = alloca bfloat, align 2 +// CHECK-LLVM-NEXT: store bfloat [[VAL]], ptr [[VAL_ADDR]], align 2 +// CHECK-LLVM-NEXT: [[TMP0:%.*]] = load bfloat, ptr [[VAL_ADDR]], align 2 +// CHECK-LLVM-NEXT: [[EXT:%.*]] = fpext bfloat [[TMP0]] to float +// CHECK-LLVM-NEXT: [[CONV:%.*]] = fptrunc float [[EXT]] to bfloat +// CHECK-LLVM-NEXT: [[TMP1:%.*]] = atomicrmw fadd ptr @bf, bfloat [[CONV]] seq_cst, align 2 +// CHECK-LLVM-NEXT: [[TMP2:%.*]] = fadd bfloat [[TMP1]], [[CONV]] +// CHECK-LLVM-NEXT: ret void +// CHECK-C-LABEL: define dso_local void @test_bf16_add( +// CHECK-C-SAME: bfloat noundef [[VAL:%.*]]) #[[ATTR0]] { +// CHECK-C-NEXT: [[ENTRY:.*:]] +// CHECK-C-NEXT: [[VAL_ADDR:%.*]] = alloca bfloat, align 2 +// CHECK-C-NEXT: store bfloat [[VAL]], ptr [[VAL_ADDR]], align 2 +// CHECK-C-NEXT: [[TMP0:%.*]] = load bfloat, ptr [[VAL_ADDR]], align 2 +// CHECK-C-NEXT: [[EXT:%.*]] = fpext bfloat [[TMP0]] to float +// CHECK-C-NEXT: [[CONV:%.*]] = fptrunc float [[EXT]] to bfloat +// CHECK-C-NEXT: [[TMP1:%.*]] = atomicrmw fadd ptr @bf, bfloat [[CONV]] seq_cst, align 2 +// CHECK-C-NEXT: [[TMP2:%.*]] = fadd bfloat [[TMP1]], [[CONV]] +// CHECK-C-NEXT: ret void +// +// CHECK-CPP-LABEL: define dso_local void @_Z13test_bf16_addu6__bf16( +// CHECK-CPP-SAME: bfloat noundef [[VAL:%.*]]) #[[ATTR0]] { +// CHECK-CPP-NEXT: [[ENTRY:.*:]] +// CHECK-CPP-NEXT: [[VAL_ADDR:%.*]] = alloca bfloat, align 2 +// CHECK-CPP-NEXT: store bfloat [[VAL]], ptr [[VAL_ADDR]], align 2 +// CHECK-CPP-NEXT: [[TMP0:%.*]] = load bfloat, ptr [[VAL_ADDR]], align 2 +// CHECK-CPP-NEXT: [[EXT:%.*]] = fpext bfloat [[TMP0]] to float +// CHECK-CPP-NEXT: [[CONV:%.*]] = fptrunc float [[EXT]] to bfloat +// CHECK-CPP-NEXT: [[TMP1:%.*]] = atomicrmw fadd ptr @bf, bfloat [[CONV]] seq_cst, align 2 +// CHECK-CPP-NEXT: [[TMP2:%.*]] = fadd bfloat [[TMP1]], [[CONV]] +// CHECK-CPP-NEXT: ret void +// +void test_bf16_add(__bf16 val){ + bf += val; +} + +// CHECK-C-LABEL: define dso_local void @test_f16_add( +// CHECK-C-SAME: half noundef [[VAL:%.*]]) #[[ATTR0]] { +// CHECK-C-NEXT: [[ENTRY:.*:]] +// CHECK-C-NEXT: [[VAL_ADDR:%.*]] = alloca half, align 2 +// CHECK-C-NEXT: store half [[VAL]], ptr [[VAL_ADDR]], align 2 +// CHECK-C-NEXT: [[TMP0:%.*]] = load half, ptr [[VAL_ADDR]], align 2 +// CHECK-C-NEXT: [[TMP1:%.*]] = atomicrmw fadd ptr @h, half [[TMP0]] seq_cst, align 2 +// CHECK-C-NEXT: [[TMP2:%.*]] = fadd half [[TMP1]], [[TMP0]] +// CHECK-C-NEXT: ret void +// +// CHECK-CPP-LABEL: define dso_local void @_Z12test_f16_addDF16_( +// CHECK-CPP-SAME: half noundef [[VAL:%.*]]) #[[ATTR0]] { +// CHECK-CPP-NEXT: [[ENTRY:.*:]] +// CHECK-CPP-NEXT: [[VAL_ADDR:%.*]] = alloca half, align 2 +// CHECK-CPP-NEXT: store half [[VAL]], ptr [[VAL_ADDR]], align 2 +// CHECK-CPP-NEXT: [[TMP0:%.*]] = load half, ptr [[VAL_ADDR]], align 2 +// CHECK-CPP-NEXT: [[TMP1:%.*]] = atomicrmw fadd ptr @h, half [[TMP0]] seq_cst, align 2 +// CHECK-CPP-NEXT: [[TMP2:%.*]] = fadd half [[TMP1]], [[TMP0]] +// CHECK-CPP-NEXT: ret void +// +void test_f16_add(_Float16 val){ + h += val; +} + +// CHECK-C-LABEL: define dso_local void @test_float_sub( +// CHECK-C-SAME: float noundef [[VAL:%.*]]) #[[ATTR0]] { +// CHECK-C-NEXT: [[ENTRY:.*:]] +// CHECK-C-NEXT: [[VAL_ADDR:%.*]] = alloca float, align 4 +// CHECK-C-NEXT: store float [[VAL]], ptr [[VAL_ADDR]], align 4 +// CHECK-C-NEXT: [[TMP0:%.*]] = load float, ptr [[VAL_ADDR]], align 4 +// CHECK-C-NEXT: [[TMP1:%.*]] = atomicrmw fsub ptr @f, float [[TMP0]] seq_cst, align 4 +// CHECK-C-NEXT: [[TMP2:%.*]] = fsub float [[TMP1]], [[TMP0]] +// CHECK-C-NEXT: ret void +// +// CHECK-CPP-LABEL: define dso_local void @_Z14test_float_subf( +// CHECK-CPP-SAME: float noundef [[VAL:%.*]]) #[[ATTR0]] { +// CHECK-CPP-NEXT: [[ENTRY:.*:]] +// CHECK-CPP-NEXT: [[VAL_ADDR:%.*]] = alloca float, align 4 +// CHECK-CPP-NEXT: store float [[VAL]], ptr [[VAL_ADDR]], align 4 +// CHECK-CPP-NEXT: [[TMP0:%.*]] = load float, ptr [[VAL_ADDR]], align 4 +// CHECK-CPP-NEXT: [[TMP1:%.*]] = atomicrmw fsub ptr @f, float [[TMP0]] seq_cst, align 4 +// CHECK-CPP-NEXT: [[TMP2:%.*]] = fsub float [[TMP1]], [[TMP0]] +// CHECK-CPP-NEXT: ret void +// +void test_float_sub(float val) { + f -= val; +} + +// CHECK-C-LABEL: define dso_local void @test_double_sub( +// CHECK-C-SAME: double noundef [[VAL:%.*]]) #[[ATTR0]] { +// CHECK-C-NEXT: [[ENTRY:.*:]] +// CHECK-C-NEXT: [[VAL_ADDR:%.*]] = alloca double, align 8 +// CHECK-C-NEXT: store double [[VAL]], ptr [[VAL_ADDR]], align 8 +// CHECK-C-NEXT: [[TMP0:%.*]] = load double, ptr [[VAL_ADDR]], align 8 +// CHECK-C-NEXT: [[TMP1:%.*]] = atomicrmw fsub ptr @d, double [[TMP0]] seq_cst, align 8 +// CHECK-C-NEXT: [[TMP2:%.*]] = fsub double [[TMP1]], [[TMP0]] +// CHECK-C-NEXT: ret void +// +// CHECK-CPP-LABEL: define dso_local void @_Z15test_double_subd( +// CHECK-CPP-SAME: double noundef [[VAL:%.*]]) #[[ATTR0]] { +// CHECK-CPP-NEXT: [[ENTRY:.*:]] +// CHECK-CPP-NEXT: [[VAL_ADDR:%.*]] = alloca double, align 8 +// CHECK-CPP-NEXT: store double [[VAL]], ptr [[VAL_ADDR]], align 8 +// CHECK-CPP-NEXT: [[TMP0:%.*]] = load double, ptr [[VAL_ADDR]], align 8 +// CHECK-CPP-NEXT: [[TMP1:%.*]] = atomicrmw fsub ptr @d, double [[TMP0]] seq_cst, align 8 +// CHECK-CPP-NEXT: [[TMP2:%.*]] = fsub double [[TMP1]], [[TMP0]] +// CHECK-CPP-NEXT: ret void +// +void test_double_sub(double val){ + d -= val; +} + +// CHECK-C-LABEL: define dso_local void @test_bf16_sub( +// CHECK-C-SAME: bfloat noundef [[VAL:%.*]]) #[[ATTR0]] { +// CHECK-C-NEXT: [[ENTRY:.*:]] +// CHECK-C-NEXT: [[VAL_ADDR:%.*]] = alloca bfloat, align 2 +// CHECK-C-NEXT: store bfloat [[VAL]], ptr [[VAL_ADDR]], align 2 +// CHECK-C-NEXT: [[TMP0:%.*]] = load bfloat, ptr [[VAL_ADDR]], align 2 +// CHECK-C-NEXT: [[EXT:%.*]] = fpext bfloat [[TMP0]] to float +// CHECK-C-NEXT: [[CONV:%.*]] = fptrunc float [[EXT]] to bfloat +// CHECK-C-NEXT: [[TMP1:%.*]] = atomicrmw fsub ptr @bf, bfloat [[CONV]] seq_cst, align 2 +// CHECK-C-NEXT: [[TMP2:%.*]] = fsub bfloat [[TMP1]], [[CONV]] +// CHECK-C-NEXT: ret void +// +// CHECK-CPP-LABEL: define dso_local void @_Z13test_bf16_subu6__bf16( +// CHECK-CPP-SAME: bfloat noundef [[VAL:%.*]]) #[[ATTR0]] { +// CHECK-CPP-NEXT: [[ENTRY:.*:]] +// CHECK-CPP-NEXT: [[VAL_ADDR:%.*]] = alloca bfloat, align 2 +// CHECK-CPP-NEXT: store bfloat [[VAL]], ptr [[VAL_ADDR]], align 2 +// CHECK-CPP-NEXT: [[TMP0:%.*]] = load bfloat, ptr [[VAL_ADDR]], align 2 +// CHECK-CPP-NEXT: [[EXT:%.*]] = fpext bfloat [[TMP0]] to float +// CHECK-CPP-NEXT: [[CONV:%.*]] = fptrunc float [[EXT]] to bfloat +// CHECK-CPP-NEXT: [[TMP1:%.*]] = atomicrmw fsub ptr @bf, bfloat [[CONV]] seq_cst, align 2 +// CHECK-CPP-NEXT: [[TMP2:%.*]] = fsub bfloat [[TMP1]], [[CONV]] +// CHECK-CPP-NEXT: ret void +// +void test_bf16_sub(__bf16 val){ + bf -= val; +} + +// CHECK-C-LABEL: define dso_local void @test_f16_sub( +// CHECK-C-SAME: half noundef [[VAL:%.*]]) #[[ATTR0]] { +// CHECK-C-NEXT: [[ENTRY:.*:]] +// CHECK-C-NEXT: [[VAL_ADDR:%.*]] = alloca half, align 2 +// CHECK-C-NEXT: store half [[VAL]], ptr [[VAL_ADDR]], align 2 +// CHECK-C-NEXT: [[TMP0:%.*]] = load half, ptr [[VAL_ADDR]], align 2 +// CHECK-C-NEXT: [[TMP1:%.*]] = atomicrmw fsub ptr @h, half [[TMP0]] seq_cst, align 2 +// CHECK-C-NEXT: [[TMP2:%.*]] = fsub half [[TMP1]], [[TMP0]] +// CHECK-C-NEXT: ret void +// +// CHECK-CPP-LABEL: define dso_local void @_Z12test_f16_subDF16_( +// CHECK-CPP-SAME: half noundef [[VAL:%.*]]) #[[ATTR0]] { +// CHECK-CPP-NEXT: [[ENTRY:.*:]] +// CHECK-CPP-NEXT: [[VAL_ADDR:%.*]] = alloca half, align 2 +// CHECK-CPP-NEXT: store half [[VAL]], ptr [[VAL_ADDR]], align 2 +// CHECK-CPP-NEXT: [[TMP0:%.*]] = load half, ptr [[VAL_ADDR]], align 2 +// CHECK-CPP-NEXT: [[TMP1:%.*]] = atomicrmw fsub ptr @h, half [[TMP0]] seq_cst, align 2 +// CHECK-CPP-NEXT: [[TMP2:%.*]] = fsub half [[TMP1]], [[TMP0]] +// CHECK-CPP-NEXT: ret void +// +void test_f16_sub(_Float16 val){ + h -= val; +} `````````` </details> https://github.com/llvm/llvm-project/pull/216033 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
