Repository navigation
[HLSL] Implement frexp() - #235154
Open
danbrown-amd wants to merge 1 commit into
Open
[HLSL] Implement frexp()#235154danbrown-amd wants to merge 1 commit into
danbrown-amd wants to merge 1 commit into
Conversation
🐧 Linux x64 Test Results
✅ The build succeeded and all tests passed. |
danbrown-amd
force-pushed
the
frexp
branch
5 times, most recently
from
October 31, 2026 00:53
12cb599 to
bc23ee6
Compare
danbrown-amd
force-pushed
the
frexp
branch
2 times, most recently
from
November 6, 2026 02:54
380b96f to
81813f6
Compare
Resolves llvm#99119, llvm#220654 Assisted-by: Claude Opus 5
danbrown-amd
marked this pull request as ready for review
November 6, 2026 06:18
danbrown-amd
requested review from
AlexVlx,
MrSidims,
alexander-shaposhnikov,
aobolensk,
dnovillo,
farzonl,
idubinov,
maarquitos14 and
michalpaszkowski
as code owners
November 6, 2026 06:18
|
@llvm/pr-subscribers-hlsl @llvm/pr-subscribers-backend-x86 Author: Dan Brown (danbrown-amd) ChangesResolves #99119, #220654 Assisted-by: Claude Opus 5 Patch is 45.62 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/235154.diff 16 Files Affected:
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index d4d2393240433d..4ae54b68d4f132 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -5957,6 +5957,12 @@ def HLSLBufferUpdateCounter : LangBuiltin<"HLSL_LANG"> {
let Prototype = "uint32_t(__hlsl_resource_t, int)";
}
+def HLSLFrexp : LangBuiltin<"HLSL_LANG"> {
+ let Spellings = ["__builtin_hlsl_elementwise_frexp"];
+ let Attributes = [NoThrow, Const, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
def HLSLSplitDouble: LangBuiltin<"HLSL_LANG"> {
let Spellings = ["__builtin_hlsl_elementwise_splitdouble"];
let Attributes = [NoThrow, Const];
diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
index be680b259b9039..48c930eb5df559 100644
--- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp
+++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
@@ -119,6 +119,32 @@ static Value *handleHlslClip(const CallExpr *E, CodeGenFunction *CGF) {
return LastInstr;
}
+static Value *handleHlslFrexp(const CallExpr *E, CodeGenFunction *CGF) {
+ Value *X = CGF->EmitScalarExpr(E->getArg(0));
+
+ // Calls through the frexp overloads wrap the exponent in an HLSLOutArgExpr;
+ // direct calls to the builtin pass a plain lvalue.
+ CallArgList Args;
+ LValue ExpLValue;
+ if (const auto *OutArg = dyn_cast<HLSLOutArgExpr>(E->getArg(1)))
+ ExpLValue = CGF->EmitHLSLOutArgExpr(OutArg, Args, OutArg->getType());
+ else
+ ExpLValue = CGF->EmitLValue(E->getArg(1));
+
+ // llvm.frexp returns {mantissa, integer exponent}; HLSL wants the exponent
+ // as a float of the same shape as X.
+ llvm::Type *ExpIntTy = X->getType()->getWithNewType(CGF->Int32Ty);
+ Value *Frexp = CGF->Builder.CreateIntrinsic(
+ Intrinsic::frexp, {X->getType(), ExpIntTy}, {X}, nullptr, "hlsl.frexp");
+ Value *Mantissa = CGF->Builder.CreateExtractValue(Frexp, 0);
+ Value *Exp = CGF->Builder.CreateSIToFP(
+ CGF->Builder.CreateExtractValue(Frexp, 1), X->getType());
+
+ CGF->EmitStoreThroughLValue(RValue::get(Exp), ExpLValue);
+ CGF->EmitWritebacks(Args);
+ return Mantissa;
+}
+
static Value *handleHlslSplitdouble(const CallExpr *E, CodeGenFunction *CGF) {
Value *Op0 = CGF->EmitScalarExpr(E->getArg(0));
const auto *OutArg1 = dyn_cast<HLSLOutArgExpr>(E->getArg(1));
@@ -1818,6 +1844,11 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
CGM.getHLSLRuntime().getBufferUpdateCounterIntrinsic(),
ArrayRef<Value *>{ResHandle, OffsetI8}, nullptr);
}
+ case Builtin::BI__builtin_hlsl_elementwise_frexp:
+ assert(E->getArg(0)->getType()->hasFloatingRepresentation() &&
+ E->getArg(1)->getType()->hasFloatingRepresentation() &&
+ "frexp operands types mismatch");
+ return handleHlslFrexp(E, this);
case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
assert((E->getArg(0)->getType()->hasFloatingRepresentation() &&
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index a86fc7dc0988bb..bce5fec19558b9 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -220,6 +220,37 @@ firstbithigh(vector<T, N> X) {
return __detail::firstbithigh_impl<vector<uint, N>, vector<T, N>, 64>(X);
}
+//===----------------------------------------------------------------------===//
+// frexp builtins
+//===----------------------------------------------------------------------===//
+
+/// \fn T frexp(T X, out T Exp)
+/// \brief Returns the mantissa and exponent of the specified floating-point
+/// value.
+/// \param X The specified floating-point value.
+/// \param Exp The returned exponent of X.
+///
+/// The mantissa has the same sign as X and an absolute value in [0.5, 1), such
+/// that X = mantissa * 2^Exp. If X is 0, both the mantissa and the exponent
+/// are 0.
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_frexp)
+float frexp(float, out float);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_frexp)
+float2 frexp(float2, out float2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_frexp)
+float3 frexp(float3, out float3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_frexp)
+float4 frexp(float4, out float4);
+template <int N>
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_frexp)
+vector<__detail::enable_if_t<(N > 4), float>, N> frexp(
+ vector<__detail::enable_if_t<(N > 4), float>, N>,
+ out __detail::type_identity_t<vector<float, N>>);
+template <int R, int C>
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_frexp)
+matrix<float, R, C> frexp(matrix<float, R, C>,
+ out __detail::type_identity_t<matrix<float, R, C>>);
+
//===----------------------------------------------------------------------===//
// mul builtins
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index eb6fce49d87083..9fb19de94df284 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -5432,6 +5432,23 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
TheCall->setType(ArgTyExpr);
break;
}
+ case Builtin::BI__builtin_hlsl_elementwise_frexp: {
+ if (SemaRef.checkArgCount(TheCall, 2))
+ return true;
+
+ if (CheckScalarOrVectorOrMatrix(&SemaRef, TheCall, SemaRef.Context.FloatTy,
+ 0) ||
+ CheckScalarOrVectorOrMatrix(&SemaRef, TheCall, SemaRef.Context.FloatTy,
+ 1) ||
+ CheckAllArgsHaveSameType(&SemaRef, TheCall))
+ return true;
+
+ if (CheckModifiableLValue(&SemaRef, TheCall, 1))
+ return true;
+
+ TheCall->setType(TheCall->getArg(0)->getType());
+ break;
+ }
case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
if (SemaRef.checkArgCount(TheCall, 3))
return true;
diff --git a/clang/test/CodeGenHLSL/builtins/frexp.hlsl b/clang/test/CodeGenHLSL/builtins/frexp.hlsl
new file mode 100644
index 00000000000000..4043fd145b8f88
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/frexp.hlsl
@@ -0,0 +1,105 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \
+// RUN: -o - | FileCheck %s --check-prefixes=CHECK,DXCHECK
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN: spirv-unknown-vulkan-library %s -emit-llvm -disable-llvm-passes \
+// RUN: -o - | FileCheck %s --check-prefixes=CHECK,SPVCHECK
+
+// The only difference between the targets is the calling convention on the
+// definitions. It is captured once, in the first function, as [[FN_TYPE]].
+
+// DXCHECK: define hidden [[FN_TYPE:]]noundef nofpclass(nan inf) float @_Z12test_frexp_ffRf(
+// SPVCHECK: define hidden [[FN_TYPE:spir_func ]]noundef nofpclass(nan inf) float @_Z12test_frexp_ffRf(
+// CHECK: [[X:%.*]] = load float, ptr %{{.*}}
+// CHECK: [[FREXP:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[X]])
+// CHECK-NEXT: [[MANT:%.*]] = extractvalue { float, i32 } [[FREXP]], 0
+// CHECK-NEXT: [[EXPI:%.*]] = extractvalue { float, i32 } [[FREXP]], 1
+// CHECK-NEXT: [[EXPF:%.*]] = sitofp {{.*}}i32 [[EXPI]] to float
+// CHECK-NEXT: store float [[EXPF]], ptr [[TMP:%.*]], align 4
+// CHECK-NEXT: [[WB:%.*]] = load float, ptr [[TMP]], align 4
+// CHECK-NEXT: store float [[WB]], ptr %{{.*}}, align 4
+// CHECK: ret float [[MANT]]
+float test_frexp_f(float X, out float E) { return frexp(X, E); }
+
+// CHECK: define hidden [[FN_TYPE]]noundef nofpclass(nan inf) <2 x float> @_Z13test_frexp_f2Dv2_fRS_(
+// CHECK: [[FREXP:%.*]] = call { <2 x float>, <2 x i32> } @llvm.frexp.v2f32.v2i32(<2 x float> %{{.*}})
+// CHECK-NEXT: [[MANT:%.*]] = extractvalue { <2 x float>, <2 x i32> } [[FREXP]], 0
+// CHECK-NEXT: [[EXPI:%.*]] = extractvalue { <2 x float>, <2 x i32> } [[FREXP]], 1
+// CHECK-NEXT: [[EXPF:%.*]] = sitofp {{.*}}<2 x i32> [[EXPI]] to <2 x float>
+// CHECK-NEXT: store <2 x float> [[EXPF]], ptr [[TMP:%.*]], align 4
+// CHECK: ret <2 x float> [[MANT]]
+float2 test_frexp_f2(float2 X, out float2 E) { return frexp(X, E); }
+
+// CHECK: define hidden [[FN_TYPE]]noundef nofpclass(nan inf) <3 x float> @_Z13test_frexp_f3Dv3_fRS_(
+// CHECK: [[FREXP:%.*]] = call { <3 x float>, <3 x i32> } @llvm.frexp.v3f32.v3i32(<3 x float> %{{.*}})
+// CHECK-NEXT: [[MANT:%.*]] = extractvalue { <3 x float>, <3 x i32> } [[FREXP]], 0
+// CHECK-NEXT: [[EXPI:%.*]] = extractvalue { <3 x float>, <3 x i32> } [[FREXP]], 1
+// CHECK-NEXT: [[EXPF:%.*]] = sitofp {{.*}}<3 x i32> [[EXPI]] to <3 x float>
+// CHECK-NEXT: store <3 x float> [[EXPF]], ptr [[TMP:%.*]]
+// CHECK: ret <3 x float> [[MANT]]
+float3 test_frexp_f3(float3 X, out float3 E) { return frexp(X, E); }
+
+// CHECK: define hidden [[FN_TYPE]]noundef nofpclass(nan inf) <4 x float> @_Z13test_frexp_f4Dv4_fRS_(
+// CHECK: [[FREXP:%.*]] = call { <4 x float>, <4 x i32> } @llvm.frexp.v4f32.v4i32(<4 x float> %{{.*}})
+// CHECK-NEXT: [[MANT:%.*]] = extractvalue { <4 x float>, <4 x i32> } [[FREXP]], 0
+// CHECK-NEXT: [[EXPI:%.*]] = extractvalue { <4 x float>, <4 x i32> } [[FREXP]], 1
+// CHECK-NEXT: [[EXPF:%.*]] = sitofp {{.*}}<4 x i32> [[EXPI]] to <4 x float>
+// CHECK-NEXT: store <4 x float> [[EXPF]], ptr [[TMP:%.*]], align 4
+// CHECK: ret <4 x float> [[MANT]]
+float4 test_frexp_f4(float4 X, out float4 E) { return frexp(X, E); }
+
+// CHECK: define hidden [[FN_TYPE]]noundef nofpclass(nan inf) <5 x float> @_Z13test_frexp_f5Dv5_fRS_(
+// CHECK: [[FREXP:%.*]] = call { <5 x float>, <5 x i32> } @llvm.frexp.v5f32.v5i32(<5 x float> %{{.*}})
+// CHECK-NEXT: [[MANT:%.*]] = extractvalue { <5 x float>, <5 x i32> } [[FREXP]], 0
+// CHECK-NEXT: [[EXPI:%.*]] = extractvalue { <5 x float>, <5 x i32> } [[FREXP]], 1
+// CHECK-NEXT: [[EXPF:%.*]] = sitofp {{.*}}<5 x i32> [[EXPI]] to <5 x float>
+// CHECK-NEXT: store <5 x float> [[EXPF]], ptr [[TMP:%.*]], align 4
+// CHECK: ret <5 x float> [[MANT]]
+vector<float, 5> test_frexp_f5(vector<float, 5> X, out vector<float, 5> E) {
+ return frexp(X, E);
+}
+
+// Direct calls to the builtin store the exponent straight to the lvalue.
+// CHECK-LABEL: test_frexp_builtin
+// CHECK: [[FREXP:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float %{{.*}})
+// CHECK-NEXT: [[MANT:%.*]] = extractvalue { float, i32 } [[FREXP]], 0
+// CHECK-NEXT: [[EXPI:%.*]] = extractvalue { float, i32 } [[FREXP]], 1
+// CHECK-NEXT: [[EXPF:%.*]] = sitofp {{.*}}i32 [[EXPI]] to float
+// CHECK-NEXT: store float [[EXPF]], ptr %{{.*}}, align 4
+// CHECK-NEXT: store float [[MANT]], ptr %{{.*}}, align 4
+float2 test_frexp_builtin(float X) {
+ float E;
+ float M = __builtin_hlsl_elementwise_frexp(X, E);
+ return float2(M, E);
+}
+
+// The exponent can also be an integer, as with DXC. It is computed as a float
+// and converted when it is written back.
+
+// CHECK-LABEL: define {{.*}}test_frexp_int_exp_scalar
+// CHECK: [[FREXP:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float %{{.*}})
+// CHECK-NEXT: [[MANT:%.*]] = extractvalue { float, i32 } [[FREXP]], 0
+// CHECK-NEXT: [[EXPI:%.*]] = extractvalue { float, i32 } [[FREXP]], 1
+// CHECK-NEXT: [[EXPF:%.*]] = sitofp {{.*}}i32 [[EXPI]] to float
+// CHECK-NEXT: store float [[EXPF]], ptr [[TMP:%.*]], align 4
+// CHECK-NEXT: [[LOAD:%.*]] = load float, ptr [[TMP]], align 4
+// CHECK-NEXT: [[CONV:%.*]] = fptosi float [[LOAD]] to i32
+// CHECK-NEXT: store i32 [[CONV]], ptr %{{.*}}, align 4
+// CHECK: ret float [[MANT]]
+float test_frexp_int_exp_scalar(float X, out int E) { return frexp(X, E); }
+
+// CHECK-LABEL: define {{.*}}test_frexp_int_exp_long
+// CHECK: [[FREXP:%.*]] = call { <8 x float>, <8 x i32> } @llvm.frexp.v8f32.v8i32(<8 x float> %{{.*}})
+// CHECK-NEXT: [[MANT:%.*]] = extractvalue { <8 x float>, <8 x i32> } [[FREXP]], 0
+// CHECK-NEXT: [[EXPI:%.*]] = extractvalue { <8 x float>, <8 x i32> } [[FREXP]], 1
+// CHECK-NEXT: [[EXPF:%.*]] = sitofp {{.*}}<8 x i32> [[EXPI]] to <8 x float>
+// CHECK-NEXT: store <8 x float> [[EXPF]], ptr [[TMP:%.*]], align 4
+// CHECK-NEXT: [[LOAD:%.*]] = load <8 x float>, ptr [[TMP]], align 4
+// CHECK-NEXT: [[CONV:%.*]] = fptosi <8 x float> [[LOAD]] to <8 x i32>
+// CHECK-NEXT: store <8 x i32> [[CONV]], ptr %{{.*}}, align 4
+// CHECK: ret <8 x float> [[MANT]]
+vector<float, 8> test_frexp_int_exp_long(vector<float, 8> X,
+ out vector<int, 8> E) {
+ return frexp(X, E);
+}
+
diff --git a/clang/test/CodeGenHLSL/builtins/frexp_mat.hlsl b/clang/test/CodeGenHLSL/builtins/frexp_mat.hlsl
new file mode 100644
index 00000000000000..699082e0c5982b
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/frexp_mat.hlsl
@@ -0,0 +1,170 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \
+// RUN: -o - | FileCheck %s --check-prefixes=CHECK,DXCHECK
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN: spirv-unknown-vulkan-library %s -emit-llvm -disable-llvm-passes \
+// RUN: -o - | FileCheck %s --check-prefixes=CHECK,SPVCHECK
+
+// DXCHECK: define hidden [[FN_TYPE:]]noundef nofpclass(nan inf) <2 x float> @{{.*}}test_frexp_f1x2{{.*}}(
+// SPVCHECK: define hidden [[FN_TYPE:spir_func ]]noundef nofpclass(nan inf) <2 x float> @{{.*}}test_frexp_f1x2{{.*}}(
+// CHECK: [[FREXP:%.*]] = call { <2 x float>, <2 x i32> } @llvm.frexp.v2f32.v2i32(<2 x float> %{{.*}})
+// CHECK-NEXT: [[MANT:%.*]] = extractvalue { <2 x float>, <2 x i32> } [[FREXP]], 0
+// CHECK-NEXT: [[EXPI:%.*]] = extractvalue { <2 x float>, <2 x i32> } [[FREXP]], 1
+// CHECK-NEXT: [[EXPF:%.*]] = sitofp {{.*}}<2 x i32> [[EXPI]] to <2 x float>
+// CHECK-NEXT: store <2 x float> [[EXPF]], ptr [[TMP:%.*]], align 4
+// CHECK: ret <2 x float> [[MANT]]
+float1x2 test_frexp_f1x2(float1x2 X, out float1x2 E) { return frexp(X, E); }
+
+// CHECK: define hidden [[FN_TYPE]]noundef nofpclass(nan inf) <3 x float> @{{.*}}test_frexp_f1x3{{.*}}(
+// CHECK: [[FREXP:%.*]] = call { <3 x float>, <3 x i32> } @llvm.frexp.v3f32.v3i32(<3 x float> %{{.*}})
+// CHECK-NEXT: [[MANT:%.*]] = extractvalue { <3 x float>, <3 x i32> } [[FREXP]], 0
+// CHECK-NEXT: [[EXPI:%.*]] = extractvalue { <3 x float>, <3 x i32> } [[FREXP]], 1
+// CHECK-NEXT: [[EXPF:%.*]] = sitofp {{.*}}<3 x i32> [[EXPI]] to <3 x float>
+// CHECK-NEXT: store <3 x float> [[EXPF]], ptr [[TMP:%.*]], align 4
+// CHECK: ret <3 x float> [[MANT]]
+float1x3 test_frexp_f1x3(float1x3 X, out float1x3 E) { return frexp(X, E); }
+
+// CHECK: define hidden [[FN_TYPE]]noundef nofpclass(nan inf) <4 x float> @{{.*}}test_frexp_f1x4{{.*}}(
+// CHECK: [[FREXP:%.*]] = call { <4 x float>, <4 x i32> } @llvm.frexp.v4f32.v4i32(<4 x float> %{{.*}})
+// CHECK-NEXT: [[MANT:%.*]] = extractvalue { <4 x float>, <4 x i32> } [[FREXP]], 0
+// CHECK-NEXT: [[EXPI:%.*]] = extractvalue { <4 x float>, <4 x i32> } [[FREXP]], 1
+// CHECK-NEXT: [[EXPF:%.*]] = sitofp {{.*}}<4 x i32> [[EXPI]] to <4 x float>
+// CHECK-NEXT: store <4 x float> [[EXPF]], ptr [[TMP:%.*]], align 4
+// CHECK: ret <4 x float> [[MANT]]
+float1x4 test_frexp_f1x4(float1x4 X, out float1x4 E) { return frexp(X, E); }
+
+// CHECK: define hidden [[FN_TYPE]]noundef nofpclass(nan inf) <2 x float> @{{.*}}test_frexp_f2x1{{.*}}(
+// CHECK: [[FREXP:%.*]] = call { <2 x float>, <2 x i32> } @llvm.frexp.v2f32.v2i32(<2 x float> %{{.*}})
+// CHECK-NEXT: [[MANT:%.*]] = extractvalue { <2 x float>, <2 x i32> } [[FREXP]], 0
+// CHECK-NEXT: [[EXPI:%.*]] = extractvalue { <2 x float>, <2 x i32> } [[FREXP]], 1
+// CHECK-NEXT: [[EXPF:%.*]] = sitofp {{.*}}<2 x i32> [[EXPI]] to <2 x float>
+// CHECK-NEXT: store <2 x float> [[EXPF]], ptr [[TMP:%.*]], align 4
+// CHECK: ret <2 x float> [[MANT]]
+float2x1 test_frexp_f2x1(float2x1 X, out float2x1 E) { return frexp(X, E); }
+
+// CHECK: define hidden [[FN_TYPE]]noundef nofpclass(nan inf) <4 x float> @{{.*}}test_frexp_f2x2{{.*}}(
+// CHECK: [[FREXP:%.*]] = call { <4 x float>, <4 x i32> } @llvm.frexp.v4f32.v4i32(<4 x float> %{{.*}})
+// CHECK-NEXT: [[MANT:%.*]] = extractvalue { <4 x float>, <4 x i32> } [[FREXP]], 0
+// CHECK-NEXT: [[EXPI:%.*]] = extractvalue { <4 x float>, <4 x i32> } [[FREXP]], 1
+// CHECK-NEXT: [[EXPF:%.*]] = sitofp {{.*}}<4 x i32> [[EXPI]] to <4 x float>
+// CHECK-NEXT: store <4 x float> [[EXPF]], ptr [[TMP:%.*]], align 4
+// CHECK: ret <4 x float> [[MANT]]
+float2x2 test_frexp_f2x2(float2x2 X, out float2x2 E) { return frexp(X, E); }
+
+// CHECK: define hidden [[FN_TYPE]]noundef nofpclass(nan inf) <6 x float> @{{.*}}test_frexp_f2x3{{.*}}(
+// CHECK: [[FREXP:%.*]] = call { <6 x float>, <6 x i32> } @llvm.frexp.v6f32.v6i32(<6 x float> %{{.*}})
+// CHECK-NEXT: [[MANT:%.*]] = extractvalue { <6 x float>, <6 x i32> } [[FREXP]], 0
+// CHECK-NEXT: [[EXPI:%.*]] = extractvalue { <6 x float>, <6 x i32> } [[FREXP]], 1
+// CHECK-NEXT: [[EXPF:%.*]] = sitofp {{.*}}<6 x i32> [[EXPI]] to <6 x float>
+// CHECK-NEXT: store <6 x float> [[EXPF]], ptr [[TMP:%.*]], align 4
+// CHECK: ret <6 x float> [[MANT]]
+float2x3 test_frexp_f2x3(float2x3 X, out float2x3 E) { return frexp(X, E); }
+
+// CHECK: define hidden [[FN_TYPE]]noundef nofpclass(nan inf) <8 x float> @{{.*}}test_frexp_f2x4{{.*}}(
+// CHECK: [[FREXP:%.*]] = call { <8 x float>, <8 x i32> } @llvm.frexp.v8f32.v8i32(<8 x float> %{{.*}})
+// CHECK-NEXT: [[MANT:%.*]] = extractvalue { <8 x float>, <8 x i32> } [[FREXP]], 0
+// CHECK-NEXT: [[EXPI:%.*]] = extractvalue { <8 x float>, <8 x i32> } [[FREXP]], 1
+// CHECK-NEXT: [[EXPF:%.*]] = sitofp {{.*}}<8 x i32> [[EXPI]] to <8 x float>
+// CHECK-NEXT: store <8 x float> [[EXPF]], ptr [[TMP:%.*]], align 4
+// CHECK: ret <8 x float> [[MANT]]
+float2x4 test_frexp_f2x4(float2x4 X, out float2x4 E) { return frexp(X, E); }
+
+// CHECK: define hidden [[FN_TYPE]]noundef nofpclass(nan inf) <3 x float> @{{.*}}test_frexp_f3x1{{.*}}(
+// CHECK: [[FREXP:%.*]] = call { <3 x float>, <3 x i32> } @llvm.frexp.v3f32.v3i32(<3 x float> %{{.*}})
+// CHECK-NEXT: [[MANT:%.*]] = extractvalue { <3 x float>, <3 x i32> } [[FREXP]], 0
+// CHECK-NEXT: [[EXPI:%.*]] = extractvalue { <3 x float>, <3 x i32> } [[FREXP]], 1
+// CHECK-NEXT: [[EXPF:%.*]] = sitofp {{.*}}<3 x i32> [[EXPI]] to <3 x float>
+// CHECK-NEXT: store <3 x float> [[EXPF]], ptr [[TMP:%.*]], align 4
+// CHECK: ret <3 x float> [[MANT]]
+float3x1 test_frexp_f3x1(float3x1 X, out float3x1 E) { return frexp(X, E); }
+
+// CHECK: define hidden [[FN_TYPE]]noundef nofpclass(nan inf) <6 x float> @{{.*}}test_frexp_f3x2{{.*}}(
+// CHECK: [[FREXP:%.*]] = call { <6 x float>, <6 x i32> } @llvm.frexp.v6f32.v6i32(<6 x float> %{{.*}})
+// CHECK-NEXT: [[MANT:%.*]] = extractvalue { <6 x float>, <6 x i32> } [[FREXP]], 0
+// CHECK-NEXT: [[EXPI:%.*]] = extractvalue { <6 x float>, <6 x i32> } [[FREXP]], 1
+// CHECK-NEXT: [[EXPF:%.*]] = sitofp {{.*}}<6 x i32> [[EXPI]] to <6 x float>
+// CHECK-NEXT: store <6 x float> [[EXPF]], ptr [[TMP:%.*]], align 4
+// CHECK: ret <6 x float> [[MANT]]
+float3x2 test_frexp_f3x2(float3x2 X, out float3x2 E) { return frexp(X, E); }
+
+// CHECK: define hidden [[FN_TYPE]]noundef nofpclass(nan inf) <9 x float> @{{.*}}test_frexp_f3x3{{.*}}(
+// CHECK: [[FREXP:%.*]] = call { <9 x float>, <9 x i32> } @llvm.frexp.v9f32.v9i32(<9 x float> %{{.*}})
+// CHECK-NEXT: [[MANT:%.*]] = extractvalue { <9 x float>, <9 x i32> } [[FREXP]], 0
+// CHECK-NEXT: [[EXPI:%.*]] = extractvalue { <9 x float>, <9 x i32> } [[FREXP]], 1
+// CHECK-NEXT: [[EXPF:%.*]] = sitofp {{.*}}<9 x i32> [[EXPI]] to <9 x float>
+// CHECK-NEXT: store <9 x float> [[EXPF]], ptr [[TMP:%.*]], align 4
+// CHECK: ret <9 x float> [[MANT]]
+float3x3 test_frexp_f3x3(float3x3 X, out float3x3 E) { return frexp(X, E); }
+
+// CHECK: define hidden [[FN_TYPE]]noundef nofpclass(nan inf) <12 x float> @{{.*}}test_frexp_f3x4{{.*}}(
+// CHECK: [[FREXP:%.*]] = call { <12 x float>, <12 x i32> } @llvm.frexp.v12f32.v12i32(<12 x float> %{{.*}})
+// CHECK-NEXT: [[MANT:%.*]] = extractvalue { <12 x float>, <12 x i32> } [[FREXP]], 0
+// CHECK-NEXT: [[EXPI:%.*]] = extractvalue { <12 x float>, <12 x i32> } [[FREXP]], 1
+// CHECK-NEXT: [[EXPF:%.*]] = sitofp {{.*}}<12 x i32> [[EXPI]] to <12 x float>
+// CHECK-NEXT: store <12 x float> [[EXPF]], ptr [[TMP:%.*]], align 4
+// CHECK: ret <12 x float> [[MANT]]
+float3x4 test_frexp_f3x4(float3x4 X, out float3x4 E)...
[truncated]
|
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Resolves #99119, #220654
Assisted-by: Claude Opus 5