[llvm] [PreISelIntrinsicLowering] Expand binary elementwise intrinsics (#193552) (PR #193580)
Philip Reames via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 23 08:02:18 PDT 2026
https://github.com/preames updated https://github.com/llvm/llvm-project/pull/193580
>From e2d2d4f9155c5f2456bdb311265cf7e7c2042f9a Mon Sep 17 00:00:00 2001
From: Philip Reames <listmail at philipreames.com>
Date: Wed, 22 Apr 2026 13:04:57 -0700
Subject: [PATCH 1/2] [PreISelIntrinsicLowering] Expand all binary elementwise
intrinsics (#193552)
This expands the set of scalable typed binary intrinsics which can be
expanded to match the entire set of builtin element wise routines
provided by clang. Support for the binary ones will follow in a separate
patch.
Note that the lowering quality is terrible, particularly when the libc
entry for the scalar routine doesn't preserve vector registers (e.g.
RISC-V default). This is a functional fix to avoid crashes when trying
to codegen these, nothing more.
Written by Claude, sanity checked by me.
---
.../Transforms/Utils/LowerVectorIntrinsics.h | 4 +
llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp | 16 ++++
llvm/lib/CodeGen/TargetLoweringBase.cpp | 8 ++
.../Utils/LowerVectorIntrinsics.cpp | 54 +++++++++++
.../AArch64/expand-fp-math-binary.ll | 95 +++++++++++++++++++
5 files changed, 177 insertions(+)
create mode 100644 llvm/test/Transforms/PreISelIntrinsicLowering/AArch64/expand-fp-math-binary.ll
diff --git a/llvm/include/llvm/Transforms/Utils/LowerVectorIntrinsics.h b/llvm/include/llvm/Transforms/Utils/LowerVectorIntrinsics.h
index 19b573d6546a0..a1548f54e94b3 100644
--- a/llvm/include/llvm/Transforms/Utils/LowerVectorIntrinsics.h
+++ b/llvm/include/llvm/Transforms/Utils/LowerVectorIntrinsics.h
@@ -24,6 +24,10 @@ class Module;
/// is deleted and replaced with a loop.
bool lowerUnaryVectorIntrinsicAsLoop(Module &M, CallInst *CI);
+/// Lower \p CI as a loop. \p CI is a binary intrinsic with two vector arguments
+/// and is deleted and replaced with a loop.
+bool lowerBinaryVectorIntrinsicAsLoop(Module &M, CallInst *CI);
+
} // namespace llvm
#endif
diff --git a/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp b/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp
index fc80707c76098..4f269f177e550 100644
--- a/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp
+++ b/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp
@@ -810,6 +810,22 @@ bool PreISelIntrinsicLowering::lowerIntrinsics(Module &M) const {
return lowerUnaryVectorIntrinsicAsLoop(M, CI);
});
break;
+ case Intrinsic::atan2:
+ case Intrinsic::ldexp:
+ case Intrinsic::pow:
+ case Intrinsic::powi:
+ Changed |= forEachCall(F, [&](CallInst *CI) {
+ Type *Ty = CI->getArgOperand(0)->getType();
+ if (!TM || !isa<ScalableVectorType>(Ty))
+ return false;
+ const TargetLowering *TL = TM->getSubtargetImpl(F)->getTargetLowering();
+ unsigned Op = TL->IntrinsicIDToISD(F.getIntrinsicID());
+ assert(Op != ISD::DELETED_NODE && "unsupported intrinsic");
+ if (!TL->isOperationExpand(Op, EVT::getEVT(Ty)))
+ return false;
+ return lowerBinaryVectorIntrinsicAsLoop(M, CI);
+ });
+ break;
case Intrinsic::ptrauth_sign:
case Intrinsic::ptrauth_auth:
Changed |= expandPtrauthForEmuPAC(F);
diff --git a/llvm/lib/CodeGen/TargetLoweringBase.cpp b/llvm/lib/CodeGen/TargetLoweringBase.cpp
index b47bf56c38dc4..f0d5b4e1d76a2 100644
--- a/llvm/lib/CodeGen/TargetLoweringBase.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringBase.cpp
@@ -2301,6 +2301,8 @@ int TargetLoweringBase::IntrinsicIDToISD(Intrinsic::ID ID) const {
return ISD::FASIN;
case Intrinsic::atan:
return ISD::FATAN;
+ case Intrinsic::atan2:
+ return ISD::FATAN2;
case Intrinsic::canonicalize:
return ISD::FCANONICALIZE;
case Intrinsic::cos:
@@ -2313,12 +2315,18 @@ int TargetLoweringBase::IntrinsicIDToISD(Intrinsic::ID ID) const {
return ISD::FEXP2;
case Intrinsic::exp10:
return ISD::FEXP10;
+ case Intrinsic::ldexp:
+ return ISD::FLDEXP;
case Intrinsic::log:
return ISD::FLOG;
case Intrinsic::log2:
return ISD::FLOG2;
case Intrinsic::log10:
return ISD::FLOG10;
+ case Intrinsic::pow:
+ return ISD::FPOW;
+ case Intrinsic::powi:
+ return ISD::FPOWI;
case Intrinsic::sin:
return ISD::FSIN;
case Intrinsic::sinh:
diff --git a/llvm/lib/Transforms/Utils/LowerVectorIntrinsics.cpp b/llvm/lib/Transforms/Utils/LowerVectorIntrinsics.cpp
index 71c10f5b157c7..e807b1c2512ae 100644
--- a/llvm/lib/Transforms/Utils/LowerVectorIntrinsics.cpp
+++ b/llvm/lib/Transforms/Utils/LowerVectorIntrinsics.cpp
@@ -59,3 +59,57 @@ bool llvm::lowerUnaryVectorIntrinsicAsLoop(Module &M, CallInst *CI) {
CI->eraseFromParent();
return true;
}
+
+bool llvm::lowerBinaryVectorIntrinsicAsLoop(Module &M, CallInst *CI) {
+ Type *Arg0Ty = CI->getArgOperand(0)->getType();
+ VectorType *VecTy = cast<VectorType>(Arg0Ty);
+ VectorType *Vec1Ty = cast<VectorType>(CI->getArgOperand(1)->getType());
+
+ BasicBlock *PreLoopBB = CI->getParent();
+ BasicBlock *PostLoopBB = nullptr;
+ Function *ParentFunc = PreLoopBB->getParent();
+ LLVMContext &Ctx = PreLoopBB->getContext();
+ Type *Int64Ty = IntegerType::get(Ctx, 64);
+
+ PostLoopBB = PreLoopBB->splitBasicBlock(CI);
+ BasicBlock *LoopBB = BasicBlock::Create(Ctx, "", ParentFunc, PostLoopBB);
+ PreLoopBB->getTerminator()->setSuccessor(0, LoopBB);
+
+ // Loop preheader
+ IRBuilder<> PreLoopBuilder(PreLoopBB->getTerminator());
+ Value *LoopEnd =
+ PreLoopBuilder.CreateElementCount(Int64Ty, VecTy->getElementCount());
+
+ // Loop body
+ IRBuilder<> LoopBuilder(LoopBB);
+
+ PHINode *LoopIndex = LoopBuilder.CreatePHI(Int64Ty, 2);
+ LoopIndex->addIncoming(ConstantInt::get(Int64Ty, 0U), PreLoopBB);
+ PHINode *Vec = LoopBuilder.CreatePHI(VecTy, 2);
+ Vec->addIncoming(CI->getArgOperand(0), PreLoopBB);
+
+ Value *Elem0 = LoopBuilder.CreateExtractElement(Vec, LoopIndex);
+ Value *Elem1 =
+ LoopBuilder.CreateExtractElement(CI->getArgOperand(1), LoopIndex);
+
+ SmallVector<Type *, 2> ScalarArgTys = {VecTy->getElementType()};
+ if (Vec1Ty->getElementType() != VecTy->getElementType())
+ ScalarArgTys.push_back(Vec1Ty->getElementType());
+ Function *ScalarFn =
+ Intrinsic::getOrInsertDeclaration(&M, CI->getIntrinsicID(), ScalarArgTys);
+ Value *Res = LoopBuilder.CreateCall(ScalarFn, {Elem0, Elem1});
+ Value *NewVec = LoopBuilder.CreateInsertElement(Vec, Res, LoopIndex);
+ Vec->addIncoming(NewVec, LoopBB);
+
+ Value *One = ConstantInt::get(Int64Ty, 1U);
+ Value *NextLoopIndex = LoopBuilder.CreateAdd(LoopIndex, One);
+ LoopIndex->addIncoming(NextLoopIndex, LoopBB);
+
+ Value *ExitCond =
+ LoopBuilder.CreateICmp(CmpInst::ICMP_EQ, NextLoopIndex, LoopEnd);
+ LoopBuilder.CreateCondBr(ExitCond, PostLoopBB, LoopBB);
+
+ CI->replaceAllUsesWith(NewVec);
+ CI->eraseFromParent();
+ return true;
+}
diff --git a/llvm/test/Transforms/PreISelIntrinsicLowering/AArch64/expand-fp-math-binary.ll b/llvm/test/Transforms/PreISelIntrinsicLowering/AArch64/expand-fp-math-binary.ll
new file mode 100644
index 0000000000000..0ad57632b787b
--- /dev/null
+++ b/llvm/test/Transforms/PreISelIntrinsicLowering/AArch64/expand-fp-math-binary.ll
@@ -0,0 +1,95 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -passes=pre-isel-intrinsic-lowering -S < %s | FileCheck %s
+target triple = "aarch64"
+
+define <vscale x 4 x float> @scalable_vec_atan2(<vscale x 4 x float> %a, <vscale x 4 x float> %b) {
+; CHECK-LABEL: define <vscale x 4 x float> @scalable_vec_atan2(
+; CHECK-SAME: <vscale x 4 x float> [[A:%.*]], <vscale x 4 x float> [[B:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64()
+; CHECK-NEXT: [[TMP2:%.*]] = mul nuw i64 [[TMP1]], 4
+; CHECK-NEXT: br label %[[BB3:.*]]
+; CHECK: [[BB3]]:
+; CHECK-NEXT: [[TMP4:%.*]] = phi i64 [ 0, [[TMP0:%.*]] ], [ [[TMP10:%.*]], %[[BB3]] ]
+; CHECK-NEXT: [[TMP5:%.*]] = phi <vscale x 4 x float> [ [[A]], [[TMP0]] ], [ [[TMP9:%.*]], %[[BB3]] ]
+; CHECK-NEXT: [[TMP6:%.*]] = extractelement <vscale x 4 x float> [[TMP5]], i64 [[TMP4]]
+; CHECK-NEXT: [[TMP7:%.*]] = extractelement <vscale x 4 x float> [[B]], i64 [[TMP4]]
+; CHECK-NEXT: [[TMP8:%.*]] = call float @llvm.atan2.f32(float [[TMP6]], float [[TMP7]])
+; CHECK-NEXT: [[TMP9]] = insertelement <vscale x 4 x float> [[TMP5]], float [[TMP8]], i64 [[TMP4]]
+; CHECK-NEXT: [[TMP10]] = add i64 [[TMP4]], 1
+; CHECK-NEXT: [[TMP11:%.*]] = icmp eq i64 [[TMP10]], [[TMP2]]
+; CHECK-NEXT: br i1 [[TMP11]], label %[[BB12:.*]], label %[[BB3]]
+; CHECK: [[BB12]]:
+; CHECK-NEXT: ret <vscale x 4 x float> [[TMP9]]
+;
+ %output = call <vscale x 4 x float> @llvm.atan2.nxv4f32(<vscale x 4 x float> %a, <vscale x 4 x float> %b)
+ ret <vscale x 4 x float> %output
+}
+
+define <vscale x 4 x float> @scalable_vec_pow(<vscale x 4 x float> %a, <vscale x 4 x float> %b) {
+; CHECK-LABEL: define <vscale x 4 x float> @scalable_vec_pow(
+; CHECK-SAME: <vscale x 4 x float> [[A:%.*]], <vscale x 4 x float> [[B:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64()
+; CHECK-NEXT: [[TMP2:%.*]] = mul nuw i64 [[TMP1]], 4
+; CHECK-NEXT: br label %[[BB3:.*]]
+; CHECK: [[BB3]]:
+; CHECK-NEXT: [[TMP4:%.*]] = phi i64 [ 0, [[TMP0:%.*]] ], [ [[TMP10:%.*]], %[[BB3]] ]
+; CHECK-NEXT: [[TMP5:%.*]] = phi <vscale x 4 x float> [ [[A]], [[TMP0]] ], [ [[TMP9:%.*]], %[[BB3]] ]
+; CHECK-NEXT: [[TMP6:%.*]] = extractelement <vscale x 4 x float> [[TMP5]], i64 [[TMP4]]
+; CHECK-NEXT: [[TMP7:%.*]] = extractelement <vscale x 4 x float> [[B]], i64 [[TMP4]]
+; CHECK-NEXT: [[TMP8:%.*]] = call float @llvm.pow.f32(float [[TMP6]], float [[TMP7]])
+; CHECK-NEXT: [[TMP9]] = insertelement <vscale x 4 x float> [[TMP5]], float [[TMP8]], i64 [[TMP4]]
+; CHECK-NEXT: [[TMP10]] = add i64 [[TMP4]], 1
+; CHECK-NEXT: [[TMP11:%.*]] = icmp eq i64 [[TMP10]], [[TMP2]]
+; CHECK-NEXT: br i1 [[TMP11]], label %[[BB12:.*]], label %[[BB3]]
+; CHECK: [[BB12]]:
+; CHECK-NEXT: ret <vscale x 4 x float> [[TMP9]]
+;
+ %output = call <vscale x 4 x float> @llvm.pow.nxv4f32(<vscale x 4 x float> %a, <vscale x 4 x float> %b)
+ ret <vscale x 4 x float> %output
+}
+
+define <vscale x 4 x float> @scalable_vec_ldexp(<vscale x 4 x float> %a, <vscale x 4 x i32> %b) {
+; CHECK-LABEL: define <vscale x 4 x float> @scalable_vec_ldexp(
+; CHECK-SAME: <vscale x 4 x float> [[A:%.*]], <vscale x 4 x i32> [[B:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64()
+; CHECK-NEXT: [[TMP2:%.*]] = mul nuw i64 [[TMP1]], 4
+; CHECK-NEXT: br label %[[BB3:.*]]
+; CHECK: [[BB3]]:
+; CHECK-NEXT: [[TMP4:%.*]] = phi i64 [ 0, [[TMP0:%.*]] ], [ [[TMP10:%.*]], %[[BB3]] ]
+; CHECK-NEXT: [[TMP5:%.*]] = phi <vscale x 4 x float> [ [[A]], [[TMP0]] ], [ [[TMP9:%.*]], %[[BB3]] ]
+; CHECK-NEXT: [[TMP6:%.*]] = extractelement <vscale x 4 x float> [[TMP5]], i64 [[TMP4]]
+; CHECK-NEXT: [[TMP7:%.*]] = extractelement <vscale x 4 x i32> [[B]], i64 [[TMP4]]
+; CHECK-NEXT: [[TMP8:%.*]] = call float @llvm.ldexp.f32.i32(float [[TMP6]], i32 [[TMP7]])
+; CHECK-NEXT: [[TMP9]] = insertelement <vscale x 4 x float> [[TMP5]], float [[TMP8]], i64 [[TMP4]]
+; CHECK-NEXT: [[TMP10]] = add i64 [[TMP4]], 1
+; CHECK-NEXT: [[TMP11:%.*]] = icmp eq i64 [[TMP10]], [[TMP2]]
+; CHECK-NEXT: br i1 [[TMP11]], label %[[BB12:.*]], label %[[BB3]]
+; CHECK: [[BB12]]:
+; CHECK-NEXT: ret <vscale x 4 x float> [[TMP9]]
+;
+ %output = call <vscale x 4 x float> @llvm.ldexp.nxv4f32.nxv4i32(<vscale x 4 x float> %a, <vscale x 4 x i32> %b)
+ ret <vscale x 4 x float> %output
+}
+
+define <vscale x 4 x float> @scalable_vec_powi(<vscale x 4 x float> %a, <vscale x 4 x i32> %b) {
+; CHECK-LABEL: define <vscale x 4 x float> @scalable_vec_powi(
+; CHECK-SAME: <vscale x 4 x float> [[A:%.*]], <vscale x 4 x i32> [[B:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64()
+; CHECK-NEXT: [[TMP2:%.*]] = mul nuw i64 [[TMP1]], 4
+; CHECK-NEXT: br label %[[BB3:.*]]
+; CHECK: [[BB3]]:
+; CHECK-NEXT: [[TMP4:%.*]] = phi i64 [ 0, [[TMP0:%.*]] ], [ [[TMP10:%.*]], %[[BB3]] ]
+; CHECK-NEXT: [[TMP5:%.*]] = phi <vscale x 4 x float> [ [[A]], [[TMP0]] ], [ [[TMP9:%.*]], %[[BB3]] ]
+; CHECK-NEXT: [[TMP6:%.*]] = extractelement <vscale x 4 x float> [[TMP5]], i64 [[TMP4]]
+; CHECK-NEXT: [[TMP7:%.*]] = extractelement <vscale x 4 x i32> [[B]], i64 [[TMP4]]
+; CHECK-NEXT: [[TMP8:%.*]] = call float @llvm.powi.f32.i32(float [[TMP6]], i32 [[TMP7]])
+; CHECK-NEXT: [[TMP9]] = insertelement <vscale x 4 x float> [[TMP5]], float [[TMP8]], i64 [[TMP4]]
+; CHECK-NEXT: [[TMP10]] = add i64 [[TMP4]], 1
+; CHECK-NEXT: [[TMP11:%.*]] = icmp eq i64 [[TMP10]], [[TMP2]]
+; CHECK-NEXT: br i1 [[TMP11]], label %[[BB12:.*]], label %[[BB3]]
+; CHECK: [[BB12]]:
+; CHECK-NEXT: ret <vscale x 4 x float> [[TMP9]]
+;
+ %output = call <vscale x 4 x float> @llvm.powi.nxv4f32.nxv4i32(<vscale x 4 x float> %a, <vscale x 4 x i32> %b)
+ ret <vscale x 4 x float> %output
+}
>From a5c09818cfe33273d5915e77d2b7fecdc72cf454 Mon Sep 17 00:00:00 2001
From: Philip Reames <listmail at philipreames.com>
Date: Thu, 23 Apr 2026 07:54:25 -0700
Subject: [PATCH 2/2] Use intptr type for index
---
.../Utils/LowerVectorIntrinsics.cpp | 12 +-
.../RISCV/expand-fp-math-binary.ll | 167 ++++++++++++++++++
2 files changed, 174 insertions(+), 5 deletions(-)
create mode 100644 llvm/test/Transforms/PreISelIntrinsicLowering/RISCV/expand-fp-math-binary.ll
diff --git a/llvm/lib/Transforms/Utils/LowerVectorIntrinsics.cpp b/llvm/lib/Transforms/Utils/LowerVectorIntrinsics.cpp
index e807b1c2512ae..a578132bd7f78 100644
--- a/llvm/lib/Transforms/Utils/LowerVectorIntrinsics.cpp
+++ b/llvm/lib/Transforms/Utils/LowerVectorIntrinsics.cpp
@@ -7,7 +7,9 @@
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/Utils/LowerVectorIntrinsics.h"
+#include "llvm/IR/DataLayout.h"
#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/Module.h"
#define DEBUG_TYPE "lower-vector-intrinsics"
@@ -69,7 +71,7 @@ bool llvm::lowerBinaryVectorIntrinsicAsLoop(Module &M, CallInst *CI) {
BasicBlock *PostLoopBB = nullptr;
Function *ParentFunc = PreLoopBB->getParent();
LLVMContext &Ctx = PreLoopBB->getContext();
- Type *Int64Ty = IntegerType::get(Ctx, 64);
+ Type *IdxTy = M.getDataLayout().getIntPtrType(Ctx);
PostLoopBB = PreLoopBB->splitBasicBlock(CI);
BasicBlock *LoopBB = BasicBlock::Create(Ctx, "", ParentFunc, PostLoopBB);
@@ -78,13 +80,13 @@ bool llvm::lowerBinaryVectorIntrinsicAsLoop(Module &M, CallInst *CI) {
// Loop preheader
IRBuilder<> PreLoopBuilder(PreLoopBB->getTerminator());
Value *LoopEnd =
- PreLoopBuilder.CreateElementCount(Int64Ty, VecTy->getElementCount());
+ PreLoopBuilder.CreateElementCount(IdxTy, VecTy->getElementCount());
// Loop body
IRBuilder<> LoopBuilder(LoopBB);
- PHINode *LoopIndex = LoopBuilder.CreatePHI(Int64Ty, 2);
- LoopIndex->addIncoming(ConstantInt::get(Int64Ty, 0U), PreLoopBB);
+ PHINode *LoopIndex = LoopBuilder.CreatePHI(IdxTy, 2);
+ LoopIndex->addIncoming(ConstantInt::get(IdxTy, 0U), PreLoopBB);
PHINode *Vec = LoopBuilder.CreatePHI(VecTy, 2);
Vec->addIncoming(CI->getArgOperand(0), PreLoopBB);
@@ -101,7 +103,7 @@ bool llvm::lowerBinaryVectorIntrinsicAsLoop(Module &M, CallInst *CI) {
Value *NewVec = LoopBuilder.CreateInsertElement(Vec, Res, LoopIndex);
Vec->addIncoming(NewVec, LoopBB);
- Value *One = ConstantInt::get(Int64Ty, 1U);
+ Value *One = ConstantInt::get(IdxTy, 1U);
Value *NextLoopIndex = LoopBuilder.CreateAdd(LoopIndex, One);
LoopIndex->addIncoming(NextLoopIndex, LoopBB);
diff --git a/llvm/test/Transforms/PreISelIntrinsicLowering/RISCV/expand-fp-math-binary.ll b/llvm/test/Transforms/PreISelIntrinsicLowering/RISCV/expand-fp-math-binary.ll
new file mode 100644
index 0000000000000..73bd3f80ac981
--- /dev/null
+++ b/llvm/test/Transforms/PreISelIntrinsicLowering/RISCV/expand-fp-math-binary.ll
@@ -0,0 +1,167 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -passes=pre-isel-intrinsic-lowering -mtriple=riscv32 -S < %s | FileCheck %s --check-prefix=RV32
+; RUN: opt -passes=pre-isel-intrinsic-lowering -mtriple=riscv64 -S < %s | FileCheck %s --check-prefix=RV64
+
+define <vscale x 4 x float> @scalable_vec_atan2(<vscale x 4 x float> %a, <vscale x 4 x float> %b) {
+; RV32-LABEL: define <vscale x 4 x float> @scalable_vec_atan2(
+; RV32-SAME: <vscale x 4 x float> [[A:%.*]], <vscale x 4 x float> [[B:%.*]]) {
+; RV32-NEXT: [[TMP1:%.*]] = call i32 @llvm.vscale.i32()
+; RV32-NEXT: [[TMP2:%.*]] = mul nuw i32 [[TMP1]], 4
+; RV32-NEXT: br label %[[BB3:.*]]
+; RV32: [[BB3]]:
+; RV32-NEXT: [[TMP4:%.*]] = phi i32 [ 0, [[TMP0:%.*]] ], [ [[TMP10:%.*]], %[[BB3]] ]
+; RV32-NEXT: [[TMP5:%.*]] = phi <vscale x 4 x float> [ [[A]], [[TMP0]] ], [ [[TMP9:%.*]], %[[BB3]] ]
+; RV32-NEXT: [[TMP6:%.*]] = extractelement <vscale x 4 x float> [[TMP5]], i32 [[TMP4]]
+; RV32-NEXT: [[TMP7:%.*]] = extractelement <vscale x 4 x float> [[B]], i32 [[TMP4]]
+; RV32-NEXT: [[TMP8:%.*]] = call float @llvm.atan2.f32(float [[TMP6]], float [[TMP7]])
+; RV32-NEXT: [[TMP9]] = insertelement <vscale x 4 x float> [[TMP5]], float [[TMP8]], i32 [[TMP4]]
+; RV32-NEXT: [[TMP10]] = add i32 [[TMP4]], 1
+; RV32-NEXT: [[TMP11:%.*]] = icmp eq i32 [[TMP10]], [[TMP2]]
+; RV32-NEXT: br i1 [[TMP11]], label %[[BB12:.*]], label %[[BB3]]
+; RV32: [[BB12]]:
+; RV32-NEXT: ret <vscale x 4 x float> [[TMP9]]
+;
+; RV64-LABEL: define <vscale x 4 x float> @scalable_vec_atan2(
+; RV64-SAME: <vscale x 4 x float> [[A:%.*]], <vscale x 4 x float> [[B:%.*]]) {
+; RV64-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64()
+; RV64-NEXT: [[TMP2:%.*]] = mul nuw i64 [[TMP1]], 4
+; RV64-NEXT: br label %[[BB3:.*]]
+; RV64: [[BB3]]:
+; RV64-NEXT: [[TMP4:%.*]] = phi i64 [ 0, [[TMP0:%.*]] ], [ [[TMP10:%.*]], %[[BB3]] ]
+; RV64-NEXT: [[TMP5:%.*]] = phi <vscale x 4 x float> [ [[A]], [[TMP0]] ], [ [[TMP9:%.*]], %[[BB3]] ]
+; RV64-NEXT: [[TMP6:%.*]] = extractelement <vscale x 4 x float> [[TMP5]], i64 [[TMP4]]
+; RV64-NEXT: [[TMP7:%.*]] = extractelement <vscale x 4 x float> [[B]], i64 [[TMP4]]
+; RV64-NEXT: [[TMP8:%.*]] = call float @llvm.atan2.f32(float [[TMP6]], float [[TMP7]])
+; RV64-NEXT: [[TMP9]] = insertelement <vscale x 4 x float> [[TMP5]], float [[TMP8]], i64 [[TMP4]]
+; RV64-NEXT: [[TMP10]] = add i64 [[TMP4]], 1
+; RV64-NEXT: [[TMP11:%.*]] = icmp eq i64 [[TMP10]], [[TMP2]]
+; RV64-NEXT: br i1 [[TMP11]], label %[[BB12:.*]], label %[[BB3]]
+; RV64: [[BB12]]:
+; RV64-NEXT: ret <vscale x 4 x float> [[TMP9]]
+;
+ %output = call <vscale x 4 x float> @llvm.atan2.nxv4f32(<vscale x 4 x float> %a, <vscale x 4 x float> %b)
+ ret <vscale x 4 x float> %output
+}
+
+define <vscale x 4 x float> @scalable_vec_pow(<vscale x 4 x float> %a, <vscale x 4 x float> %b) {
+; RV32-LABEL: define <vscale x 4 x float> @scalable_vec_pow(
+; RV32-SAME: <vscale x 4 x float> [[A:%.*]], <vscale x 4 x float> [[B:%.*]]) {
+; RV32-NEXT: [[TMP1:%.*]] = call i32 @llvm.vscale.i32()
+; RV32-NEXT: [[TMP2:%.*]] = mul nuw i32 [[TMP1]], 4
+; RV32-NEXT: br label %[[BB3:.*]]
+; RV32: [[BB3]]:
+; RV32-NEXT: [[TMP4:%.*]] = phi i32 [ 0, [[TMP0:%.*]] ], [ [[TMP10:%.*]], %[[BB3]] ]
+; RV32-NEXT: [[TMP5:%.*]] = phi <vscale x 4 x float> [ [[A]], [[TMP0]] ], [ [[TMP9:%.*]], %[[BB3]] ]
+; RV32-NEXT: [[TMP6:%.*]] = extractelement <vscale x 4 x float> [[TMP5]], i32 [[TMP4]]
+; RV32-NEXT: [[TMP7:%.*]] = extractelement <vscale x 4 x float> [[B]], i32 [[TMP4]]
+; RV32-NEXT: [[TMP8:%.*]] = call float @llvm.pow.f32(float [[TMP6]], float [[TMP7]])
+; RV32-NEXT: [[TMP9]] = insertelement <vscale x 4 x float> [[TMP5]], float [[TMP8]], i32 [[TMP4]]
+; RV32-NEXT: [[TMP10]] = add i32 [[TMP4]], 1
+; RV32-NEXT: [[TMP11:%.*]] = icmp eq i32 [[TMP10]], [[TMP2]]
+; RV32-NEXT: br i1 [[TMP11]], label %[[BB12:.*]], label %[[BB3]]
+; RV32: [[BB12]]:
+; RV32-NEXT: ret <vscale x 4 x float> [[TMP9]]
+;
+; RV64-LABEL: define <vscale x 4 x float> @scalable_vec_pow(
+; RV64-SAME: <vscale x 4 x float> [[A:%.*]], <vscale x 4 x float> [[B:%.*]]) {
+; RV64-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64()
+; RV64-NEXT: [[TMP2:%.*]] = mul nuw i64 [[TMP1]], 4
+; RV64-NEXT: br label %[[BB3:.*]]
+; RV64: [[BB3]]:
+; RV64-NEXT: [[TMP4:%.*]] = phi i64 [ 0, [[TMP0:%.*]] ], [ [[TMP10:%.*]], %[[BB3]] ]
+; RV64-NEXT: [[TMP5:%.*]] = phi <vscale x 4 x float> [ [[A]], [[TMP0]] ], [ [[TMP9:%.*]], %[[BB3]] ]
+; RV64-NEXT: [[TMP6:%.*]] = extractelement <vscale x 4 x float> [[TMP5]], i64 [[TMP4]]
+; RV64-NEXT: [[TMP7:%.*]] = extractelement <vscale x 4 x float> [[B]], i64 [[TMP4]]
+; RV64-NEXT: [[TMP8:%.*]] = call float @llvm.pow.f32(float [[TMP6]], float [[TMP7]])
+; RV64-NEXT: [[TMP9]] = insertelement <vscale x 4 x float> [[TMP5]], float [[TMP8]], i64 [[TMP4]]
+; RV64-NEXT: [[TMP10]] = add i64 [[TMP4]], 1
+; RV64-NEXT: [[TMP11:%.*]] = icmp eq i64 [[TMP10]], [[TMP2]]
+; RV64-NEXT: br i1 [[TMP11]], label %[[BB12:.*]], label %[[BB3]]
+; RV64: [[BB12]]:
+; RV64-NEXT: ret <vscale x 4 x float> [[TMP9]]
+;
+ %output = call <vscale x 4 x float> @llvm.pow.nxv4f32(<vscale x 4 x float> %a, <vscale x 4 x float> %b)
+ ret <vscale x 4 x float> %output
+}
+
+define <vscale x 4 x float> @scalable_vec_ldexp(<vscale x 4 x float> %a, <vscale x 4 x i32> %b) {
+; RV32-LABEL: define <vscale x 4 x float> @scalable_vec_ldexp(
+; RV32-SAME: <vscale x 4 x float> [[A:%.*]], <vscale x 4 x i32> [[B:%.*]]) {
+; RV32-NEXT: [[TMP1:%.*]] = call i32 @llvm.vscale.i32()
+; RV32-NEXT: [[TMP2:%.*]] = mul nuw i32 [[TMP1]], 4
+; RV32-NEXT: br label %[[BB3:.*]]
+; RV32: [[BB3]]:
+; RV32-NEXT: [[TMP4:%.*]] = phi i32 [ 0, [[TMP0:%.*]] ], [ [[TMP10:%.*]], %[[BB3]] ]
+; RV32-NEXT: [[TMP5:%.*]] = phi <vscale x 4 x float> [ [[A]], [[TMP0]] ], [ [[TMP9:%.*]], %[[BB3]] ]
+; RV32-NEXT: [[TMP6:%.*]] = extractelement <vscale x 4 x float> [[TMP5]], i32 [[TMP4]]
+; RV32-NEXT: [[TMP7:%.*]] = extractelement <vscale x 4 x i32> [[B]], i32 [[TMP4]]
+; RV32-NEXT: [[TMP8:%.*]] = call float @llvm.ldexp.f32.i32(float [[TMP6]], i32 [[TMP7]])
+; RV32-NEXT: [[TMP9]] = insertelement <vscale x 4 x float> [[TMP5]], float [[TMP8]], i32 [[TMP4]]
+; RV32-NEXT: [[TMP10]] = add i32 [[TMP4]], 1
+; RV32-NEXT: [[TMP11:%.*]] = icmp eq i32 [[TMP10]], [[TMP2]]
+; RV32-NEXT: br i1 [[TMP11]], label %[[BB12:.*]], label %[[BB3]]
+; RV32: [[BB12]]:
+; RV32-NEXT: ret <vscale x 4 x float> [[TMP9]]
+;
+; RV64-LABEL: define <vscale x 4 x float> @scalable_vec_ldexp(
+; RV64-SAME: <vscale x 4 x float> [[A:%.*]], <vscale x 4 x i32> [[B:%.*]]) {
+; RV64-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64()
+; RV64-NEXT: [[TMP2:%.*]] = mul nuw i64 [[TMP1]], 4
+; RV64-NEXT: br label %[[BB3:.*]]
+; RV64: [[BB3]]:
+; RV64-NEXT: [[TMP4:%.*]] = phi i64 [ 0, [[TMP0:%.*]] ], [ [[TMP10:%.*]], %[[BB3]] ]
+; RV64-NEXT: [[TMP5:%.*]] = phi <vscale x 4 x float> [ [[A]], [[TMP0]] ], [ [[TMP9:%.*]], %[[BB3]] ]
+; RV64-NEXT: [[TMP6:%.*]] = extractelement <vscale x 4 x float> [[TMP5]], i64 [[TMP4]]
+; RV64-NEXT: [[TMP7:%.*]] = extractelement <vscale x 4 x i32> [[B]], i64 [[TMP4]]
+; RV64-NEXT: [[TMP8:%.*]] = call float @llvm.ldexp.f32.i32(float [[TMP6]], i32 [[TMP7]])
+; RV64-NEXT: [[TMP9]] = insertelement <vscale x 4 x float> [[TMP5]], float [[TMP8]], i64 [[TMP4]]
+; RV64-NEXT: [[TMP10]] = add i64 [[TMP4]], 1
+; RV64-NEXT: [[TMP11:%.*]] = icmp eq i64 [[TMP10]], [[TMP2]]
+; RV64-NEXT: br i1 [[TMP11]], label %[[BB12:.*]], label %[[BB3]]
+; RV64: [[BB12]]:
+; RV64-NEXT: ret <vscale x 4 x float> [[TMP9]]
+;
+ %output = call <vscale x 4 x float> @llvm.ldexp.nxv4f32.nxv4i32(<vscale x 4 x float> %a, <vscale x 4 x i32> %b)
+ ret <vscale x 4 x float> %output
+}
+
+define <vscale x 4 x float> @scalable_vec_powi(<vscale x 4 x float> %a, <vscale x 4 x i32> %b) {
+; RV32-LABEL: define <vscale x 4 x float> @scalable_vec_powi(
+; RV32-SAME: <vscale x 4 x float> [[A:%.*]], <vscale x 4 x i32> [[B:%.*]]) {
+; RV32-NEXT: [[TMP1:%.*]] = call i32 @llvm.vscale.i32()
+; RV32-NEXT: [[TMP2:%.*]] = mul nuw i32 [[TMP1]], 4
+; RV32-NEXT: br label %[[BB3:.*]]
+; RV32: [[BB3]]:
+; RV32-NEXT: [[TMP4:%.*]] = phi i32 [ 0, [[TMP0:%.*]] ], [ [[TMP10:%.*]], %[[BB3]] ]
+; RV32-NEXT: [[TMP5:%.*]] = phi <vscale x 4 x float> [ [[A]], [[TMP0]] ], [ [[TMP9:%.*]], %[[BB3]] ]
+; RV32-NEXT: [[TMP6:%.*]] = extractelement <vscale x 4 x float> [[TMP5]], i32 [[TMP4]]
+; RV32-NEXT: [[TMP7:%.*]] = extractelement <vscale x 4 x i32> [[B]], i32 [[TMP4]]
+; RV32-NEXT: [[TMP8:%.*]] = call float @llvm.powi.f32.i32(float [[TMP6]], i32 [[TMP7]])
+; RV32-NEXT: [[TMP9]] = insertelement <vscale x 4 x float> [[TMP5]], float [[TMP8]], i32 [[TMP4]]
+; RV32-NEXT: [[TMP10]] = add i32 [[TMP4]], 1
+; RV32-NEXT: [[TMP11:%.*]] = icmp eq i32 [[TMP10]], [[TMP2]]
+; RV32-NEXT: br i1 [[TMP11]], label %[[BB12:.*]], label %[[BB3]]
+; RV32: [[BB12]]:
+; RV32-NEXT: ret <vscale x 4 x float> [[TMP9]]
+;
+; RV64-LABEL: define <vscale x 4 x float> @scalable_vec_powi(
+; RV64-SAME: <vscale x 4 x float> [[A:%.*]], <vscale x 4 x i32> [[B:%.*]]) {
+; RV64-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64()
+; RV64-NEXT: [[TMP2:%.*]] = mul nuw i64 [[TMP1]], 4
+; RV64-NEXT: br label %[[BB3:.*]]
+; RV64: [[BB3]]:
+; RV64-NEXT: [[TMP4:%.*]] = phi i64 [ 0, [[TMP0:%.*]] ], [ [[TMP10:%.*]], %[[BB3]] ]
+; RV64-NEXT: [[TMP5:%.*]] = phi <vscale x 4 x float> [ [[A]], [[TMP0]] ], [ [[TMP9:%.*]], %[[BB3]] ]
+; RV64-NEXT: [[TMP6:%.*]] = extractelement <vscale x 4 x float> [[TMP5]], i64 [[TMP4]]
+; RV64-NEXT: [[TMP7:%.*]] = extractelement <vscale x 4 x i32> [[B]], i64 [[TMP4]]
+; RV64-NEXT: [[TMP8:%.*]] = call float @llvm.powi.f32.i32(float [[TMP6]], i32 [[TMP7]])
+; RV64-NEXT: [[TMP9]] = insertelement <vscale x 4 x float> [[TMP5]], float [[TMP8]], i64 [[TMP4]]
+; RV64-NEXT: [[TMP10]] = add i64 [[TMP4]], 1
+; RV64-NEXT: [[TMP11:%.*]] = icmp eq i64 [[TMP10]], [[TMP2]]
+; RV64-NEXT: br i1 [[TMP11]], label %[[BB12:.*]], label %[[BB3]]
+; RV64: [[BB12]]:
+; RV64-NEXT: ret <vscale x 4 x float> [[TMP9]]
+;
+ %output = call <vscale x 4 x float> @llvm.powi.nxv4f32.nxv4i32(<vscale x 4 x float> %a, <vscale x 4 x i32> %b)
+ ret <vscale x 4 x float> %output
+}
More information about the llvm-commits
mailing list