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 &lt;amina.chabane@<!-- -->arm.com&gt;

---
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

Reply via email to