Skip to content

Conversation

@AmrDeveloper
Copy link
Member

Upstream support for FPToFPBuiltin ATanOp

@llvmbot llvmbot added clang Clang issues not falling into any other category ClangIR Anything related to the ClangIR project labels Sep 8, 2025
@llvmbot
Copy link
Member

llvmbot commented Sep 8, 2025

@llvm/pr-subscribers-clangir

@llvm/pr-subscribers-clang

Author: Amr Hesham (AmrDeveloper)

Changes

Upstream support for FPToFPBuiltin ATanOp


Full diff: https://github.com/llvm/llvm-project/pull/157496.diff

5 Files Affected:

  • (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+10)
  • (modified) clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp (+2)
  • (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp (+10)
  • (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h (+9)
  • (modified) clang/test/CIR/CodeGen/builtins-elementwise.c (+26)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 4592078af966b..cd63f0ea63f46 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -3808,6 +3808,16 @@ def CIR_ACosOp : CIR_UnaryFPToFPBuiltinOp<"acos", "ACosOp"> {
   }];
 }
 
+def CIR_ATanOp : CIR_UnaryFPToFPBuiltinOp<"atan", "ATanOp"> {
+  let summary = "Computes the floating-point arcus tangent value";
+  let description = [{
+    `cir.atan` computes the arcus tangent of a floating-point operand
+    and returns a result of the same type.
+
+    Floating-point exceptions are ignored, and it does not set `errno`.
+  }];
+}
+
 def CIR_FAbsOp : CIR_UnaryFPToFPBuiltinOp<"fabs", "FAbsOp"> {
   let summary = "Computes the floating-point absolute value";
   let description = [{
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index b68e91f64dc84..2d14850b4440d 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -360,6 +360,8 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
 
   case Builtin::BI__builtin_elementwise_acos:
     return emitUnaryFPBuiltin<cir::ACosOp>(*this, *e);
+  case Builtin::BI__builtin_elementwise_atan:
+    return emitUnaryFPBuiltin<cir::ATanOp>(*this, *e);
   }
 
   // If this is an alias for a lib function (e.g. __builtin_sin), emit
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index ee9f58c829ca9..4599e39c1b6b7 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -1050,6 +1050,15 @@ mlir::LogicalResult CIRToLLVMBaseClassAddrOpLowering::matchAndRewrite(
   return mlir::success();
 }
 
+mlir::LogicalResult CIRToLLVMATanOpLowering::matchAndRewrite(
+    cir::ATanOp op, OpAdaptor adaptor,
+    mlir::ConversionPatternRewriter &rewriter) const {
+  mlir::Type resTy = typeConverter->convertType(op.getType());
+  rewriter.replaceOpWithNewOp<mlir::LLVM::ATanOp>(op, resTy,
+                                                  adaptor.getOperands()[0]);
+  return mlir::success();
+}
+
 mlir::LogicalResult CIRToLLVMAllocaOpLowering::matchAndRewrite(
     cir::AllocaOp op, OpAdaptor adaptor,
     mlir::ConversionPatternRewriter &rewriter) const {
@@ -2431,6 +2440,7 @@ void ConvertCIRToLLVMPass::runOnOperation() {
                CIRToLLVMAssumeAlignedOpLowering,
                CIRToLLVMAssumeSepStorageOpLowering,
                CIRToLLVMBaseClassAddrOpLowering,
+               CIRToLLVMATanOpLowering,
                CIRToLLVMBinOpLowering,
                CIRToLLVMBitClrsbOpLowering,
                CIRToLLVMBitClzOpLowering,
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
index 2c2aede09b0b2..3c2bcfc978589 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
@@ -736,6 +736,15 @@ class CIRToLLVMACosOpLowering : public mlir::OpConversionPattern<cir::ACosOp> {
                   mlir::ConversionPatternRewriter &) const override;
 };
 
+class CIRToLLVMATanOpLowering : public mlir::OpConversionPattern<cir::ATanOp> {
+public:
+  using mlir::OpConversionPattern<cir::ATanOp>::OpConversionPattern;
+
+  mlir::LogicalResult
+  matchAndRewrite(cir::ATanOp op, OpAdaptor,
+                  mlir::ConversionPatternRewriter &) const override;
+};
+
 class CIRToLLVMInlineAsmOpLowering
     : public mlir::OpConversionPattern<cir::InlineAsmOp> {
   mlir::DataLayout const &dataLayout;
diff --git a/clang/test/CIR/CodeGen/builtins-elementwise.c b/clang/test/CIR/CodeGen/builtins-elementwise.c
index 1898f56a33628..2555c47e76757 100644
--- a/clang/test/CIR/CodeGen/builtins-elementwise.c
+++ b/clang/test/CIR/CodeGen/builtins-elementwise.c
@@ -36,3 +36,29 @@ void test_builtin_elementwise_acos(float f, double d, vfloat4 vf4,
   vd4 = __builtin_elementwise_acos(vd4);
 }
 
+void test_builtin_elementwise_atan(float f, double d, vfloat4 vf4,
+  vdouble4  vd4) {
+  // CIR-LABEL: test_builtin_elementwise_atan
+  // LLVM-LABEL: test_builtin_elementwise_atan
+  // OGCG-LABEL: test_builtin_elementwise_atan
+
+  // CIR: %{{.*}} = cir.atan %{{.*}} : !cir.float
+  // LLVM: %{{.*}} = call float @llvm.atan.f32(float %{{.*}})
+  // OGCG: %{{.*}} = call float @llvm.atan.f32(float %{{.*}})
+  f = __builtin_elementwise_atan(f);
+
+  // CIR: %{{.*}} = cir.atan %{{.*}} : !cir.double
+  // LLVM: %{{.*}} = call double @llvm.atan.f64(double %{{.*}})
+  // OGCG: %{{.*}} = call double @llvm.atan.f64(double %{{.*}})
+  d = __builtin_elementwise_atan(d);
+
+  // CIR: %{{.*}} = cir.atan %{{.*}} : !cir.vector<4 x !cir.float>
+  // LLVM: %{{.*}} = call <4 x float> @llvm.atan.v4f32(<4 x float> %{{.*}})
+  // OGCG: %{{.*}} = call <4 x float> @llvm.atan.v4f32(<4 x float> %{{.*}})
+  vf4 = __builtin_elementwise_atan(vf4);
+
+  // CIR: %{{.*}} = cir.atan %{{.*}} : !cir.vector<4 x !cir.double>
+  // LLVM: %{{.*}} = call <4 x double> @llvm.atan.v4f64(<4 x double> %{{.*}})
+  // OGCG: %{{.*}} = call <4 x double> @llvm.atan.v4f64(<4 x double> %{{.*}})
+  vd4 = __builtin_elementwise_atan(vd4);
+}

Copy link
Contributor

@xlauko xlauko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm, with minor nit.

This should be fixed in other UnaryFPToFPBuiltinOp patterns too.

Comment on lines 1057 to 1058
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
rewriter.replaceOpWithNewOp<mlir::LLVM::ATanOp>(op, resTy,
adaptor.getOperands()[0]);
rewriter.replaceOpWithNewOp<mlir::LLVM::ATanOp>(op, resTy,
adaptor.getSrc());

Copy link
Contributor

@andykaylor andykaylor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@AmrDeveloper AmrDeveloper merged commit 5437d90 into llvm:main Sep 11, 2025
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang Clang issues not falling into any other category ClangIR Anything related to the ClangIR project

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants