https://github.com/Luhaocong updated 
https://github.com/llvm/llvm-project/pull/193215

>From 47f0b2208cce7cb01b46bb071fcc53628aa810e1 Mon Sep 17 00:00:00 2001
From: Haocong Lu <[email protected]>
Date: Sat, 5 Sep 2026 13:25:08 +0800
Subject: [PATCH] [CIR] Upstream missing support for floating point unary
 operator

- Add Support for `__bf16/Float16/bfloat16/float128` scalar
  pre/post increment and decrement.
- Add support for float vector increment and decrement.
- Add test case for `__bf16/Float16/bfloat16/double/long double/float128`
  unary operator with target `x86_64`.
- Add test case for interger/float vector increment and decrement
  with target `powerpc64le + altivec`.
---
 clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp    |  72 +-
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp |   5 +-
 clang/lib/CodeGen/CGExprScalar.cpp            |  15 +-
 .../CIR/CodeGen/unary-inc-dec-unsupport.cpp   |  11 +
 .../test/CIR/CodeGen/unary-inc-dec-vector.cpp | 153 ++++
 clang/test/CIR/CodeGen/unary.cpp              | 695 +++++++++++++++++-
 6 files changed, 889 insertions(+), 62 deletions(-)
 create mode 100644 clang/test/CIR/CodeGen/unary-inc-dec-unsupport.cpp
 create mode 100644 clang/test/CIR/CodeGen/unary-inc-dec-vector.cpp

diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index f7a39a9b4a8c9..55c7fe8fb974e 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -682,7 +682,7 @@ class ScalarExprEmitter : public 
StmtVisitor<ScalarExprEmitter, mlir::Value> {
         value = emitIncDecConsiderOverflowBehavior(e, value);
       } else {
         // NOTE(CIR): clang calls CreateAdd but folds this to a unary op
-        value = emitIncOrDec(e, input, /*nsw=*/false);
+        value = emitIntIncOrDec(e, input, /*nsw=*/false);
       }
     } else if (const PointerType *ptr = type->getAs<PointerType>()) {
       QualType type = ptr->getPointeeType();
@@ -704,32 +704,14 @@ class ScalarExprEmitter : public 
StmtVisitor<ScalarExprEmitter, mlir::Value> {
       }
     } else if (type->isVectorType()) {
       if (type->hasIntegerRepresentation()) {
-        value = emitIncOrDec(e, input, /*nsw=*/false);
+        value = emitIntIncOrDec(e, input, /*nsw=*/false);
       } else {
-        cgf.cgm.errorNYI(e->getSourceRange(), "Unary inc/dec vector of float");
-        return {};
+        CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, e);
+        value = emitFloatIncOrDec(e, input);
       }
     } else if (type->isRealFloatingType()) {
       CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, e);
-
-      if (type->isHalfType() &&
-          !cgf.getContext().getLangOpts().NativeHalfType) {
-        cgf.cgm.errorNYI(e->getSourceRange(), "Unary inc/dec half");
-        return {};
-      }
-
-      if (mlir::isa<cir::SingleType, cir::DoubleType, cir::LongDoubleType>(
-              value.getType())) {
-        mlir::Location loc = cgf.getLoc(e->getExprLoc());
-        auto fpType = mlir::cast<cir::FPTypeInterface>(value.getType());
-        mlir::Value amount = builder.getConstFP(
-            loc, value.getType(), llvm::APFloat(fpType.getFloatSemantics(), 
1));
-        value = e->isIncrementOp() ? builder.createFAdd(loc, value, amount)
-                                   : builder.createFSub(loc, value, amount);
-      } else {
-        cgf.cgm.errorNYI(e->getSourceRange(), "Unary inc/dec other fp type");
-        return {};
-      }
+      value = emitFloatIncOrDec(e, input);
     } else if (type->isFixedPointType()) {
       value = emitFixedPointIncDec(e, value, type);
     } else {
@@ -756,13 +738,13 @@ class ScalarExprEmitter : public 
StmtVisitor<ScalarExprEmitter, mlir::Value> {
                                                  mlir::Value inVal) {
     switch (cgf.getLangOpts().getSignedOverflowBehavior()) {
     case LangOptions::SOB_Defined:
-      return emitIncOrDec(e, inVal, /*nsw=*/false);
+      return emitIntIncOrDec(e, inVal, /*nsw=*/false);
     case LangOptions::SOB_Undefined:
       assert(!cir::MissingFeatures::sanitizers());
-      return emitIncOrDec(e, inVal, /*nsw=*/true);
+      return emitIntIncOrDec(e, inVal, /*nsw=*/true);
     case LangOptions::SOB_Trapping:
       if (!e->canOverflow())
-        return emitIncOrDec(e, inVal, /*nsw=*/true);
+        return emitIntIncOrDec(e, inVal, /*nsw=*/true);
       cgf.cgm.errorNYI(e->getSourceRange(), "inc/def overflow SOB_Trapping");
       return {};
     }
@@ -828,14 +810,48 @@ class ScalarExprEmitter : public 
StmtVisitor<ScalarExprEmitter, mlir::Value> {
     return builder.createOrFold<cir::MinusOp>(loc, operand, nsw);
   }
 
-  mlir::Value emitIncOrDec(const UnaryOperator *e, mlir::Value input,
-                           bool nsw = false) {
+  mlir::Value emitIntIncOrDec(const UnaryOperator *e, mlir::Value input,
+                              bool nsw = false) {
     mlir::Location loc = cgf.getLoc(e->getSourceRange().getBegin());
     return e->isIncrementOp()
                ? builder.createOrFold<cir::IncOp>(loc, input, nsw)
                : builder.createOrFold<cir::DecOp>(loc, input, nsw);
   }
 
+  mlir::Value emitFloatIncOrDec(const UnaryOperator *e, mlir::Value input) {
+    assert(cir::isFPOrVectorOfFPType(input.getType()) &&
+           "Expect floating-point operand");
+    mlir::Location loc = cgf.getLoc(e->getSourceRange().getBegin());
+
+    if (auto vecType = mlir::dyn_cast<cir::VectorType>(input.getType())) {
+      mlir::Type fpScalarType = vecType.getElementType();
+      auto fpInterface = mlir::cast<cir::FPTypeInterface>(fpScalarType);
+      mlir::Value amount = builder.getConstFP(
+          loc, fpScalarType, llvm::APFloat(fpInterface.getFloatSemantics(), 
1));
+      amount = cir::VecSplatOp::create(builder, loc, vecType, amount);
+      return e->isIncrementOp() ? builder.createFAdd(loc, input, amount)
+                                : builder.createFSub(loc, input, amount);
+    } else {
+      QualType type = e->getSubExpr()->getType();
+      // Another special case: half FP increment should be done via float.
+      if (type->isHalfType() && !cgf.getContext().getLangOpts().NativeHalfType)
+        input = builder.createFloatingCast(input, builder.getSingleTy());
+
+      auto fpInterface = mlir::cast<cir::FPTypeInterface>(input.getType());
+      mlir::Value amount =
+          builder.getConstFP(loc, input.getType(),
+                             llvm::APFloat(fpInterface.getFloatSemantics(), 
1));
+      mlir::Value output = e->isIncrementOp()
+                               ? builder.createFAdd(loc, input, amount)
+                               : builder.createFSub(loc, input, amount);
+
+      if (type->isHalfType() && !cgf.getContext().getLangOpts().NativeHalfType)
+        output = builder.createFloatingCast(output, builder.getFp16Ty());
+
+      return output;
+    }
+  }
+
   mlir::Value VisitUnaryNot(const UnaryOperator *e) {
     ignoreResultAssign = false;
     mlir::Value op = Visit(e->getSubExpr());
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 6f7509c363fd3..bd1ace8be7563 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -3201,8 +3201,9 @@ lowerIncDecOp(CIROp op, typename CIROp::Adaptor adaptor,
   auto maybeNSW = nswFlag(op.getNoSignedWrap());
   mlir::LLVM::ConstantOp one;
   if (mlir::isa<cir::VectorType>(op.getType())) {
-    mlir::DenseIntElementsAttr oneVec = mlir::DenseIntElementsAttr::get(
-        mlir::cast<mlir::ShapedType>(llvmType), 1);
+    mlir::ShapedType shapedTy = mlir::cast<mlir::ShapedType>(llvmType);
+    mlir::APInt oneAP(shapedTy.getElementTypeBitWidth(), 1);
+    auto oneVec = mlir::DenseElementsAttr::get(shapedTy, {oneAP});
     one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, oneVec);
   } else {
     one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp 
b/clang/lib/CodeGen/CGExprScalar.cpp
index 8a1dd776118f5..0ceaeef3da4b4 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -3557,12 +3557,9 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const 
UnaryOperator *E, LValue LV,
     llvm::Value *amt;
     CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, E);
 
-    if (type->isHalfType() && !CGF.getContext().getLangOpts().NativeHalfType) {
-      // Another special case: half FP increment should be done via float. If
-      // the input isn't already half, it may be i16.
-      Value *bitcast = Builder.CreateBitCast(input, CGF.CGM.HalfTy);
-      value = Builder.CreateFPExt(bitcast, CGF.CGM.FloatTy, "incdec.conv");
-    }
+    // Another special case: half FP increment should be done via float.
+    if (type->isHalfType() && !CGF.getContext().getLangOpts().NativeHalfType)
+      value = Builder.CreateFPExt(value, CGF.CGM.FloatTy, "incdec.conv");
 
     if (value->getType()->isFloatTy())
       amt = llvm::ConstantFP::get(VMContext,
@@ -3593,12 +3590,10 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const 
UnaryOperator *E, LValue LV,
     }
     value = Builder.CreateFAdd(value, amt, isInc ? "inc" : "dec");
 
-    if (type->isHalfType() && !CGF.getContext().getLangOpts().NativeHalfType) {
+    if (type->isHalfType() && !CGF.getContext().getLangOpts().NativeHalfType)
       value = Builder.CreateFPTrunc(value, CGF.CGM.HalfTy, "incdec.conv");
-      value = Builder.CreateBitCast(value, input->getType());
-    }
 
-  // Fixed-point types.
+    // Fixed-point types.
   } else if (type->isFixedPointType()) {
     // Fixed-point types are tricky. In some cases, it isn't possible to
     // represent a 1 or a -1 in the type at all. Piggyback off of
diff --git a/clang/test/CIR/CodeGen/unary-inc-dec-unsupport.cpp 
b/clang/test/CIR/CodeGen/unary-inc-dec-unsupport.cpp
new file mode 100644
index 0000000000000..58cf166eee2b9
--- /dev/null
+++ b/clang/test/CIR/CodeGen/unary-inc-dec-unsupport.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -triple powerpc64le -fclangir -emit-cir -verify %s -o -
+
+// PPC fp128 (__ibm128) unary inc/dec is not yet supported, drop the errorNYI
+// and turn this into a regular test.
+
+__ibm128 g; // expected-error@*:* {{ClangIR code gen Not Yet Implemented: 
processing of built-in type: '__ibm128'}}
+
+void test_pre_inc() { ++g; }  
+void test_pre_dec() { --g; }
+void test_post_inc() { g++; }
+void test_post_dec() { g--; }
diff --git a/clang/test/CIR/CodeGen/unary-inc-dec-vector.cpp 
b/clang/test/CIR/CodeGen/unary-inc-dec-vector.cpp
new file mode 100644
index 0000000000000..5b5bf72af369d
--- /dev/null
+++ b/clang/test/CIR/CodeGen/unary-inc-dec-vector.cpp
@@ -0,0 +1,153 @@
+// RUN: %clang_cc1 -triple powerpc64le -target-feature +altivec 
-Wno-unused-value -fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
+// RUN: %clang_cc1 -triple powerpc64le -target-feature +altivec 
-Wno-unused-value -fclangir -emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM
+// RUN: %clang_cc1 -triple powerpc64le -target-feature +altivec 
-Wno-unused-value -emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
+
+// Unary inc/dec on vector types, covering the CIRGenExprScalar.cpp vector
+// branch:
+//   * integer vectors go through emitIntIncOrDec -> cir.inc/cir.dec
+//   * float vectors go through emitFloatIncOrDec -> cir.fadd/cir.fsub
+
+typedef int vi4 __attribute__((vector_size(16)));
+typedef unsigned uvi4 __attribute__((vector_size(16)));
+typedef short vsh8 __attribute__((vector_size(16)));
+typedef float vf4 __attribute__((vector_size(16)));
+typedef double vd2 __attribute__((vector_size(16)));
+
+void vecIntIncDec(vi4 a) {
+  ++a;
+  --a;
+  a++;
+  a--;
+}
+// CIR-LABEL: @_Z12vecIntIncDecDv4_i
+// CIR:  cir.inc %{{.+}} : !cir.vector<4 x !s32i>
+// CIR:  cir.dec %{{.+}} : !cir.vector<4 x !s32i>
+// CIR:  cir.inc %{{.+}} : !cir.vector<4 x !s32i>
+// CIR:  cir.dec %{{.+}} : !cir.vector<4 x !s32i>
+
+// LLVM-LABEL: @_Z12vecIntIncDecDv4_i
+// LLVM: add <4 x i32> %{{.+}}, splat (i32 1)
+// LLVM: sub <4 x i32> %{{.+}}, splat (i32 1)
+// LLVM: add <4 x i32> %{{.+}}, splat (i32 1)
+// LLVM: sub <4 x i32> %{{.+}}, splat (i32 1)
+
+// OGCG-LABEL: @_Z12vecIntIncDecDv4_i
+// OGCG: add <4 x i32> %{{.+}}, splat (i32 1)
+// OGCG: add <4 x i32> %{{.+}}, splat (i32 -1)
+// OGCG: add <4 x i32> %{{.+}}, splat (i32 1)
+// OGCG: add <4 x i32> %{{.+}}, splat (i32 -1)
+
+void vecUIntIncDec(uvi4 b) {
+  ++b;
+  --b;
+  b++;
+  b--;
+}
+// CIR-LABEL: @_Z13vecUIntIncDecDv4_j
+// CIR:  cir.inc %{{.+}} : !cir.vector<4 x !u32i>
+// CIR:  cir.dec %{{.+}} : !cir.vector<4 x !u32i>
+// CIR:  cir.inc %{{.+}} : !cir.vector<4 x !u32i>
+// CIR:  cir.dec %{{.+}} : !cir.vector<4 x !u32i>
+
+// LLVM-LABEL: @_Z13vecUIntIncDecDv4_j
+// LLVM: add <4 x i32> %{{.+}}, splat (i32 1)
+// LLVM: sub <4 x i32> %{{.+}}, splat (i32 1)
+// LLVM: add <4 x i32> %{{.+}}, splat (i32 1)
+// LLVM: sub <4 x i32> %{{.+}}, splat (i32 1)
+
+// OGCG-LABEL: @_Z13vecUIntIncDecDv4_j
+// OGCG: add <4 x i32> %{{.+}}, splat (i32 1)
+// OGCG: add <4 x i32> %{{.+}}, splat (i32 -1)
+// OGCG: add <4 x i32> %{{.+}}, splat (i32 1)
+// OGCG: add <4 x i32> %{{.+}}, splat (i32 -1)
+
+void vecShortIncDec(vsh8 c) {
+  ++c;
+  --c;
+  c++;
+  c--;
+}
+// CIR-LABEL: @_Z14vecShortIncDecDv8_s
+// CIR:  cir.inc %{{.+}} : !cir.vector<8 x !s16i>
+// CIR:  cir.dec %{{.+}} : !cir.vector<8 x !s16i>
+// CIR:  cir.inc %{{.+}} : !cir.vector<8 x !s16i>
+// CIR:  cir.dec %{{.+}} : !cir.vector<8 x !s16i>
+
+// LLVM-LABEL: @_Z14vecShortIncDecDv8_s
+// LLVM: add <8 x i16> %{{.+}}, splat (i16 1)
+// LLVM: sub <8 x i16> %{{.+}}, splat (i16 1)
+// LLVM: add <8 x i16> %{{.+}}, splat (i16 1)
+// LLVM: sub <8 x i16> %{{.+}}, splat (i16 1)
+
+// OGCG-LABEL: @_Z14vecShortIncDecDv8_s
+// OGCG: add <8 x i16> %{{.+}}, splat (i16 1)
+// OGCG: add <8 x i16> %{{.+}}, splat (i16 -1)
+// OGCG: add <8 x i16> %{{.+}}, splat (i16 1)
+// OGCG: add <8 x i16> %{{.+}}, splat (i16 -1)
+
+void vecFloatIncDec(vf4 a) {
+  ++a;
+  --a;
+  a++;
+  a--;
+}
+// CIR-LABEL: @_Z14vecFloatIncDecDv4_f
+// CIR:  %[[ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float
+// CIR:  %[[ONEVEC:.*]] = cir.vec.splat %[[ONE]] : !cir.float, !cir.vector<4 x 
!cir.float>
+// CIR:  cir.fadd %{{.+}}, %[[ONEVEC]] : !cir.vector<4 x !cir.float>
+// CIR:  %[[ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float
+// CIR:  %[[ONEVEC:.*]] = cir.vec.splat %[[ONE]] : !cir.float, !cir.vector<4 x 
!cir.float>
+// CIR:  cir.fsub %{{.+}}, %[[ONEVEC]] : !cir.vector<4 x !cir.float>
+// CIR:  %[[ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float
+// CIR:  %[[ONEVEC:.*]] = cir.vec.splat %[[ONE]] : !cir.float, !cir.vector<4 x 
!cir.float>
+// CIR:  cir.fadd %{{.+}}, %[[ONEVEC]] : !cir.vector<4 x !cir.float>
+// CIR:  %[[ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float
+// CIR:  %[[ONEVEC:.*]] = cir.vec.splat %[[ONE]] : !cir.float, !cir.vector<4 x 
!cir.float>
+// CIR:  cir.fsub %{{.+}}, %[[ONEVEC]] : !cir.vector<4 x !cir.float>
+
+// LLVM-LABEL: @_Z14vecFloatIncDecDv4_f
+// LLVM: fadd <4 x float> %{{.+}}, splat (float 1.000000e+00)
+// LLVM: fsub <4 x float> %{{.+}}, splat (float 1.000000e+00)
+// LLVM: fadd <4 x float> %{{.+}}, splat (float 1.000000e+00)
+// LLVM: fsub <4 x float> %{{.+}}, splat (float 1.000000e+00)
+
+// OGCG-LABEL: @_Z14vecFloatIncDecDv4_f
+// OGCG: fadd <4 x float> %{{.+}}, splat (float 1.000000e+00)
+// OGCG: fadd <4 x float> %{{.+}}, splat (float -1.000000e+00)
+// OGCG: fadd <4 x float> %{{.+}}, splat (float 1.000000e+00)
+// OGCG: fadd <4 x float> %{{.+}}, splat (float -1.000000e+00)
+
+void vecDoubleIncDec(vd2 b) {
+  ++b;
+  --b;
+  b++;
+  b--;
+}
+// CIR-LABEL: @_Z15vecDoubleIncDecDv2_d
+// CIR:  %[[ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.double
+// CIR:  %[[ONEVEC:.*]] = cir.vec.splat %[[ONE]] : !cir.double, !cir.vector<2 
x !cir.double>
+// CIR:  cir.fadd %{{.+}}, %[[ONEVEC]] : !cir.vector<2 x !cir.double>
+// CIR:  %[[ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.double
+// CIR:  %[[ONEVEC:.*]] = cir.vec.splat %[[ONE]] : !cir.double, !cir.vector<2 
x !cir.double>
+// CIR:  cir.fsub %{{.+}}, %[[ONEVEC]] : !cir.vector<2 x !cir.double>
+// CIR:  %[[ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.double
+// CIR:  %[[ONEVEC:.*]] = cir.vec.splat %[[ONE]] : !cir.double, !cir.vector<2 
x !cir.double>
+// CIR:  cir.fadd %{{.+}}, %[[ONEVEC]] : !cir.vector<2 x !cir.double>
+// CIR:  %[[ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.double
+// CIR:  %[[ONEVEC:.*]] = cir.vec.splat %[[ONE]] : !cir.double, !cir.vector<2 
x !cir.double>
+// CIR:  cir.fsub %{{.+}}, %[[ONEVEC]] : !cir.vector<2 x !cir.double>
+
+// LLVM-LABEL: @_Z15vecDoubleIncDecDv2_d
+// LLVM: fadd <2 x double> %{{.+}}, splat (double 1.000000e+00)
+// LLVM: fsub <2 x double> %{{.+}}, splat (double 1.000000e+00)
+// LLVM: fadd <2 x double> %{{.+}}, splat (double 1.000000e+00)
+// LLVM: fsub <2 x double> %{{.+}}, splat (double 1.000000e+00)
+
+// OGCG-LABEL: @_Z15vecDoubleIncDecDv2_d
+// OGCG: fadd <2 x double> %{{.+}}, splat (double 1.000000e+00)
+// OGCG: fadd <2 x double> %{{.+}}, splat (double -1.000000e+00)
+// OGCG: fadd <2 x double> %{{.+}}, splat (double 1.000000e+00)
+// OGCG: fadd <2 x double> %{{.+}}, splat (double -1.000000e+00)
diff --git a/clang/test/CIR/CodeGen/unary.cpp b/clang/test/CIR/CodeGen/unary.cpp
index 03b068a68d066..84a07691ce85b 100644
--- a/clang/test/CIR/CodeGen/unary.cpp
+++ b/clang/test/CIR/CodeGen/unary.cpp
@@ -222,6 +222,24 @@ int inc2() {
 // OGCG:   store i32 %[[A_LOAD]], ptr %[[B]], align 4
 // OGCG:   %[[B_TO_OUTPUT:.*]] = load i32, ptr %[[B]], align 4
 
+void chars(char c) {
+// CHECK: cir.func{{.*}} @_Z5charsc
+
+  int c1 = +c;
+  // CHECK: %[[PROMO:.*]] = cir.cast integral %{{.+}} : !s8i -> !s32i
+  int c2 = -c;
+  // CHECK: %[[PROMO:.*]] = cir.cast integral %{{.+}} : !s8i -> !s32i
+  // CHECK: cir.minus nsw %[[PROMO]] : !s32i
+
+  // Chars can go through some integer promotion codegen paths even when not 
promoted.
+  // These should not have nsw attributes because the intermediate promotion 
makes the
+  // overflow defined behavior.
+  ++c; // CHECK: cir.inc %{{.+}} : !s8i
+  --c; // CHECK: cir.dec %{{.+}} : !s8i
+  c++; // CHECK: cir.inc %{{.+}} : !s8i
+  c--; // CHECK: cir.dec %{{.+}} : !s8i
+}
+
 float fpPlus() {
   float a = 1.0f;
   return +a;
@@ -409,65 +427,698 @@ float fpPostInc2() {
 // OGCG:   store float %[[A_LOAD]], ptr %[[B]], align 4
 // OGCG:   %[[B_TO_OUTPUT:.*]] = load float, ptr %[[B]], align 4
 
-void chars(char c) {
-// CHECK: cir.func{{.*}} @_Z5charsc
+// double unary operations
+double doubleUPlus(double f) {
+  return +f;
+}
 
-  int c1 = +c;
-  // CHECK: %[[PROMO:.*]] = cir.cast integral %{{.+}} : !s8i -> !s32i
-  int c2 = -c;
-  // CHECK: %[[PROMO:.*]] = cir.cast integral %{{.+}} : !s8i -> !s32i
-  // CHECK: cir.minus nsw %[[PROMO]] : !s32i
+// CHECK: cir.func{{.*}} @_Z11doubleUPlusd({{.*}}) -> (!cir.double{{.*}})
+// CHECK:   %[[DBL_F:.*]] = cir.alloca "f" {{.*}} init : !cir.ptr<!cir.double>
+// CHECK:   %[[DBL_LOAD:.*]] = cir.load{{.*}} %[[DBL_F]]
 
-  // Chars can go through some integer promotion codegen paths even when not 
promoted.
-  // These should not have nsw attributes because the intermediate promotion 
makes the
-  // overflow defined behavior.
-  ++c; // CHECK: cir.inc %{{.+}} : !s8i
-  --c; // CHECK: cir.dec %{{.+}} : !s8i
-  c++; // CHECK: cir.inc %{{.+}} : !s8i
-  c--; // CHECK: cir.dec %{{.+}} : !s8i
+// LLVM: define{{.*}} double @_Z11doubleUPlusd({{.*}})
+// LLVM:   %[[DBL_LOAD:.*]] = load double, ptr %{{.*}}, align 8
+
+// OGCG: define{{.*}} double @_Z11doubleUPlusd({{.*}})
+// OGCG:   %[[DBL_LOAD:.*]] = load double, ptr %{{.*}}, align 8
+
+double doubleUMinus(double f) {
+  return -f;
+}
+
+// CHECK: cir.func{{.*}} @_Z12doubleUMinusd({{.*}}) -> (!cir.double{{.*}})
+// CHECK:   %[[DBL_F:.*]] = cir.alloca "f" {{.*}} init : !cir.ptr<!cir.double>
+// CHECK:   %[[DBL_LOAD:.*]] = cir.load{{.*}} %[[DBL_F]]
+// CHECK:   %[[DBL_NEGATED:.*]] = cir.fneg %[[DBL_LOAD]]
+
+// LLVM: define{{.*}} double @_Z12doubleUMinusd({{.*}})
+// LLVM:   %[[DBL_LOAD:.*]] = load double, ptr %{{.*}}, align 8
+// LLVM:   %[[DBL_NEGATED:.*]] = fneg double %[[DBL_LOAD]]
+
+// OGCG: define{{.*}} double @_Z12doubleUMinusd({{.*}})
+// OGCG:   %[[DBL_LOAD:.*]] = load double, ptr %{{.*}}, align 8
+// OGCG:   %[[DBL_NEGATED:.*]] = fneg double %[[DBL_LOAD]]
+
+double doubleUPreInc(double f) {
+  return ++f;
+}
+
+// CHECK: cir.func{{.*}} @_Z13doubleUPreIncd({{.*}}) -> (!cir.double{{.*}})
+// CHECK:   %[[DBL_F:.*]] = cir.alloca "f" {{.*}} init : !cir.ptr<!cir.double>
+// CHECK:   %[[DBL_LOAD:.*]] = cir.load{{.*}} %[[DBL_F]]
+// CHECK:   %[[DBL_ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.double
+// CHECK:   %[[DBL_INC:.*]] = cir.fadd %[[DBL_LOAD]], %[[DBL_ONE]]
+
+// LLVM: define{{.*}} double @_Z13doubleUPreIncd({{.*}})
+// LLVM:   %[[DBL_LOAD:.*]] = load double, ptr %{{.*}}, align 8
+// LLVM:   %[[DBL_INC:.*]] = fadd double %[[DBL_LOAD]], 1.000000e+00
+
+// OGCG: define{{.*}} double @_Z13doubleUPreIncd({{.*}})
+// OGCG:   %[[DBL_LOAD:.*]] = load double, ptr %{{.*}}, align 8
+// OGCG:   %[[DBL_INC:.*]] = fadd double %[[DBL_LOAD]], 1.000000e+00
+
+double doubleUPreDec(double f) {
+  return --f;
+}
+
+// CHECK: cir.func{{.*}} @_Z13doubleUPreDecd({{.*}}) -> (!cir.double{{.*}})
+// CHECK:   %[[DBL_F:.*]] = cir.alloca "f" {{.*}} init : !cir.ptr<!cir.double>
+// CHECK:   %[[DBL_LOAD:.*]] = cir.load{{.*}} %[[DBL_F]]
+// CHECK:   %[[DBL_ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.double
+// CHECK:   %[[DBL_DEC:.*]] = cir.fsub %[[DBL_LOAD]], %[[DBL_ONE]]
+
+// LLVM: define{{.*}} double @_Z13doubleUPreDecd({{.*}})
+// LLVM:   %[[DBL_LOAD:.*]] = load double, ptr %{{.*}}, align 8
+// LLVM:   %[[DBL_DEC:.*]] = fsub double %[[DBL_LOAD]], 1.000000e+00
+
+// OGCG: define{{.*}} double @_Z13doubleUPreDecd({{.*}})
+// OGCG:   %[[DBL_LOAD:.*]] = load double, ptr %{{.*}}, align 8
+// OGCG:   %[[DBL_DEC:.*]] = fadd double %[[DBL_LOAD]], -1.000000e+00
+
+double doubleUPostInc(double f) {
+  return f++;
+}
+
+// CHECK: cir.func{{.*}} @_Z14doubleUPostIncd({{.*}}) -> (!cir.double{{.*}})
+// CHECK:   %[[DBL_F:.*]] = cir.alloca "f" {{.*}} init : !cir.ptr<!cir.double>
+// CHECK:   %[[DBL_LOAD:.*]] = cir.load{{.*}} %[[DBL_F]]
+// CHECK:   %[[DBL_ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.double
+// CHECK:   %[[DBL_INC:.*]] = cir.fadd %[[DBL_LOAD]], %[[DBL_ONE]]
+
+// LLVM: define{{.*}} double @_Z14doubleUPostIncd({{.*}})
+// LLVM:   %[[DBL_LOAD:.*]] = load double, ptr %{{.*}}, align 8
+// LLVM:   %[[DBL_INC:.*]] = fadd double %[[DBL_LOAD]], 1.000000e+00
+
+// OGCG: define{{.*}} double @_Z14doubleUPostIncd({{.*}})
+// OGCG:   %[[DBL_LOAD:.*]] = load double, ptr %{{.*}}, align 8
+// OGCG:   %[[DBL_INC:.*]] = fadd double %[[DBL_LOAD]], 1.000000e+00
+
+double doubleUPostDec(double f) {
+  return f--;
+}
+
+// CHECK: cir.func{{.*}} @_Z14doubleUPostDecd({{.*}}) -> (!cir.double{{.*}})
+// CHECK:   %[[DBL_F:.*]] = cir.alloca "f" {{.*}} init : !cir.ptr<!cir.double>
+// CHECK:   %[[DBL_LOAD:.*]] = cir.load{{.*}} %[[DBL_F]]
+// CHECK:   %[[DBL_ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.double
+// CHECK:   %[[DBL_DEC:.*]] = cir.fsub %[[DBL_LOAD]], %[[DBL_ONE]]
+
+// LLVM: define{{.*}} double @_Z14doubleUPostDecd({{.*}})
+// LLVM:   %[[DBL_LOAD:.*]] = load double, ptr %{{.*}}, align 8
+// LLVM:   %[[DBL_DEC:.*]] = fsub double %[[DBL_LOAD]], 1.000000e+00
+
+// OGCG: define{{.*}} double @_Z14doubleUPostDecd({{.*}})
+// OGCG:   %[[DBL_LOAD:.*]] = load double, ptr %{{.*}}, align 8
+// OGCG:   %[[DBL_DEC:.*]] = fadd double %[[DBL_LOAD]], -1.000000e+00
+
+// long double unary operations
+long double ldUPlus(long double f) {
+  return +f;
+}
+
+// CHECK: cir.func{{.*}} @_Z7ldUPluse({{.*}}) -> 
(!cir.long_double<!cir.f80>{{.*}})
+// CHECK:   %[[LD_F:.*]] = cir.alloca "f" {{.*}} init : 
!cir.ptr<!cir.long_double<!cir.f80>>
+// CHECK:   %[[LD_LOAD:.*]] = cir.load{{.*}} %[[LD_F]]
+
+// LLVM: define{{.*}} x86_fp80 @_Z7ldUPluse({{.*}})
+// LLVM:   %[[LD_LOAD:.*]] = load x86_fp80, ptr %{{.*}}, align 16
+
+// OGCG: define{{.*}} x86_fp80 @_Z7ldUPluse({{.*}})
+// OGCG:   %[[LD_LOAD:.*]] = load x86_fp80, ptr %{{.*}}, align 16
+
+long double ldUMinus(long double f) {
+  return -f;
+}
+
+// CHECK: cir.func{{.*}} @_Z8ldUMinuse({{.*}}) -> 
(!cir.long_double<!cir.f80>{{.*}})
+// CHECK:   %[[LD_F:.*]] = cir.alloca "f" {{.*}} init : 
!cir.ptr<!cir.long_double<!cir.f80>>
+// CHECK:   %[[LD_LOAD:.*]] = cir.load{{.*}} %[[LD_F]]
+// CHECK:   %[[LD_NEGATED:.*]] = cir.fneg %[[LD_LOAD]]
+
+// LLVM: define{{.*}} x86_fp80 @_Z8ldUMinuse({{.*}})
+// LLVM:   %[[LD_LOAD:.*]] = load x86_fp80, ptr %{{.*}}, align 16
+// LLVM:   %[[LD_NEGATED:.*]] = fneg x86_fp80 %[[LD_LOAD]]
+
+// OGCG: define{{.*}} x86_fp80 @_Z8ldUMinuse({{.*}})
+// OGCG:   %[[LD_LOAD:.*]] = load x86_fp80, ptr %{{.*}}, align 16
+// OGCG:   %[[LD_NEGATED:.*]] = fneg x86_fp80 %[[LD_LOAD]]
+
+long double ldUPreInc(long double f) {
+  return ++f;
+}
+
+// CHECK: cir.func{{.*}} @_Z9ldUPreInce({{.*}}) -> 
(!cir.long_double<!cir.f80>{{.*}})
+// CHECK:   %[[LD_F:.*]] = cir.alloca "f" {{.*}} init : 
!cir.ptr<!cir.long_double<!cir.f80>>
+// CHECK:   %[[LD_LOAD:.*]] = cir.load{{.*}} %[[LD_F]]
+// CHECK:   %[[LD_ONE:.*]] = cir.const #cir.fp<1.000000e+00> : 
!cir.long_double<!cir.f80>
+// CHECK:   %[[LD_INC:.*]] = cir.fadd %[[LD_LOAD]], %[[LD_ONE]]
+
+// LLVM: define{{.*}} x86_fp80 @_Z9ldUPreInce({{.*}})
+// LLVM:   %[[LD_LOAD:.*]] = load x86_fp80, ptr %{{.*}}, align 16
+// LLVM:   %[[LD_INC:.*]] = fadd x86_fp80 %[[LD_LOAD]], 1.000000e+00
+
+// OGCG: define{{.*}} x86_fp80 @_Z9ldUPreInce({{.*}})
+// OGCG:   %[[LD_LOAD:.*]] = load x86_fp80, ptr %{{.*}}, align 16
+// OGCG:   %[[LD_INC:.*]] = fadd x86_fp80 %[[LD_LOAD]], 1.000000e+00
+
+long double ldUPreDec(long double f) {
+  return --f;
+}
+
+// CHECK: cir.func{{.*}} @_Z9ldUPreDece({{.*}}) -> 
(!cir.long_double<!cir.f80>{{.*}})
+// CHECK:   %[[LD_F:.*]] = cir.alloca "f" {{.*}} init : 
!cir.ptr<!cir.long_double<!cir.f80>>
+// CHECK:   %[[LD_LOAD:.*]] = cir.load{{.*}} %[[LD_F]]
+// CHECK:   %[[LD_ONE:.*]] = cir.const #cir.fp<1.000000e+00> : 
!cir.long_double<!cir.f80>
+// CHECK:   %[[LD_DEC:.*]] = cir.fsub %[[LD_LOAD]], %[[LD_ONE]]
+
+// LLVM: define{{.*}} x86_fp80 @_Z9ldUPreDece({{.*}})
+// LLVM:   %[[LD_LOAD:.*]] = load x86_fp80, ptr %{{.*}}, align 16
+// LLVM:   %[[LD_DEC:.*]] = fsub x86_fp80 %[[LD_LOAD]], 1.000000e+00
+
+// OGCG: define{{.*}} x86_fp80 @_Z9ldUPreDece({{.*}})
+// OGCG:   %[[LD_LOAD:.*]] = load x86_fp80, ptr %{{.*}}, align 16
+// OGCG:   %[[LD_DEC:.*]] = fadd x86_fp80 %[[LD_LOAD]], -1.000000e+00
+
+long double ldUPostInc(long double f) {
+  return f++;
+}
+
+// CHECK: cir.func{{.*}} @_Z10ldUPostInce({{.*}}) -> 
(!cir.long_double<!cir.f80>{{.*}})
+// CHECK:   %[[LD_F:.*]] = cir.alloca "f" {{.*}} init : 
!cir.ptr<!cir.long_double<!cir.f80>>
+// CHECK:   %[[LD_LOAD:.*]] = cir.load{{.*}} %[[LD_F]]
+// CHECK:   %[[LD_ONE:.*]] = cir.const #cir.fp<1.000000e+00> : 
!cir.long_double<!cir.f80>
+// CHECK:   %[[LD_INC:.*]] = cir.fadd %[[LD_LOAD]], %[[LD_ONE]]
+
+// LLVM: define{{.*}} x86_fp80 @_Z10ldUPostInce({{.*}})
+// LLVM:   %[[LD_LOAD:.*]] = load x86_fp80, ptr %{{.*}}, align 16
+// LLVM:   %[[LD_INC:.*]] = fadd x86_fp80 %[[LD_LOAD]], 1.000000e+00
+
+// OGCG: define{{.*}} x86_fp80 @_Z10ldUPostInce({{.*}})
+// OGCG:   %[[LD_LOAD:.*]] = load x86_fp80, ptr %{{.*}}, align 16
+// OGCG:   %[[LD_INC:.*]] = fadd x86_fp80 %[[LD_LOAD]], 1.000000e+00
+
+long double ldUPostDec(long double f) {
+  return f--;
+}
+
+// CHECK: cir.func{{.*}} @_Z10ldUPostDece({{.*}}) -> 
(!cir.long_double<!cir.f80>{{.*}})
+// CHECK:   %[[LD_F:.*]] = cir.alloca "f" {{.*}} init : 
!cir.ptr<!cir.long_double<!cir.f80>>
+// CHECK:   %[[LD_LOAD:.*]] = cir.load{{.*}} %[[LD_F]]
+// CHECK:   %[[LD_ONE:.*]] = cir.const #cir.fp<1.000000e+00> : 
!cir.long_double<!cir.f80>
+// CHECK:   %[[LD_DEC:.*]] = cir.fsub %[[LD_LOAD]], %[[LD_ONE]]
+
+// LLVM: define{{.*}} x86_fp80 @_Z10ldUPostDece({{.*}})
+// LLVM:   %[[LD_LOAD:.*]] = load x86_fp80, ptr %{{.*}}, align 16
+// LLVM:   %[[LD_DEC:.*]] = fsub x86_fp80 %[[LD_LOAD]], 1.000000e+00
+
+// OGCG: define{{.*}} x86_fp80 @_Z10ldUPostDece({{.*}})
+// OGCG:   %[[LD_LOAD:.*]] = load x86_fp80, ptr %{{.*}}, align 16
+// OGCG:   %[[LD_DEC:.*]] = fadd x86_fp80 %[[LD_LOAD]], -1.000000e+00
+
+// __float128 unary operations
+__float128 f128UPlus(__float128 f) {
+  return +f;
+}
+
+// CHECK: cir.func{{.*}} @_Z9f128UPlusg({{.*}}) -> (!cir.f128{{.*}})
+// CHECK:   %[[F128_F:.*]] = cir.alloca "f" {{.*}} init : !cir.ptr<!cir.f128>
+// CHECK:   %[[F128_LOAD:.*]] = cir.load{{.*}} %[[F128_F]]
+
+// LLVM: define{{.*}} fp128 @_Z9f128UPlusg({{.*}})
+// LLVM:   %[[F128_LOAD:.*]] = load fp128, ptr %{{.*}}, align 16
+
+// OGCG: define{{.*}} fp128 @_Z9f128UPlusg({{.*}})
+// OGCG:   %[[F128_LOAD:.*]] = load fp128, ptr %{{.*}}, align 16
+
+__float128 f128UMinus(__float128 f) {
+  return -f;
+}
+
+// CHECK: cir.func{{.*}} @_Z10f128UMinusg({{.*}}) -> (!cir.f128{{.*}})
+// CHECK:   %[[F128_F:.*]] = cir.alloca "f" {{.*}} init : !cir.ptr<!cir.f128>
+// CHECK:   %[[F128_LOAD:.*]] = cir.load{{.*}} %[[F128_F]]
+// CHECK:   %[[F128_NEG:.*]] = cir.fneg %[[F128_LOAD]]
+
+// LLVM: define{{.*}} fp128 @_Z10f128UMinusg({{.*}})
+// LLVM:   %[[F128_LOAD:.*]] = load fp128, ptr %{{.*}}, align 16
+// LLVM:   %[[F128_NEG:.*]] = fneg fp128 %[[F128_LOAD]]
+
+// OGCG: define{{.*}} fp128 @_Z10f128UMinusg({{.*}})
+// OGCG:   %[[F128_LOAD:.*]] = load fp128, ptr %{{.*}}, align 16
+// OGCG:   %[[F128_NEG:.*]] = fneg fp128 %[[F128_LOAD]]
+
+__float128 f128UPreInc(__float128 f) {
+  return ++f;
+}
+
+// CHECK: cir.func{{.*}} @_Z11f128UPreIncg({{.*}}) -> (!cir.f128{{.*}})
+// CHECK:   %[[F128_F:.*]] = cir.alloca "f" {{.*}} init : !cir.ptr<!cir.f128>
+// CHECK:   %[[F128_LOAD:.*]] = cir.load{{.*}} %[[F128_F]]
+// CHECK:   %[[F128_ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.f128
+// CHECK:   %[[F128_INC:.*]] = cir.fadd %[[F128_LOAD]], %[[F128_ONE]]
+
+// LLVM: define{{.*}} fp128 @_Z11f128UPreIncg({{.*}})
+// LLVM:   %[[F128_LOAD:.*]] = load fp128, ptr %{{.*}}, align 16
+// LLVM:   %[[F128_INC:.*]] = fadd fp128 %[[F128_LOAD]], 1.000000e+00
+
+// OGCG: define{{.*}} fp128 @_Z11f128UPreIncg({{.*}})
+// OGCG:   %[[F128_LOAD:.*]] = load fp128, ptr %{{.*}}, align 16
+// OGCG:   %[[F128_INC:.*]] = fadd fp128 %[[F128_LOAD]], 1.000000e+00
+
+__float128 f128UPreDec(__float128 f) {
+  return --f;
+}
+
+// CHECK: cir.func{{.*}} @_Z11f128UPreDecg({{.*}}) -> (!cir.f128{{.*}})
+// CHECK:   %[[F128_F:.*]] = cir.alloca "f" {{.*}} init : !cir.ptr<!cir.f128>
+// CHECK:   %[[F128_LOAD:.*]] = cir.load{{.*}} %[[F128_F]]
+// CHECK:   %[[F128_ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.f128
+// CHECK:   %[[F128_DEC:.*]] = cir.fsub %[[F128_LOAD]], %[[F128_ONE]]
+
+// LLVM: define{{.*}} fp128 @_Z11f128UPreDecg({{.*}})
+// LLVM:   %[[F128_LOAD:.*]] = load fp128, ptr %{{.*}}, align 16
+// LLVM:   %[[F128_DEC:.*]] = fsub fp128 %[[F128_LOAD]], 1.000000e+00
+
+// OGCG: define{{.*}} fp128 @_Z11f128UPreDecg({{.*}})
+// OGCG:   %[[F128_LOAD:.*]] = load fp128, ptr %{{.*}}, align 16
+// OGCG:   %[[F128_DEC:.*]] = fadd fp128 %[[F128_LOAD]], -1.000000e+00
+
+__float128 f128UPostInc(__float128 f) {
+  return f++;
+}
+
+// CHECK: cir.func{{.*}} @_Z12f128UPostIncg({{.*}}) -> (!cir.f128{{.*}})
+// CHECK:   %[[F128_F:.*]] = cir.alloca "f" {{.*}} init : !cir.ptr<!cir.f128>
+// CHECK:   %[[F128_LOAD:.*]] = cir.load{{.*}} %[[F128_F]]
+// CHECK:   %[[F128_ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.f128
+// CHECK:   %[[F128_INC:.*]] = cir.fadd %[[F128_LOAD]], %[[F128_ONE]]
+
+// LLVM: define{{.*}} fp128 @_Z12f128UPostIncg({{.*}})
+// LLVM:   %[[F128_LOAD:.*]] = load fp128, ptr %{{.*}}, align 16
+// LLVM:   %[[F128_INC:.*]] = fadd fp128 %[[F128_LOAD]], 1.000000e+00
+
+// OGCG: define{{.*}} fp128 @_Z12f128UPostIncg({{.*}})
+// OGCG:   %[[F128_LOAD:.*]] = load fp128, ptr %{{.*}}, align 16
+// OGCG:   %[[F128_INC:.*]] = fadd fp128 %[[F128_LOAD]], 1.000000e+00
+
+__float128 f128UPostDec(__float128 f) {
+  return f--;
 }
 
-_Float16 fp16UPlus(_Float16 f) {
+// CHECK: cir.func{{.*}} @_Z12f128UPostDecg({{.*}}) -> (!cir.f128{{.*}})
+// CHECK:   %[[F128_F:.*]] = cir.alloca "f" {{.*}} init : !cir.ptr<!cir.f128>
+// CHECK:   %[[F128_LOAD:.*]] = cir.load{{.*}} %[[F128_F]]
+// CHECK:   %[[F128_ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.f128
+// CHECK:   %[[F128_DEC:.*]] = cir.fsub %[[F128_LOAD]], %[[F128_ONE]]
+
+// LLVM: define{{.*}} fp128 @_Z12f128UPostDecg({{.*}})
+// LLVM:   %[[F128_LOAD:.*]] = load fp128, ptr %{{.*}}, align 16
+// LLVM:   %[[F128_DEC:.*]] = fsub fp128 %[[F128_LOAD]], 1.000000e+00
+
+// OGCG: define{{.*}} fp128 @_Z12f128UPostDecg({{.*}})
+// OGCG:   %[[F128_LOAD:.*]] = load fp128, ptr %{{.*}}, align 16
+// OGCG:   %[[F128_DEC:.*]] = fadd fp128 %[[F128_LOAD]], -1.000000e+00
+
+// Float16 unary operations
+_Float16 Float16UPlus(_Float16 f) {
   return +f;
 }
 
-// CHECK: cir.func{{.*}} @_Z9fp16UPlusDF16_({{.*}}) -> (!cir.f16{{.*}})
+// CHECK: cir.func{{.*}} @_Z12Float16UPlusDF16_({{.*}}) -> (!cir.f16{{.*}})
 // CHECK:   %[[INPUT:.*]] = cir.load{{.*}} %[[F:.*]]
 // CHECK:   %[[PROMOTED:.*]] = cir.cast floating %[[INPUT]] : !cir.f16 -> 
!cir.float
 // CHECK:   %[[UNPROMOTED:.*]] = cir.cast floating %[[PROMOTED]] : !cir.float 
-> !cir.f16
 
-// LLVM: define{{.*}} half @_Z9fp16UPlusDF16_({{.*}})
+// LLVM: define{{.*}} half @_Z12Float16UPlusDF16_({{.*}})
 // LLVM:   %[[F_LOAD:.*]] = load half, ptr %{{.*}}, align 2
 // LLVM:   %[[PROMOTED:.*]] = fpext half %[[F_LOAD]] to float
 // LLVM:   %[[UNPROMOTED:.*]] = fptrunc float %[[PROMOTED]] to half
 
-// OGCG: define{{.*}} half @_Z9fp16UPlusDF16_({{.*}})
+// OGCG: define{{.*}} half @_Z12Float16UPlusDF16_({{.*}})
 // OGCG:   %[[F_LOAD:.*]] = load half, ptr %{{.*}}, align 2
 // OGCG:   %[[PROMOTED:.*]] = fpext half %[[F_LOAD]] to float
 // OGCG:   %[[UNPROMOTED:.*]] = fptrunc float %[[PROMOTED]] to half
 
-_Float16 fp16UMinus(_Float16 f) {
+_Float16 Float16UMinus(_Float16 f) {
   return -f;
 }
 
-// CHECK: cir.func{{.*}} @_Z10fp16UMinusDF16_({{.*}}) -> (!cir.f16{{.*}})
+// CHECK: cir.func{{.*}} @_Z13Float16UMinusDF16_({{.*}}) -> (!cir.f16{{.*}})
 // CHECK:   %[[INPUT:.*]] = cir.load{{.*}} %[[F:.*]]
 // CHECK:   %[[PROMOTED:.*]] = cir.cast floating %[[INPUT]] : !cir.f16 -> 
!cir.float
 // CHECK:   %[[RESULT:.*]] = cir.fneg %[[PROMOTED]]
 // CHECK:   %[[UNPROMOTED:.*]] = cir.cast floating %[[RESULT]] : !cir.float -> 
!cir.f16
 
-// LLVM: define{{.*}} half @_Z10fp16UMinusDF16_({{.*}})
+// LLVM: define{{.*}} half @_Z13Float16UMinusDF16_({{.*}})
 // LLVM:   %[[F_LOAD:.*]] = load half, ptr %{{.*}}, align 2
 // LLVM:   %[[PROMOTED:.*]] = fpext half %[[F_LOAD]] to float
 // LLVM:   %[[RESULT:.*]] = fneg float %[[PROMOTED]]
 // LLVM:   %[[UNPROMOTED:.*]] = fptrunc float %[[RESULT]] to half
 
-// OGCG: define{{.*}} half @_Z10fp16UMinusDF16_({{.*}})
+// OGCG: define{{.*}} half @_Z13Float16UMinusDF16_({{.*}})
 // OGCG:   %[[F_LOAD:.*]] = load half, ptr %{{.*}}, align 2
 // OGCG:   %[[PROMOTED:.*]] = fpext half %[[F_LOAD]] to float
 // OGCG:   %[[RESULT:.*]] = fneg float %[[PROMOTED]]
 // OGCG:   %[[UNPROMOTED:.*]] = fptrunc float %[[RESULT]] to half
 
+_Float16 Float16UPreInc(_Float16 f) {
+  return ++f;
+}
+
+// CHECK: cir.func{{.*}} @_Z14Float16UPreIncDF16_({{.*}}) -> (!cir.f16{{.*}})
+// CHECK:   %[[PREINC_F:.*]] = cir.alloca "f" {{.*}} init : !cir.ptr<!cir.f16>
+// CHECK:   %[[PREINC_INPUT:.*]] = cir.load{{.*}} %[[PREINC_F]]
+// CHECK:   %[[PREINC_ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.f16
+// CHECK:   %[[PREINC_RESULT:.*]] = cir.fadd %[[PREINC_INPUT]], 
%[[PREINC_ONE]] : !cir.f16
+
+// LLVM: define{{.*}} half @_Z14Float16UPreIncDF16_({{.*}})
+// LLVM:   %[[PREINC_F_ADDR:.*]] = alloca half, align 2
+// LLVM:   %[[PREINC_INPUT:.*]] = load half, ptr %[[PREINC_F_ADDR]], align 2
+// LLVM:   %[[PREINC_RESULT:.*]] = fadd half %[[PREINC_INPUT]], 1.000000e+00
+
+// OGCG: define{{.*}} half @_Z14Float16UPreIncDF16_({{.*}})
+// OGCG:   %[[PREINC_F_ADDR:.*]] = alloca half, align 2
+// OGCG:   %[[PREINC_INPUT:.*]] = load half, ptr %[[PREINC_F_ADDR]], align 2
+// OGCG:   %[[PREINC_RESULT:.*]] = fadd half %[[PREINC_INPUT]], 1.000000e+00
+
+_Float16 Float16UPreDec(_Float16 f) {
+  return --f;
+}
+
+// CHECK: cir.func{{.*}} @_Z14Float16UPreDecDF16_({{.*}}) -> (!cir.f16{{.*}})
+// CHECK:   %[[PREDEC_F:.*]] = cir.alloca "f" {{.*}} init : !cir.ptr<!cir.f16>
+// CHECK:   %[[PREDEC_INPUT:.*]] = cir.load{{.*}} %[[PREDEC_F]]
+// CHECK:   %[[PREDEC_ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.f16
+// CHECK:   %[[PREDEC_RESULT:.*]] = cir.fsub %[[PREDEC_INPUT]], 
%[[PREDEC_ONE]] : !cir.f16
+
+// LLVM: define{{.*}} half @_Z14Float16UPreDecDF16_({{.*}})
+// LLVM:   %[[PREDEC_F_ADDR:.*]] = alloca half, align 2
+// LLVM:   %[[PREDEC_INPUT:.*]] = load half, ptr %[[PREDEC_F_ADDR]], align 2
+// LLVM:   %[[PREDEC_RESULT:.*]] = fsub half %[[PREDEC_INPUT]], 1.000000e+00
+
+// OGCG: define{{.*}} half @_Z14Float16UPreDecDF16_({{.*}})
+// OGCG:   %[[PREDEC_F_ADDR:.*]] = alloca half, align 2
+// OGCG:   %[[PREDEC_INPUT:.*]] = load half, ptr %[[PREDEC_F_ADDR]], align 2
+// OGCG:   %[[PREDEC_RESULT:.*]] = fadd half %[[PREDEC_INPUT]], -1.000000e+00
+
+_Float16 Float16UPostInc(_Float16 f) {
+  return f++;
+}
+
+// CHECK: cir.func{{.*}} @_Z15Float16UPostIncDF16_({{.*}}) -> (!cir.f16{{.*}})
+// CHECK:   %[[POSTINC_F:.*]] = cir.alloca "f" {{.*}} init : !cir.ptr<!cir.f16>
+// CHECK:   %[[POSTINC_INPUT:.*]] = cir.load{{.*}} %[[POSTINC_F]]
+// CHECK:   %[[POSTINC_ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.f16
+// CHECK:   %[[POSTINC_RESULT:.*]] = cir.fadd %[[POSTINC_INPUT]], 
%[[POSTINC_ONE]] : !cir.f16
+
+// LLVM: define{{.*}} half @_Z15Float16UPostIncDF16_({{.*}})
+// LLVM:   %[[POSTINC_F_ADDR:.*]] = alloca half, align 2
+// LLVM:   %[[POSTINC_INPUT:.*]] = load half, ptr %[[POSTINC_F_ADDR]], align 2
+// LLVM:   %[[POSTINC_RESULT:.*]] = fadd half %[[POSTINC_INPUT]], 1.000000e+00
+
+// OGCG: define{{.*}} half @_Z15Float16UPostIncDF16_({{.*}})
+// OGCG:   %[[POSTINC_F_ADDR:.*]] = alloca half, align 2
+// OGCG:   %[[POSTINC_INPUT:.*]] = load half, ptr %[[POSTINC_F_ADDR]], align 2
+// OGCG:   %[[POSTINC_RESULT:.*]] = fadd half %[[POSTINC_INPUT]], 1.000000e+00
+
+_Float16 Float16UPostDec(_Float16 f) {
+  return f--;
+}
+
+// CHECK: cir.func{{.*}} @_Z15Float16UPostDecDF16_({{.*}}) -> (!cir.f16{{.*}})
+// CHECK:   %[[POSTDEC_F:.*]] = cir.alloca "f" {{.*}} init : !cir.ptr<!cir.f16>
+// CHECK:   %[[POSTDEC_INPUT:.*]] = cir.load{{.*}} %[[POSTDEC_F]]
+// CHECK:   %[[POSTDEC_ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.f16
+// CHECK:   %[[POSTDEC_RESULT:.*]] = cir.fsub %[[POSTDEC_INPUT]], 
%[[POSTDEC_ONE]] : !cir.f16
+
+// LLVM: define{{.*}} half @_Z15Float16UPostDecDF16_({{.*}})
+// LLVM:   %[[POSTDEC_F_ADDR:.*]] = alloca half, align 2
+// LLVM:   %[[POSTDEC_INPUT:.*]] = load half, ptr %[[POSTDEC_F_ADDR]], align 2
+// LLVM:   %[[POSTDEC_RESULT:.*]] = fsub half %[[POSTDEC_INPUT]], 1.000000e+00
+
+// OGCG: define{{.*}} half @_Z15Float16UPostDecDF16_({{.*}})
+// OGCG:   %[[POSTDEC_F_ADDR:.*]] = alloca half, align 2
+// OGCG:   %[[POSTDEC_INPUT:.*]] = load half, ptr %[[POSTDEC_F_ADDR]], align 2
+// OGCG:   %[[POSTDEC_RESULT:.*]] = fadd half %[[POSTDEC_INPUT]], -1.000000e+00
+
+// __fp16 unary operations
+void fp16PtrUPlus(__fp16 *f) {
+  *f = +(*f);
+}
+
+// CHECK: cir.func{{.*}} @_Z12fp16PtrUPlusPDh({{.*}})
+// CHECK:   %[[FPTR_F:.*]] = cir.alloca "f" {{.*}} init : 
!cir.ptr<!cir.ptr<!cir.f16>>
+// CHECK:   %[[FPTR_DEREF:.*]] = cir.load deref{{.*}} %[[FPTR_F]]
+// CHECK:   %[[FPTR_LOAD:.*]] = cir.load{{.*}} %[[FPTR_DEREF]]
+// CHECK:   %[[FPTR_PROMOTED:.*]] = cir.cast floating %[[FPTR_LOAD]] : 
!cir.f16 -> !cir.float
+// CHECK:   %[[FPTR_UNPROMOTED:.*]] = cir.cast floating %[[FPTR_PROMOTED]] : 
!cir.float -> !cir.f16
+
+// LLVM: define{{.*}} void @_Z12fp16PtrUPlusPDh({{.*}})
+// LLVM:   %[[FPTR_LOAD:.*]] = load half, ptr %{{.*}}, align 2
+// LLVM:   %[[FPTR_PROMOTED:.*]] = fpext half %[[FPTR_LOAD]] to float
+// LLVM:   %[[FPTR_UNPROMOTED:.*]] = fptrunc float %[[FPTR_PROMOTED]] to half
+
+// OGCG: define{{.*}} void @_Z12fp16PtrUPlusPDh({{.*}})
+// OGCG:   %[[FPTR_LOAD:.*]] = load half, ptr %{{.*}}, align 2
+// OGCG:   %[[FPTR_PROMOTED:.*]] = fpext half %[[FPTR_LOAD]] to float
+// OGCG:   %[[FPTR_UNPROMOTED:.*]] = fptrunc float %[[FPTR_PROMOTED]] to half
+
+void fp16PtrUMinus(__fp16 *f) {
+  *f = -(*f);
+}
+
+// CHECK: cir.func{{.*}} @_Z13fp16PtrUMinusPDh({{.*}})
+// CHECK:   %[[FPTR_F:.*]] = cir.alloca "f" {{.*}} init : 
!cir.ptr<!cir.ptr<!cir.f16>>
+// CHECK:   %[[FPTR_DEREF:.*]] = cir.load deref{{.*}} %[[FPTR_F]]
+// CHECK:   %[[FPTR_LOAD:.*]] = cir.load{{.*}} %[[FPTR_DEREF]]
+// CHECK:   %[[FPTR_PROMOTED:.*]] = cir.cast floating %[[FPTR_LOAD]] : 
!cir.f16 -> !cir.float
+// CHECK:   %[[FPTR_NEGATED:.*]] = cir.fneg %[[FPTR_PROMOTED]]
+// CHECK:   %[[FPTR_UNPROMOTED:.*]] = cir.cast floating %[[FPTR_NEGATED]] : 
!cir.float -> !cir.f16
+
+// LLVM: define{{.*}} void @_Z13fp16PtrUMinusPDh({{.*}})
+// LLVM:   %[[FPTR_LOAD:.*]] = load half, ptr %{{.*}}, align 2
+// LLVM:   %[[FPTR_PROMOTED:.*]] = fpext half %[[FPTR_LOAD]] to float
+// LLVM:   %[[FPTR_NEGATED:.*]] = fneg float %[[FPTR_PROMOTED]]
+// LLVM:   %[[FPTR_UNPROMOTED:.*]] = fptrunc float %[[FPTR_NEGATED]] to half
+
+// OGCG: define{{.*}} void @_Z13fp16PtrUMinusPDh({{.*}})
+// OGCG:   %[[FPTR_LOAD:.*]] = load half, ptr %{{.*}}, align 2
+// OGCG:   %[[FPTR_PROMOTED:.*]] = fpext half %[[FPTR_LOAD]] to float
+// OGCG:   %[[FPTR_NEGATED:.*]] = fneg float %[[FPTR_PROMOTED]]
+// OGCG:   %[[FPTR_UNPROMOTED:.*]] = fptrunc float %[[FPTR_NEGATED]] to half
+
+void fp16PtrUPreInc(__fp16 *f) {
+ ++(*f);
+}
+
+// CHECK: cir.func{{.*}} @_Z14fp16PtrUPreIncPDh({{.*}})
+// CHECK:   %[[FPTR_F:.*]] = cir.alloca "f" {{.*}} init : 
!cir.ptr<!cir.ptr<!cir.f16>>
+// CHECK:   %[[FPTR_DEREF:.*]] = cir.load deref{{.*}} %[[FPTR_F]]
+// CHECK:   %[[FPTR_LOAD:.*]] = cir.load{{.*}} %[[FPTR_DEREF]]
+// CHECK:   %[[FPTR_PROMOTED:.*]] = cir.cast floating %[[FPTR_LOAD]] : 
!cir.f16 -> !cir.float
+// CHECK:   %[[FPTR_ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float
+// CHECK:   %[[FPTR_INC:.*]] = cir.fadd %[[FPTR_PROMOTED]], %[[FPTR_ONE]] : 
!cir.float
+// CHECK:   %[[FPTR_UNPROMOTED:.*]] = cir.cast floating %[[FPTR_INC]] : 
!cir.float -> !cir.f16
+
+// LLVM: define{{.*}} void @_Z14fp16PtrUPreIncPDh({{.*}})
+// LLVM:   %[[FPTR_LOAD:.*]] = load half, ptr %{{.*}}, align 2
+// LLVM:   %[[FPTR_PROMOTED:.*]] = fpext half %[[FPTR_LOAD]] to float
+// LLVM:   %[[FPTR_INC:.*]] = fadd float %[[FPTR_PROMOTED]], 1.000000e+00
+// LLVM:   %[[FPTR_UNPROMOTED:.*]] = fptrunc float %[[FPTR_INC]] to half
+
+// OGCG: define{{.*}} void @_Z14fp16PtrUPreIncPDh({{.*}})
+// OGCG:   %[[FPTR_LOAD:.*]] = load half, ptr %{{.*}}, align 2
+// OGCG:   %[[FPTR_PROMOTED:.*]] = fpext half %[[FPTR_LOAD]] to float
+// OGCG:   %[[FPTR_INC:.*]] = fadd float %[[FPTR_PROMOTED]], 1.000000e+00
+// OGCG:   %[[FPTR_UNPROMOTED:.*]] = fptrunc float %[[FPTR_INC]] to half
+
+void fp16PtrUPreDec(__fp16 *f) {
+  --(*f);
+}
+
+// CHECK: cir.func{{.*}} @_Z14fp16PtrUPreDecPDh({{.*}})
+// CHECK:   %[[FPTR_F:.*]] = cir.alloca "f" {{.*}} init : 
!cir.ptr<!cir.ptr<!cir.f16>>
+// CHECK:   %[[FPTR_DEREF:.*]] = cir.load deref{{.*}} %[[FPTR_F]]
+// CHECK:   %[[FPTR_LOAD:.*]] = cir.load{{.*}} %[[FPTR_DEREF]]
+// CHECK:   %[[FPTR_PROMOTED:.*]] = cir.cast floating %[[FPTR_LOAD]] : 
!cir.f16 -> !cir.float
+// CHECK:   %[[FPTR_ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float
+// CHECK:   %[[FPTR_DEC:.*]] = cir.fsub %[[FPTR_PROMOTED]], %[[FPTR_ONE]] : 
!cir.float
+// CHECK:   %[[FPTR_UNPROMOTED:.*]] = cir.cast floating %[[FPTR_DEC]] : 
!cir.float -> !cir.f16
+
+// LLVM: define{{.*}} void @_Z14fp16PtrUPreDecPDh({{.*}})
+// LLVM:   %[[FPTR_LOAD:.*]] = load half, ptr %{{.*}}, align 2
+// LLVM:   %[[FPTR_PROMOTED:.*]] = fpext half %[[FPTR_LOAD]] to float
+// LLVM:   %[[FPTR_DEC:.*]] = fsub float %[[FPTR_PROMOTED]], 1.000000e+00
+// LLVM:   %[[FPTR_UNPROMOTED:.*]] = fptrunc float %[[FPTR_DEC]] to half
+
+// OGCG: define{{.*}} void @_Z14fp16PtrUPreDecPDh({{.*}})
+// OGCG:   %[[FPTR_LOAD:.*]] = load half, ptr %{{.*}}, align 2
+// OGCG:   %[[FPTR_PROMOTED:.*]] = fpext half %[[FPTR_LOAD]] to float
+// OGCG:   %[[FPTR_DEC:.*]] = fadd float %[[FPTR_PROMOTED]], -1.000000e+00
+// OGCG:   %[[FPTR_UNPROMOTED:.*]] = fptrunc float %[[FPTR_DEC]] to half
+
+void fp16PtrUPostInc(__fp16 *f) {
+  (*f)++;
+}
+
+// CHECK: cir.func{{.*}} @_Z15fp16PtrUPostIncPDh({{.*}})
+// CHECK:   %[[FPTR_F:.*]] = cir.alloca "f" {{.*}} init : 
!cir.ptr<!cir.ptr<!cir.f16>>
+// CHECK:   %[[FPTR_DEREF:.*]] = cir.load deref{{.*}} %[[FPTR_F]]
+// CHECK:   %[[FPTR_LOAD:.*]] = cir.load{{.*}} %[[FPTR_DEREF]]
+// CHECK:   %[[FPTR_PROMOTED:.*]] = cir.cast floating %[[FPTR_LOAD]] : 
!cir.f16 -> !cir.float
+// CHECK:   %[[FPTR_ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float
+// CHECK:   %[[FPTR_INC:.*]] = cir.fadd %[[FPTR_PROMOTED]], %[[FPTR_ONE]] : 
!cir.float
+// CHECK:   %[[FPTR_UNPROMOTED:.*]] = cir.cast floating %[[FPTR_DEC]] : 
!cir.float -> !cir.f16
+
+// LLVM: define{{.*}} void @_Z15fp16PtrUPostIncPDh({{.*}})
+// LLVM:   %[[FPTR_LOAD:.*]] = load half, ptr %{{.*}}, align 2
+// LLVM:   %[[FPTR_PROMOTED:.*]] = fpext half %[[FPTR_LOAD]] to float
+// LLVM:   %[[FPTR_INC:.*]] = fadd float %[[FPTR_PROMOTED]], 1.000000e+00
+// LLVM:   %[[FPTR_UNPROMOTED:.*]] = fptrunc float %[[FPTR_INC]] to half
+
+// OGCG: define{{.*}} void @_Z15fp16PtrUPostIncPDh({{.*}})
+// OGCG:   %[[FPTR_LOAD:.*]] = load half, ptr %{{.*}}, align 2
+// OGCG:   %[[FPTR_PROMOTED:.*]] = fpext half %[[FPTR_LOAD]] to float
+// OGCG:   %[[FPTR_INC:.*]] = fadd float %[[FPTR_PROMOTED]], 1.000000e+00
+// OGCG:   %[[FPTR_UNPROMOTED:.*]] = fptrunc float %[[FPTR_INC]] to half
+
+void fp16PtrUPostDec(__fp16 *f) {
+  (*f)--;
+}
+
+// CHECK: cir.func{{.*}} @_Z15fp16PtrUPostDecPDh({{.*}})
+// CHECK:   %[[FPTR_F:.*]] = cir.alloca "f" {{.*}} init : 
!cir.ptr<!cir.ptr<!cir.f16>>
+// CHECK:   %[[FPTR_DEREF:.*]] = cir.load deref{{.*}} %[[FPTR_F]]
+// CHECK:   %[[FPTR_LOAD:.*]] = cir.load{{.*}} %[[FPTR_DEREF]]
+// CHECK:   %[[FPTR_PROMOTED:.*]] = cir.cast floating %[[FPTR_LOAD]] : 
!cir.f16 -> !cir.float
+// CHECK:   %[[FPTR_ONE:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float
+// CHECK:   %[[FPTR_DEC:.*]] = cir.fsub %[[FPTR_PROMOTED]], %[[FPTR_ONE]] : 
!cir.float
+// CHECK:   %[[FPTR_UNPROMOTED:.*]] = cir.cast floating %[[FPTR_DEC]] : 
!cir.float -> !cir.f16
+
+// LLVM: define{{.*}} void @_Z15fp16PtrUPostDecPDh({{.*}})
+// LLVM:   %[[FPTR_LOAD:.*]] = load half, ptr %{{.*}}, align 2
+// LLVM:   %[[FPTR_PROMOTED:.*]] = fpext half %[[FPTR_LOAD]] to float
+// LLVM:   %[[FPTR_DEC:.*]] = fsub float %[[FPTR_PROMOTED]], 1.000000e+00
+// LLVM:   %[[FPTR_UNPROMOTED:.*]] = fptrunc float %[[FPTR_DEC]] to half
+
+// OGCG: define{{.*}} void @_Z15fp16PtrUPostDecPDh({{.*}})
+// OGCG:   %[[FPTR_LOAD:.*]] = load half, ptr %{{.*}}, align 2
+// OGCG:   %[[FPTR_PROMOTED:.*]] = fpext half %[[FPTR_LOAD]] to float
+// OGCG:   %[[FPTR_DEC:.*]] = fadd float %[[FPTR_PROMOTED]], -1.000000e+00
+// OGCG:   %[[FPTR_UNPROMOTED:.*]] = fptrunc float %[[FPTR_DEC]] to half
+
+// __bf16 unary operations
+__bf16 bf16UPlus(__bf16 f) {
+  return +f;
+}
+
+// CHECK: cir.func{{.*}} @_Z9bf16UPlusDF16b({{.*}}) -> (!cir.bf16{{.*}})
+// CHECK:   %[[BF16_F:.*]] = cir.alloca "f" {{.*}} init : !cir.ptr<!cir.bf16>
+// CHECK:   %[[BF16_LOAD:.*]] = cir.load{{.*}} %[[BF16_F]]
+// CHECK:   %[[BF16_PROMOTED:.*]] = cir.cast floating %[[BF16_LOAD]] : 
!cir.bf16 -> !cir.float
+// CHECK:   %[[BF16_UNPROMOTED:.*]] = cir.cast floating %[[BF16_PROMOTED]] : 
!cir.float -> !cir.bf16
+
+// LLVM: define{{.*}} bfloat @_Z9bf16UPlusDF16b({{.*}})
+// LLVM:   %[[BF16_LOAD:.*]] = load bfloat, ptr %{{.*}}, align 2
+// LLVM:   %[[BF16_PROMOTED:.*]] = fpext bfloat %[[BF16_LOAD]] to float
+// LLVM:   %[[BF16_UNPROMOTED:.*]] = fptrunc float %[[BF16_PROMOTED]] to bfloat
+
+// OGCG: define{{.*}} bfloat @_Z9bf16UPlusDF16b({{.*}})
+// OGCG:   %[[BF16_LOAD:.*]] = load bfloat, ptr %{{.*}}, align 2
+// OGCG:   %[[BF16_PROMOTED:.*]] = fpext bfloat %[[BF16_LOAD]] to float
+// OGCG:   %[[BF16_UNPROMOTED:.*]] = fptrunc float %[[BF16_PROMOTED]] to bfloat
+
+__bf16 bf16UMinus(__bf16 f) {
+  return -f;
+}
+
+// CHECK: cir.func{{.*}} @_Z10bf16UMinusDF16b({{.*}}) -> (!cir.bf16{{.*}})
+// CHECK:   %[[BF16_F:.*]] = cir.alloca "f" {{.*}} init : !cir.ptr<!cir.bf16>
+// CHECK:   %[[BF16_LOAD:.*]] = cir.load{{.*}} %[[BF16_F]]
+// CHECK:   %[[BF16_PROMOTED:.*]] = cir.cast floating %[[BF16_LOAD]] : 
!cir.bf16 -> !cir.float
+// CHECK:   %[[BF16_NEGATED:.*]] = cir.fneg %[[BF16_PROMOTED]]
+// CHECK:   %[[BF16_UNPROMOTED:.*]] = cir.cast floating %[[BF16_NEGATED]] : 
!cir.float -> !cir.bf16
+
+// LLVM: define{{.*}} bfloat @_Z10bf16UMinusDF16b({{.*}})
+// LLVM:   %[[BF16_LOAD:.*]] = load bfloat, ptr %{{.*}}, align 2
+// LLVM:   %[[BF16_PROMOTED:.*]] = fpext bfloat %[[BF16_LOAD]] to float
+// LLVM:   %[[BF16_NEGATED:.*]] = fneg float %[[BF16_PROMOTED]]
+// LLVM:   %[[BF16_UNPROMOTED:.*]] = fptrunc float %[[BF16_NEGATED]] to bfloat
+
+// OGCG: define{{.*}} bfloat @_Z10bf16UMinusDF16b({{.*}})
+// OGCG:   %[[BF16_LOAD:.*]] = load bfloat, ptr %{{.*}}, align 2
+// OGCG:   %[[BF16_PROMOTED:.*]] = fpext bfloat %[[BF16_LOAD]] to float
+// OGCG:   %[[BF16_NEGATED:.*]] = fneg float %[[BF16_PROMOTED]]
+// OGCG:   %[[BF16_UNPROMOTED:.*]] = fptrunc float %[[BF16_NEGATED]] to bfloat
+
+__bf16 bf16UPreInc(__bf16 f) {
+  return ++f;
+}
+
+// CHECK: cir.func{{.*}} @_Z11bf16UPreIncDF16b({{.*}}) -> (!cir.bf16{{.*}})
+// CHECK:   %[[BF16_F:.*]] = cir.alloca "f" {{.*}} init : !cir.ptr<!cir.bf16>
+// CHECK:   %[[BF16_LOAD:.*]] = cir.load{{.*}} %[[BF16_F]]
+// CHECK:   %[[BF16_INC:.*]] = cir.fadd %[[BF16_LOAD]], %{{.*}} : !cir.bf16
+
+// LLVM: define{{.*}} bfloat @_Z11bf16UPreIncDF16b({{.*}})
+// LLVM:   %[[BF16_LOAD:.*]] = load bfloat, ptr %{{.*}}, align 2
+// LLVM:   %[[BF16_INC:.*]] = fadd bfloat %[[BF16_LOAD]], 1.000000e+00
+
+// OGCG: define{{.*}} bfloat @_Z11bf16UPreIncDF16b({{.*}})
+// OGCG:   %[[BF16_LOAD:.*]] = load bfloat, ptr %{{.*}}, align 2
+// OGCG:   %[[BF16_INC:.*]] = fadd bfloat %[[BF16_LOAD]], 1.000000e+00
+
+__bf16 bf16UPreDec(__bf16 f) {
+  return --f;
+}
+
+// CHECK: cir.func{{.*}} @_Z11bf16UPreDecDF16b({{.*}}) -> (!cir.bf16{{.*}})
+// CHECK:   %[[BF16_F:.*]] = cir.alloca "f" {{.*}} init : !cir.ptr<!cir.bf16>
+// CHECK:   %[[BF16_LOAD:.*]] = cir.load{{.*}} %[[BF16_F]]
+// CHECK:   %[[BF16_DEC:.*]] = cir.fsub %[[BF16_LOAD]], %{{.*}} : !cir.bf16
+
+// LLVM: define{{.*}} bfloat @_Z11bf16UPreDecDF16b({{.*}})
+// LLVM:   %[[BF16_LOAD:.*]] = load bfloat, ptr %{{.*}}, align 2
+// LLVM:   %[[BF16_DEC:.*]] = fsub bfloat %[[BF16_LOAD]], 1.000000e+00
+
+// OGCG: define{{.*}} bfloat @_Z11bf16UPreDecDF16b({{.*}})
+// OGCG:   %[[BF16_LOAD:.*]] = load bfloat, ptr %{{.*}}, align 2
+// OGCG:   %[[BF16_DEC:.*]] = fadd bfloat %[[BF16_LOAD]], -1.000000e+00
+
+__bf16 bf16UPostInc(__bf16 f) {
+  return f++;
+}
+
+// CHECK: cir.func{{.*}} @_Z12bf16UPostIncDF16b({{.*}}) -> (!cir.bf16{{.*}})
+// CHECK:   %[[BF16_F:.*]] = cir.alloca "f" {{.*}} init : !cir.ptr<!cir.bf16>
+// CHECK:   %[[BF16_LOAD:.*]] = cir.load{{.*}} %[[BF16_F]]
+// CHECK:   %[[BF16_INC:.*]] = cir.fadd %[[BF16_LOAD]], %{{.*}} : !cir.bf16
+
+// LLVM: define{{.*}} bfloat @_Z12bf16UPostIncDF16b({{.*}})
+// LLVM:   %[[BF16_LOAD:.*]] = load bfloat, ptr %{{.*}}, align 2
+// LLVM:   %[[BF16_INC:.*]] = fadd bfloat %[[BF16_LOAD]], 1.000000e+00
+
+// OGCG: define{{.*}} bfloat @_Z12bf16UPostIncDF16b({{.*}})
+// OGCG:   %[[BF16_LOAD:.*]] = load bfloat, ptr %{{.*}}, align 2
+// OGCG:   %[[BF16_INC:.*]] = fadd bfloat %[[BF16_LOAD]], 1.000000e+00
+
+__bf16 bf16UPostDec(__bf16 f) {
+  return f--;
+}
+
+// CHECK: cir.func{{.*}} @_Z12bf16UPostDecDF16b({{.*}}) -> (!cir.bf16{{.*}})
+// CHECK:   %[[BF16_F:.*]] = cir.alloca "f" {{.*}} init : !cir.ptr<!cir.bf16>
+// CHECK:   %[[BF16_LOAD:.*]] = cir.load{{.*}} %[[BF16_F]]
+// CHECK:   %[[BF16_DEC:.*]] = cir.fsub %[[BF16_LOAD]], %{{.*}} : !cir.bf16
+
+// LLVM: define{{.*}} bfloat @_Z12bf16UPostDecDF16b({{.*}})
+// LLVM:   %[[BF16_LOAD:.*]] = load bfloat, ptr %{{.*}}, align 2
+// LLVM:   %[[BF16_DEC:.*]] = fsub bfloat %[[BF16_LOAD]], 1.000000e+00
+
+// OGCG: define{{.*}} bfloat @_Z12bf16UPostDecDF16b({{.*}})
+// OGCG:   %[[BF16_LOAD:.*]] = load bfloat, ptr %{{.*}}, align 2
+// OGCG:   %[[BF16_DEC:.*]] = fadd bfloat %[[BF16_LOAD]], -1.000000e+00
+
 void test_logical_not() {
   int a = 5;
   a = !a;

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to