https://github.com/adams381 updated 
https://github.com/llvm/llvm-project/pull/178093

>From 6e0249fcf97e047c8c28b0332bfdd0bdb56e765d Mon Sep 17 00:00:00 2001
From: Adam Smith <[email protected]>
Date: Mon, 26 Jan 2026 16:48:11 -0800
Subject: [PATCH 1/5] [CIR] Add non-floating-point builtin intrinsics

Add support for non-FP builtins as a follow-up to the FP math builtins PR:
- Integer abs/labs/llabs with cir.abs operation
- __builtin_unpredictable handling
- Integer elementwise abs support
- Tests: builtin-rotate.c, pred-info-builtins.c, updates to libc.c
  and builtins-elementwise.c

This PR depends on #175233 (FP math builtins) and should be merged after it.
---
 clang/include/clang/CIR/Dialect/IR/CIROps.td  |  29 +++++
 clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp       |  39 +++++-
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp |  11 ++
 clang/test/CIR/CodeGen/builtin-rotate.c       | 118 ++++++++++++++++++
 clang/test/CIR/CodeGen/builtins-elementwise.c |  12 +-
 clang/test/CIR/CodeGen/libc.c                 |  39 ++++++
 clang/test/CIR/CodeGen/pred-info-builtins.c   |  72 +++++++++++
 7 files changed, 317 insertions(+), 3 deletions(-)
 create mode 100644 clang/test/CIR/CodeGen/builtin-rotate.c
 create mode 100644 clang/test/CIR/CodeGen/pred-info-builtins.c

diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index e21a4c3421a1b..5686c0890155f 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -5788,6 +5788,35 @@ def CIR_FAbsOp : CIR_UnaryFPToFPBuiltinOp<"fabs", 
"FAbsOp"> {
   }];
 }
 
+def CIR_AbsOp : CIR_Op<"abs", [Pure, SameOperandsAndResultType]> {
+  let summary = "Computes the absolute value of a signed integer";
+  let description = [{
+    `cir.abs` computes the absolute value of a signed integer or vector
+    of signed integers.
+
+    The `min_is_poison` attribute indicates whether the result value is a
+    poison value if the argument is statically or dynamically the minimum
+    value for the type.
+
+    Example:
+
+    ```mlir
+      %0 = cir.const #cir.int<-42> : s32i
+      %1 = cir.abs %0 min_is_poison : s32i
+      %2 = cir.abs %3 : !cir.vector<!s32i x 4>
+    ```
+  }];
+
+  let arguments = (ins
+    CIR_AnySIntOrVecOfSIntType:$src,
+    UnitAttr:$min_is_poison
+  );
+
+  let results = (outs CIR_AnySIntOrVecOfSIntType:$result);
+
+  let assemblyFormat = "$src ( `min_is_poison` $min_is_poison^ )? `:` 
type($src) attr-dict";
+}
+
 def CIR_FloorOp : CIR_UnaryFPToFPBuiltinOp<"floor", "FloorOp"> {
   let summary = "Computes the floating-point floor value";
   let description = [{
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp 
b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index 196dab7a38dd7..8525e06af1c9d 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -965,6 +965,34 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl 
&gd, unsigned builtinID,
     return {};
   }
 
+  case Builtin::BIabs:
+  case Builtin::BIlabs:
+  case Builtin::BIllabs:
+  case Builtin::BI__builtin_abs:
+  case Builtin::BI__builtin_labs:
+  case Builtin::BI__builtin_llabs: {
+    bool sanitizeOverflow = sanOpts.has(SanitizerKind::SignedIntegerOverflow);
+    mlir::Value arg = emitScalarExpr(e->getArg(0));
+    mlir::Value result;
+    switch (getLangOpts().getSignedOverflowBehavior()) {
+    case LangOptions::SOB_Defined:
+      result = cir::AbsOp::create(builder, loc, arg.getType(), arg,
+                                  /*minIsPoison=*/false);
+      break;
+    case LangOptions::SOB_Undefined:
+      if (!sanitizeOverflow) {
+        result = cir::AbsOp::create(builder, loc, arg.getType(), arg,
+                                    /*minIsPoison=*/true);
+        break;
+      }
+      [[fallthrough]];
+    case LangOptions::SOB_Trapping:
+      cgm.errorNYI(e->getSourceRange(), "abs with overflow handling");
+      return RValue::get(nullptr);
+    }
+    return RValue::get(result);
+  }
+
   case Builtin::BI__assume:
   case Builtin::BI__builtin_assume: {
     if (e->getArg(0)->HasSideEffects(getContext()))
@@ -1087,6 +1115,11 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl 
&gd, unsigned builtinID,
   case Builtin::BI__builtin_popcountg:
     return emitBuiltinBitOp<cir::BitPopcountOp>(*this, e);
 
+  case Builtin::BI__builtin_unpredictable: {
+    assert(!cir::MissingFeatures::insertBuiltinUnpredictable());
+    return RValue::get(emitScalarExpr(e->getArg(0)));
+  }
+
   case Builtin::BI__builtin_expect:
   case Builtin::BI__builtin_expect_with_probability: {
     mlir::Value argValue = emitScalarExpr(e->getArg(0));
@@ -1381,8 +1414,10 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl 
&gd, unsigned builtinID,
     bool isIntTy = cir::isIntOrVectorOfIntType(cirTy);
     if (!isIntTy)
       return emitUnaryFPBuiltin<cir::FAbsOp>(*this, *e);
-    // Integer abs is not yet implemented
-    return errorBuiltinNYI(*this, e, builtinID);
+    mlir::Value arg = emitScalarExpr(e->getArg(0));
+    mlir::Value result = cir::AbsOp::create(builder, getLoc(e->getExprLoc()),
+                                            arg.getType(), arg, false);
+    return RValue::get(result);
   }
   case Builtin::BI__builtin_elementwise_acos:
     return emitUnaryMaybeConstrainedFPBuiltin<cir::ACosOp>(*this, *e);
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 28b3454d20613..b1efbe1c15094 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -2278,6 +2278,17 @@ mlir::LogicalResult 
CIRToLLVMFAbsOpLowering::matchAndRewrite(
   return mlir::success();
 }
 
+mlir::LogicalResult CIRToLLVMAbsOpLowering::matchAndRewrite(
+    cir::AbsOp op, OpAdaptor adaptor,
+    mlir::ConversionPatternRewriter &rewriter) const {
+  mlir::Type resTy = typeConverter->convertType(op.getType());
+  auto absOp = mlir::LLVM::AbsOp::create(rewriter, op.getLoc(), resTy,
+                                         adaptor.getOperands()[0],
+                                         adaptor.getMinIsPoison());
+  rewriter.replaceOp(op, absOp);
+  return mlir::success();
+}
+
 /// Convert the `cir.func` attributes to `llvm.func` attributes.
 /// Only retain those attributes that are not constructed by
 /// `LLVMFuncOp::build`. If `filterArgAttrs` is set, also filter out
diff --git a/clang/test/CIR/CodeGen/builtin-rotate.c 
b/clang/test/CIR/CodeGen/builtin-rotate.c
new file mode 100644
index 0000000000000..9f69e76f96148
--- /dev/null
+++ b/clang/test/CIR/CodeGen/builtin-rotate.c
@@ -0,0 +1,118 @@
+// RUN: %clang_cc1 -triple aarch64-none-linux-android21 -fclangir -emit-cir %s 
-o %t.cir
+// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
+// RUN: %clang_cc1 -triple aarch64-none-linux-android21 -fclangir -emit-llvm 
%s -o %t-cir.ll
+// RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s
+// RUN: %clang_cc1 -triple aarch64-none-linux-android21 -emit-llvm %s -o %t.ll
+// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s
+
+void f() {
+// CIR-LABEL: @f
+// LLVM-LABEL: @f
+// OGCG-LABEL: @f
+  unsigned int v[4];
+  unsigned int h = __builtin_rotateleft32(v[0], 1);
+// CIR: %[[CONST:.*]] = cir.const #cir.int<1> : !u32i
+// CIR: cir.rotate left {{.*}}, %[[CONST]] : !u32i
+
+// LLVM: %[[SRC:.*]] = load i32, ptr
+// LLVM: call i32 @llvm.fshl.i32(i32 %[[SRC]], i32 %[[SRC]], i32 1)
+
+// OGCG: %[[SRC:.*]] = load i32, ptr
+// OGCG: call i32 @llvm.fshl.i32(i32 %[[SRC]], i32 %[[SRC]], i32 1)
+}
+
+unsigned char rotl8(unsigned char x, unsigned char y) {
+// CIR-LABEL: rotl8
+// CIR: cir.rotate left {{.*}}, {{.*}} : !u8i
+
+// LLVM-LABEL: rotl8
+// LLVM: [[F:%.*]] = call i8 @llvm.fshl.i8(i8 [[X:%.*]], i8 [[X]], i8 
[[Y:%.*]])
+
+// OGCG-LABEL: rotl8
+// OGCG: call i8 @llvm.fshl.i8(i8 {{.*}}, i8 {{.*}}, i8 {{.*}})
+  return __builtin_rotateleft8(x, y);
+}
+
+short rotl16(short x, short y) {
+// CIR-LABEL: rotl16
+// CIR: cir.rotate left {{.*}}, {{.*}} : !u16i
+
+// LLVM-LABEL: rotl16
+// LLVM: [[F:%.*]] = call i16 @llvm.fshl.i16(i16 [[X:%.*]], i16 [[X]], i16 
[[Y:%.*]])
+
+// OGCG-LABEL: rotl16
+// OGCG: call i16 @llvm.fshl.i16(i16 {{.*}}, i16 {{.*}}, i16 {{.*}})
+  return __builtin_rotateleft16(x, y);
+}
+
+int rotl32(int x, unsigned int y) {
+// CIR-LABEL: rotl32
+// CIR: cir.rotate left {{.*}}, {{.*}} : !u32i
+
+// LLVM-LABEL: rotl32
+// LLVM: [[F:%.*]] = call i32 @llvm.fshl.i32(i32 [[X:%.*]], i32 [[X]], i32 
[[Y:%.*]])
+
+// OGCG-LABEL: rotl32
+// OGCG: call i32 @llvm.fshl.i32(i32 {{.*}}, i32 {{.*}}, i32 {{.*}})
+  return __builtin_rotateleft32(x, y);
+}
+
+unsigned long long rotl64(unsigned long long x, long long y) {
+// CIR-LABEL: rotl64
+// CIR: cir.rotate left {{.*}}, {{.*}} : !u64i
+
+// LLVM-LABEL: rotl64
+// LLVM: [[F:%.*]] = call i64 @llvm.fshl.i64(i64 [[X:%.*]], i64 [[X]], i64 
[[Y:%.*]])
+
+// OGCG-LABEL: rotl64
+// OGCG: call i64 @llvm.fshl.i64(i64 {{.*}}, i64 {{.*}}, i64 {{.*}})
+  return __builtin_rotateleft64(x, y);
+}
+
+char rotr8(char x, char y) {
+// CIR-LABEL: rotr8
+// CIR: cir.rotate right {{.*}}, {{.*}} : !u8i
+
+// LLVM-LABEL: rotr8
+// LLVM: [[F:%.*]] = call i8 @llvm.fshr.i8(i8 [[X:%.*]], i8 [[X]], i8 
[[Y:%.*]])
+
+// OGCG-LABEL: rotr8
+// OGCG: call i8 @llvm.fshr.i8(i8 {{.*}}, i8 {{.*}}, i8 {{.*}})
+  return __builtin_rotateright8(x, y);
+}
+
+unsigned short rotr16(unsigned short x, unsigned short y) {
+// CIR-LABEL: rotr16
+// CIR: cir.rotate right {{.*}}, {{.*}} : !u16i
+
+// LLVM-LABEL: rotr16
+// LLVM: [[F:%.*]] = call i16 @llvm.fshr.i16(i16 [[X:%.*]], i16 [[X]], i16 
[[Y:%.*]])
+
+// OGCG-LABEL: rotr16
+// OGCG: call i16 @llvm.fshr.i16(i16 {{.*}}, i16 {{.*}}, i16 {{.*}})
+  return __builtin_rotateright16(x, y);
+}
+
+unsigned int rotr32(unsigned int x, int y) {
+// CIR-LABEL: rotr32
+// CIR: cir.rotate right {{.*}}, {{.*}} : !u32i
+
+// LLVM-LABEL: rotr32
+// LLVM: [[F:%.*]] = call i32 @llvm.fshr.i32(i32 [[X:%.*]], i32 [[X]], i32 
[[Y:%.*]])
+
+// OGCG-LABEL: rotr32
+// OGCG: call i32 @llvm.fshr.i32(i32 {{.*}}, i32 {{.*}}, i32 {{.*}})
+  return __builtin_rotateright32(x, y);
+}
+
+long long rotr64(long long x, unsigned long long y) {
+// CIR-LABEL: rotr64
+// CIR: cir.rotate right {{.*}}, {{.*}} : !u64i
+
+// LLVM-LABEL: rotr64
+// LLVM: [[F:%.*]] = call i64 @llvm.fshr.i64(i64 [[X:%.*]], i64 [[X]], i64 
[[Y:%.*]])
+
+// OGCG-LABEL: rotr64
+// OGCG: call i64 @llvm.fshr.i64(i64 {{.*}}, i64 {{.*}}, i64 {{.*}})
+  return __builtin_rotateright64(x, y);
+}
\ No newline at end of file
diff --git a/clang/test/CIR/CodeGen/builtins-elementwise.c 
b/clang/test/CIR/CodeGen/builtins-elementwise.c
index 3ca46e1fe3f4a..6c31ce19788d9 100644
--- a/clang/test/CIR/CodeGen/builtins-elementwise.c
+++ b/clang/test/CIR/CodeGen/builtins-elementwise.c
@@ -10,7 +10,7 @@ typedef int vint4 __attribute__((ext_vector_type(4)));
 typedef float vfloat4 __attribute__((ext_vector_type(4)));
 typedef double vdouble4 __attribute__((ext_vector_type(4)));
 
-void test_builtin_elementwise_abs(float f, double d,
+void test_builtin_elementwise_abs(vint4 vi4, int i, float f, double d,
                                   vfloat4 vf4, vdouble4  vd4) {
     // CIR-LABEL: test_builtin_elementwise_abs
     // LLVM-LABEL: test_builtin_elementwise_abs
@@ -25,6 +25,16 @@ void test_builtin_elementwise_abs(float f, double d,
     // OGCG: {{%.*}} = call double @llvm.fabs.f64(double {{%.*}})
     d = __builtin_elementwise_abs(d);
 
+    // CIR: {{%.*}} = cir.abs {{%.*}} : !cir.vector<4 x !s32i>
+    // LLVM: {{%.*}} = call <4 x i32> @llvm.abs.v4i32(<4 x i32> {{%.*}}, i1 
false)
+    // OGCG: {{%.*}} = call <4 x i32> @llvm.abs.v4i32(<4 x i32> {{%.*}}, i1 
false)
+    vi4 = __builtin_elementwise_abs(vi4);
+
+    // CIR: {{%.*}} = cir.abs {{%.*}} : !s32
+    // LLVM: {{%.*}} = call i32 @llvm.abs.i32(i32 {{%.*}}, i1 false)
+    // OGCG: {{%.*}} = call i32 @llvm.abs.i32(i32 {{%.*}}, i1 false)
+    i = __builtin_elementwise_abs(i);
+
     // CIR: {{%.*}} = cir.fabs {{%.*}} : !cir.vector<4 x !cir.float>
     // LLVM: {{%.*}} = call <4 x float> @llvm.fabs.v4f32(<4 x float> {{%.*}})
     // OGCG: {{%.*}} = call <4 x float> @llvm.fabs.v4f32(<4 x float> {{%.*}})
diff --git a/clang/test/CIR/CodeGen/libc.c b/clang/test/CIR/CodeGen/libc.c
index 6bd2bca33de57..1964cf5ddb06a 100644
--- a/clang/test/CIR/CodeGen/libc.c
+++ b/clang/test/CIR/CodeGen/libc.c
@@ -1,5 +1,14 @@
 // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o 
%t.cir
 // RUN: FileCheck --input-file=%t.cir %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o 
%t.ll
+// RUN: FileCheck --check-prefix=LLVM --input-file=%t.ll %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t-ogcg.ll
+// RUN: FileCheck --check-prefix=OGCG --input-file=%t-ogcg.ll %s
+
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o 
%t.cir -fwrapv
+// RUN: FileCheck --check-prefix=CIR_NO_POISON --input-file=%t.cir %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o 
%t.ll -fwrapv
+// RUN: FileCheck --check-prefix=LLVM_NO_POISON --input-file=%t.ll %s
 
 // Note: In the final implementation, we will want these to generate
 // CIR-specific libc operations. This test is just a placeholder
@@ -35,3 +44,33 @@ float testFabsf(float x) {
   return fabsf(x);
   // CHECK: cir.fabs %{{.+}} : !cir.float
 }
+
+int abs(int);
+int testAbs(int x) {
+  return abs(x);
+  // CHECK: cir.abs %{{.+}} min_is_poison : !s32i
+  // LLVM: %{{.+}} = call i32 @llvm.abs.i32(i32 %{{.+}}, i1 true)
+  // OGCG: %{{.+}} = call i32 @llvm.abs.i32(i32 %{{.+}}, i1 true)
+  // CIR_NO_POISON: cir.abs %{{.+}} : !s32i
+  // LLVM_NO_POISON: %{{.+}} = call i32 @llvm.abs.i32(i32 %{{.+}}, i1 false)
+}
+
+long labs(long);
+long testLabs(long x) {
+  return labs(x);
+  // CHECK: cir.abs %{{.+}} min_is_poison : !s64i
+  // LLVM: %{{.+}} = call i64 @llvm.abs.i64(i64 %{{.+}}, i1 true)
+  // OGCG: %{{.+}} = call i64 @llvm.abs.i64(i64 %{{.+}}, i1 true)
+  // CIR_NO_POISON: cir.abs %{{.+}} : !s64i
+  // LLVM_NO_POISON: %{{.+}} = call i64 @llvm.abs.i64(i64 %{{.+}}, i1 false)
+}
+
+long long llabs(long long);
+long long testLlabs(long long x) {
+  return llabs(x);
+  // CHECK: cir.abs %{{.+}} min_is_poison : !s64i
+  // LLVM: %{{.+}} = call i64 @llvm.abs.i64(i64 %{{.+}}, i1 true)
+  // OGCG: %{{.+}} = call i64 @llvm.abs.i64(i64 %{{.+}}, i1 true)
+  // CIR_NO_POISON: cir.abs %{{.+}} : !s64i
+  // LLVM_NO_POISON: %{{.+}} = call i64 @llvm.abs.i64(i64 %{{.+}}, i1 false)
+}
diff --git a/clang/test/CIR/CodeGen/pred-info-builtins.c 
b/clang/test/CIR/CodeGen/pred-info-builtins.c
new file mode 100644
index 0000000000000..da9d42dc109f4
--- /dev/null
+++ b/clang/test/CIR/CodeGen/pred-info-builtins.c
@@ -0,0 +1,72 @@
+// RUN: %clang_cc1 -O0 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s 
-o - | FileCheck %s --check-prefix=CIR-O0
+// RUN: %clang_cc1 -O2 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s 
-o - | FileCheck %s --check-prefix=CIR-O2
+// RUN: %clang_cc1 -O0 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm 
%s -o - | FileCheck %s --check-prefix=LLVM
+// RUN: %clang_cc1 -O0 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o - | 
FileCheck %s --check-prefix=OGCG
+
+extern void __attribute__((noinline)) bar(void);
+
+void expect(int x) {
+  if (__builtin_expect(x, 0))
+    bar();
+}
+// CIR-O0: cir.func dso_local @expect
+// CIR-O0:   cir.if {{%.*}} {
+// CIR-O0:     cir.call @bar() : () -> ()
+
+// CIR-O2: cir.func dso_local @expect
+// CIR-O2:   [[EXPECT:%.*]] = cir.expect({{.*}}, {{.*}}) : !s64i
+// CIR-O2:   [[EXPECT_BOOL:%.*]] = cir.cast int_to_bool [[EXPECT]] : !s64i -> 
!cir.bool
+// CIR-O2:   cir.if [[EXPECT_BOOL]]
+// CIR-O2:     cir.call @bar() : () -> ()
+
+// LLVM-LABEL: @expect
+// LLVM: br i1 {{.*}}, label %[[THEN:.*]], label %[[END:.*]]
+// LLVM: [[THEN]]:
+// LLVM: call void @bar()
+
+// OGCG-LABEL: @expect
+// OGCG: br i1 {{.*}}, label %[[THEN:.*]], label %[[END:.*]]
+// OGCG: [[THEN]]:
+// OGCG: call void @bar()
+
+void expect_with_probability(int x) {
+  if (__builtin_expect_with_probability(x, 1, 0.8))
+    bar();
+}
+// CIR-O0: cir.func dso_local @expect_with_probability
+// CIR-O0:   cir.if {{%.*}} {
+// CIR-O0:     cir.call @bar() : () -> ()
+
+// CIR-O2:  cir.func dso_local @expect_with_probability
+// CIR-O2:    [[EXPECT:%.*]] = cir.expect({{.*}}, {{.*}}, 8.000000e-01) : !s64i
+// CIR-O2:    [[EXPECT_BOOL:%.*]] = cir.cast int_to_bool [[EXPECT]] : !s64i -> 
!cir.bool
+// CIR-O2:    cir.if [[EXPECT_BOOL]]
+// CIR-O2:      cir.call @bar() : () -> ()
+
+// LLVM-LABEL: @expect_with_probability
+// LLVM: br i1 {{.*}}, label %[[THEN:.*]], label %[[END:.*]]
+// LLVM: [[THEN]]:
+// LLVM: call void @bar()
+
+// OGCG-LABEL: @expect_with_probability
+// OGCG: br i1 {{.*}}, label %[[THEN:.*]], label %[[END:.*]]
+// OGCG: [[THEN]]:
+// OGCG: call void @bar()
+
+void unpredictable(int x) {
+  if (__builtin_unpredictable(x > 1))
+    bar();
+}
+// CIR-O0: cir.func dso_local @unpredictable
+// CIR-O0:   cir.if {{%.*}} {
+// CIR-O0:     cir.call @bar() : () -> ()
+
+// LLVM-LABEL: @unpredictable
+// LLVM: br i1 {{.*}}, label %[[THEN:.*]], label %[[END:.*]]
+// LLVM: [[THEN]]:
+// LLVM: call void @bar()
+
+// OGCG-LABEL: @unpredictable
+// OGCG: br i1 {{.*}}, label %[[THEN:.*]], label %[[END:.*]]
+// OGCG: [[THEN]]:
+// OGCG: call void @bar()

>From c0d122679bfc6b1d2ddd1cf69842789e426d3db4 Mon Sep 17 00:00:00 2001
From: Adam Smith <[email protected]>
Date: Fri, 13 Feb 2026 10:30:54 -0800
Subject: [PATCH 2/5] [CIR] Fix pred-info-builtins no_inline

At -O0, CIR now adds no_inline to non-always_inline functions to match
classic codegen. Update the three CHECK lines in pred-info-builtins.c
to expect "cir.func no_inline dso_local" instead of "cir.func dso_local" for
@expect, @expect_with_probability, and @unpredictable so the test passes
after the noinline fix merged in #175233.

Co-authored-by: Cursor <[email protected]>
---
 clang/test/CIR/CodeGen/pred-info-builtins.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/clang/test/CIR/CodeGen/pred-info-builtins.c 
b/clang/test/CIR/CodeGen/pred-info-builtins.c
index da9d42dc109f4..f13d4afee966f 100644
--- a/clang/test/CIR/CodeGen/pred-info-builtins.c
+++ b/clang/test/CIR/CodeGen/pred-info-builtins.c
@@ -9,7 +9,7 @@ void expect(int x) {
   if (__builtin_expect(x, 0))
     bar();
 }
-// CIR-O0: cir.func dso_local @expect
+// CIR-O0: cir.func no_inline dso_local @expect
 // CIR-O0:   cir.if {{%.*}} {
 // CIR-O0:     cir.call @bar() : () -> ()
 
@@ -33,7 +33,7 @@ void expect_with_probability(int x) {
   if (__builtin_expect_with_probability(x, 1, 0.8))
     bar();
 }
-// CIR-O0: cir.func dso_local @expect_with_probability
+// CIR-O0: cir.func no_inline dso_local @expect_with_probability
 // CIR-O0:   cir.if {{%.*}} {
 // CIR-O0:     cir.call @bar() : () -> ()
 
@@ -57,7 +57,7 @@ void unpredictable(int x) {
   if (__builtin_unpredictable(x > 1))
     bar();
 }
-// CIR-O0: cir.func dso_local @unpredictable
+// CIR-O0: cir.func no_inline dso_local @unpredictable
 // CIR-O0:   cir.if {{%.*}} {
 // CIR-O0:     cir.call @bar() : () -> ()
 

>From 3f698f4c46c20ad6c8500271f1456c670fe0c41f Mon Sep 17 00:00:00 2001
From: adams381 <[email protected]>
Date: Fri, 13 Feb 2026 14:42:17 -0600
Subject: [PATCH 3/5] Update clang/test/CIR/CodeGen/pred-info-builtins.c

This will generate code according to the O2 rules without running any LLVM 
optimization passes.

Co-authored-by: Andy Kaylor <[email protected]>
---
 clang/test/CIR/CodeGen/pred-info-builtins.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang/test/CIR/CodeGen/pred-info-builtins.c 
b/clang/test/CIR/CodeGen/pred-info-builtins.c
index f13d4afee966f..f05918f8d0323 100644
--- a/clang/test/CIR/CodeGen/pred-info-builtins.c
+++ b/clang/test/CIR/CodeGen/pred-info-builtins.c
@@ -1,7 +1,7 @@
 // RUN: %clang_cc1 -O0 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s 
-o - | FileCheck %s --check-prefix=CIR-O0
 // RUN: %clang_cc1 -O2 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s 
-o - | FileCheck %s --check-prefix=CIR-O2
-// RUN: %clang_cc1 -O0 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm 
%s -o - | FileCheck %s --check-prefix=LLVM
-// RUN: %clang_cc1 -O0 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o - | 
FileCheck %s --check-prefix=OGCG
+// RUN: %clang_cc1 -O2 -disable-llvm-passes -triple x86_64-unknown-linux-gnu 
-fclangir -emit-llvm %s -o - | FileCheck %s --check-prefix=LLVM
+// RUN: %clang_cc1 -O2 -disable-llvm-passes -triple x86_64-unknown-linux-gnu 
-emit-llvm %s -o - | FileCheck %s --check-prefix=OGCG
 
 extern void __attribute__((noinline)) bar(void);
 

>From 4c3080b10fc4d8076103673c539269972bf67afe Mon Sep 17 00:00:00 2001
From: adams381 <[email protected]>
Date: Fri, 13 Feb 2026 14:43:05 -0600
Subject: [PATCH 4/5] Update clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp

We already have MissingFeatures markers in the places where this should happen.

Co-authored-by: Andy Kaylor <[email protected]>
---
 clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp 
b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index 8525e06af1c9d..b8b5120c0403f 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -1116,7 +1116,10 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl 
&gd, unsigned builtinID,
     return emitBuiltinBitOp<cir::BitPopcountOp>(*this, e);
 
   case Builtin::BI__builtin_unpredictable: {
-    assert(!cir::MissingFeatures::insertBuiltinUnpredictable());
+        // Always return the argument of __builtin_unpredictable. LLVM does not
+        // have an intrinsic corresponding to this builtin. Metadata for this 
builtin
+        // should be added directly to instructions such as branches or 
switches
+        // that use it.
     return RValue::get(emitScalarExpr(e->getArg(0)));
   }
 

>From b982f03a8b9e3f2b1afa79dfa29213d7351bbd41 Mon Sep 17 00:00:00 2001
From: Adam Smith <[email protected]>
Date: Fri, 13 Feb 2026 12:53:18 -0800
Subject: [PATCH 5/5] [CIR] Address reviewer feedback on non-FP builtins PR

CIR-O2 wildcards: use cir.func {{.*}} @... for expect and
expect_with_probability (avoids tying test to dso_local etc.).

CIR-O0-NOT: cir.expect: at -O0 skip emitting ExpectOp; return first arg only.
Re-add CIR-O0-NOT: cir.expect in pred-info-builtins.c.

pred-info vs builtin_call: add header comment in pred-info-builtins.c that this
file focuses on O0 vs O2 CIR and LLVM/OGCG -O2 -disable-llvm-passes;
builtin_call.cpp covers call lowering.

Co-authored-by: Cursor <[email protected]>
---
 clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp           |  7 +++++++
 clang/test/CIR/CodeGen/pred-info-builtins.c       | 15 ++++++++++-----
 .../{CodeGen => CodeGenBuiltins}/builtin-rotate.c |  0
 3 files changed, 17 insertions(+), 5 deletions(-)
 rename clang/test/CIR/{CodeGen => CodeGenBuiltins}/builtin-rotate.c (100%)

diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp 
b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index b8b5120c0403f..388eac7976e3a 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -1115,6 +1115,10 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl 
&gd, unsigned builtinID,
   case Builtin::BI__builtin_popcountg:
     return emitBuiltinBitOp<cir::BitPopcountOp>(*this, e);
 
+  // Always return the argument of __builtin_unpredictable.  LLVM does not
+  // have an intrinsic corresponding to this builtin.  Metadata for this
+  // builtin should be added directly to instructions such as branches or
+  // switches that use it.
   case Builtin::BI__builtin_unpredictable: {
         // Always return the argument of __builtin_unpredictable. LLVM does not
         // have an intrinsic corresponding to this builtin. Metadata for this 
builtin
@@ -1126,6 +1130,9 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl 
&gd, unsigned builtinID,
   case Builtin::BI__builtin_expect:
   case Builtin::BI__builtin_expect_with_probability: {
     mlir::Value argValue = emitScalarExpr(e->getArg(0));
+    if (cgm.getCodeGenOpts().OptimizationLevel == 0)
+      return RValue::get(argValue);
+
     mlir::Value expectedValue = emitScalarExpr(e->getArg(1));
 
     mlir::FloatAttr probAttr;
diff --git a/clang/test/CIR/CodeGen/pred-info-builtins.c 
b/clang/test/CIR/CodeGen/pred-info-builtins.c
index f05918f8d0323..09e6b9013aee7 100644
--- a/clang/test/CIR/CodeGen/pred-info-builtins.c
+++ b/clang/test/CIR/CodeGen/pred-info-builtins.c
@@ -1,4 +1,9 @@
+// Test __builtin_expect, __builtin_expect_with_probability, and 
__builtin_unpredictable.
+// Focus: O0 vs O2 CIR output (no cir.expect at O0), and LLVM/OGCG with -O2 
-disable-llvm-passes.
+// Builtin call lowering is also covered by builtin_call.cpp.
+//
 // RUN: %clang_cc1 -O0 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s 
-o - | FileCheck %s --check-prefix=CIR-O0
+// CIR-O0-NOT: cir.expect
 // RUN: %clang_cc1 -O2 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s 
-o - | FileCheck %s --check-prefix=CIR-O2
 // RUN: %clang_cc1 -O2 -disable-llvm-passes -triple x86_64-unknown-linux-gnu 
-fclangir -emit-llvm %s -o - | FileCheck %s --check-prefix=LLVM
 // RUN: %clang_cc1 -O2 -disable-llvm-passes -triple x86_64-unknown-linux-gnu 
-emit-llvm %s -o - | FileCheck %s --check-prefix=OGCG
@@ -9,11 +14,11 @@ void expect(int x) {
   if (__builtin_expect(x, 0))
     bar();
 }
-// CIR-O0: cir.func no_inline dso_local @expect
+// CIR-O0: cir.func {{.*}} @expect
 // CIR-O0:   cir.if {{%.*}} {
 // CIR-O0:     cir.call @bar() : () -> ()
 
-// CIR-O2: cir.func dso_local @expect
+// CIR-O2: cir.func {{.*}} @expect
 // CIR-O2:   [[EXPECT:%.*]] = cir.expect({{.*}}, {{.*}}) : !s64i
 // CIR-O2:   [[EXPECT_BOOL:%.*]] = cir.cast int_to_bool [[EXPECT]] : !s64i -> 
!cir.bool
 // CIR-O2:   cir.if [[EXPECT_BOOL]]
@@ -33,11 +38,11 @@ void expect_with_probability(int x) {
   if (__builtin_expect_with_probability(x, 1, 0.8))
     bar();
 }
-// CIR-O0: cir.func no_inline dso_local @expect_with_probability
+// CIR-O0: cir.func {{.*}} @expect_with_probability
 // CIR-O0:   cir.if {{%.*}} {
 // CIR-O0:     cir.call @bar() : () -> ()
 
-// CIR-O2:  cir.func dso_local @expect_with_probability
+// CIR-O2:  cir.func {{.*}} @expect_with_probability
 // CIR-O2:    [[EXPECT:%.*]] = cir.expect({{.*}}, {{.*}}, 8.000000e-01) : !s64i
 // CIR-O2:    [[EXPECT_BOOL:%.*]] = cir.cast int_to_bool [[EXPECT]] : !s64i -> 
!cir.bool
 // CIR-O2:    cir.if [[EXPECT_BOOL]]
@@ -57,7 +62,7 @@ void unpredictable(int x) {
   if (__builtin_unpredictable(x > 1))
     bar();
 }
-// CIR-O0: cir.func no_inline dso_local @unpredictable
+// CIR-O0: cir.func {{.*}} @unpredictable
 // CIR-O0:   cir.if {{%.*}} {
 // CIR-O0:     cir.call @bar() : () -> ()
 
diff --git a/clang/test/CIR/CodeGen/builtin-rotate.c 
b/clang/test/CIR/CodeGenBuiltins/builtin-rotate.c
similarity index 100%
rename from clang/test/CIR/CodeGen/builtin-rotate.c
rename to clang/test/CIR/CodeGenBuiltins/builtin-rotate.c

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

Reply via email to