-
Notifications
You must be signed in to change notification settings - Fork 13.5k
Reland "[InstSimplify] Add basic constant folding for llvm.sincos
"
#119192
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This calls into the existing constant folding for `llvm.sin` and `llvm.cos`, which currently does not fold for any non-finite values, so most tests are negative tests.
@llvm/pr-subscribers-llvm-transforms @llvm/pr-subscribers-llvm-analysis Author: Benjamin Maxwell (MacDue) ChangesThis calls into the existing constant folding for Note: The constant folding does not consider the This is a reland of #114527 that updates the syntax of one of the tests from: Full diff: https://github.com/llvm/llvm-project/pull/119192.diff 2 Files Affected:
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index efbccee76f2c51..0233d31459062d 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -1632,6 +1632,7 @@ bool llvm::canConstantFoldCallTo(const CallBase *Call, const Function *F) {
case Intrinsic::sqrt:
case Intrinsic::sin:
case Intrinsic::cos:
+ case Intrinsic::sincos:
case Intrinsic::pow:
case Intrinsic::powi:
case Intrinsic::ldexp:
@@ -3534,6 +3535,40 @@ ConstantFoldStructCall(StringRef Name, Intrinsic::ID IntrinsicID,
return nullptr;
return ConstantStruct::get(StTy, Result0, Result1);
}
+ case Intrinsic::sincos: {
+ Type *Ty = StTy->getContainedType(0);
+ Type *TyScalar = Ty->getScalarType();
+
+ auto ConstantFoldScalarSincosCall =
+ [&](Constant *Op) -> std::pair<Constant *, Constant *> {
+ Constant *SinResult =
+ ConstantFoldScalarCall(Name, Intrinsic::sin, TyScalar, Op, TLI, Call);
+ Constant *CosResult =
+ ConstantFoldScalarCall(Name, Intrinsic::cos, TyScalar, Op, TLI, Call);
+ return std::make_pair(SinResult, CosResult);
+ };
+
+ if (auto *FVTy = dyn_cast<FixedVectorType>(Ty)) {
+ SmallVector<Constant *> SinResults(FVTy->getNumElements());
+ SmallVector<Constant *> CosResults(FVTy->getNumElements());
+
+ for (unsigned I = 0, E = FVTy->getNumElements(); I != E; ++I) {
+ Constant *Lane = Operands[0]->getAggregateElement(I);
+ std::tie(SinResults[I], CosResults[I]) =
+ ConstantFoldScalarSincosCall(Lane);
+ if (!SinResults[I] || !CosResults[I])
+ return nullptr;
+ }
+
+ return ConstantStruct::get(StTy, ConstantVector::get(SinResults),
+ ConstantVector::get(CosResults));
+ }
+
+ auto [SinResult, CosResult] = ConstantFoldScalarSincosCall(Operands[0]);
+ if (!SinResult || !CosResult)
+ return nullptr;
+ return ConstantStruct::get(StTy, SinResult, CosResult);
+ }
default:
// TODO: Constant folding of vector intrinsics that fall through here does
// not work (e.g. overflow intrinsics)
diff --git a/llvm/test/Transforms/InstSimplify/sincos.ll b/llvm/test/Transforms/InstSimplify/sincos.ll
new file mode 100644
index 00000000000000..e0f81ee45af056
--- /dev/null
+++ b/llvm/test/Transforms/InstSimplify/sincos.ll
@@ -0,0 +1,148 @@
+; RUN: opt -S -passes=instsimplify %s | FileCheck %s
+
+define { float, float } @sincos_zero() {
+; CHECK-LABEL: define { float, float } @sincos_zero() {
+; CHECK-NEXT: ret { float, float } { float 0.000000e+00, float 1.000000e+00 }
+;
+ %ret = call { float, float } @llvm.sincos.f32(float zeroinitializer)
+ ret { float, float } %ret
+}
+
+define { float, float } @sincos_neg_zero() {
+; CHECK-LABEL: define { float, float } @sincos_neg_zero() {
+; CHECK-NEXT: ret { float, float } { float -0.000000e+00, float 1.000000e+00 }
+;
+ %ret = call { float, float } @llvm.sincos.f32(float -0.0)
+ ret { float, float } %ret
+}
+
+define { float, float } @sincos_one() {
+; CHECK-LABEL: define { float, float } @sincos_one() {
+; CHECK-NEXT: ret { float, float } { float [[$SIN_ONE:.+]], float [[$COS_ONE:.+]] }
+;
+ %ret = call { float, float } @llvm.sincos.f32(float 1.0)
+ ret { float, float } %ret
+}
+
+define { float, float } @sincos_two() {
+; CHECK-LABEL: define { float, float } @sincos_two() {
+; CHECK-NEXT: ret { float, float } { float [[$SIN_TWO:.+]], float [[$COS_TWO:.+]] }
+;
+ %ret = call { float, float } @llvm.sincos.f32(float 2.0)
+ ret { float, float } %ret
+}
+
+define { <2 x float>, <2 x float> } @sincos_vector() {
+; CHECK-LABEL: define { <2 x float>, <2 x float> } @sincos_vector() {
+; CHECK-NEXT: ret { <2 x float>, <2 x float> } { <2 x float> <float [[$SIN_ONE]], float [[$SIN_TWO]]>, <2 x float> <float [[$COS_ONE]], float [[$COS_TWO]]> }
+;
+ %ret = call { <2 x float>, <2 x float> } @llvm.sincos.v2f32(<2 x float> <float 1.0, float 2.0>)
+ ret { <2 x float>, <2 x float> } %ret
+}
+
+define { <2 x float>, <2 x float> } @sincos_zero_vector() {
+; CHECK-LABEL: define { <2 x float>, <2 x float> } @sincos_zero_vector() {
+; CHECK-NEXT: ret { <2 x float>, <2 x float> } { <2 x float> zeroinitializer, <2 x float> splat (float 1.000000e+00) }
+;
+ %ret = call { <2 x float>, <2 x float> } @llvm.sincos.v2f32(<2 x float> zeroinitializer)
+ ret { <2 x float>, <2 x float> } %ret
+}
+
+define { float, float } @sincos_poison() {
+; CHECK-LABEL: define { float, float } @sincos_poison() {
+; CHECK-NEXT: [[RET:%.*]] = call { float, float } @llvm.sincos.f32(float poison)
+; CHECK-NEXT: ret { float, float } [[RET]]
+;
+ %ret = call { float, float } @llvm.sincos.f32(float poison)
+ ret { float, float } %ret
+}
+
+define { <2 x float>, <2 x float> } @sincos_poison_vector() {
+; CHECK-LABEL: define { <2 x float>, <2 x float> } @sincos_poison_vector() {
+; CHECK-NEXT: [[RET:%.*]] = call { <2 x float>, <2 x float> } @llvm.sincos.v2f32(<2 x float> poison)
+; CHECK-NEXT: ret { <2 x float>, <2 x float> } [[RET]]
+;
+ %ret = call { <2 x float>, <2 x float> } @llvm.sincos.v2f32(<2 x float> poison)
+ ret { <2 x float>, <2 x float> } %ret
+}
+
+define { <vscale x 2 x float>, <vscale x 2 x float> } @sincos_poison_scalable_vector() {
+; CHECK-LABEL: define { <vscale x 2 x float>, <vscale x 2 x float> } @sincos_poison_scalable_vector() {
+; CHECK-NEXT: [[RET:%.*]] = call { <vscale x 2 x float>, <vscale x 2 x float> } @llvm.sincos.nxv2f32(<vscale x 2 x float> poison)
+; CHECK-NEXT: ret { <vscale x 2 x float>, <vscale x 2 x float> } [[RET]]
+;
+ %ret = call { <vscale x 2 x float>, <vscale x 2 x float> } @llvm.sincos.nxv2f32(<vscale x 2 x float> poison)
+ ret { <vscale x 2 x float>, <vscale x 2 x float> } %ret
+}
+
+define { float, float } @sincos_undef() {
+; CHECK-LABEL: define { float, float } @sincos_undef() {
+; CHECK-NEXT: [[RET:%.*]] = call { float, float } @llvm.sincos.f32(float undef)
+; CHECK-NEXT: ret { float, float } [[RET]]
+;
+ %ret = call { float, float } @llvm.sincos.f32(float undef)
+ ret { float, float } %ret
+}
+
+define { <2 x float>, <2 x float> } @sincos_undef_vector() {
+; CHECK-LABEL: define { <2 x float>, <2 x float> } @sincos_undef_vector() {
+; CHECK-NEXT: [[RET:%.*]] = call { <2 x float>, <2 x float> } @llvm.sincos.v2f32(<2 x float> undef)
+; CHECK-NEXT: ret { <2 x float>, <2 x float> } [[RET]]
+;
+ %ret = call { <2 x float>, <2 x float> } @llvm.sincos.v2f32(<2 x float> undef)
+ ret { <2 x float>, <2 x float> } %ret
+}
+
+define { <vscale x 2 x float>, <vscale x 2 x float> } @sincos_undef_scalable_vector() {
+; CHECK-LABEL: define { <vscale x 2 x float>, <vscale x 2 x float> } @sincos_undef_scalable_vector() {
+; CHECK-NEXT: [[RET:%.*]] = call { <vscale x 2 x float>, <vscale x 2 x float> } @llvm.sincos.nxv2f32(<vscale x 2 x float> undef)
+; CHECK-NEXT: ret { <vscale x 2 x float>, <vscale x 2 x float> } [[RET]]
+;
+ %ret = call { <vscale x 2 x float>, <vscale x 2 x float> } @llvm.sincos.nxv2f32(<vscale x 2 x float> undef)
+ ret { <vscale x 2 x float>, <vscale x 2 x float> } %ret
+}
+
+define { <vscale x 2 x float>, <vscale x 2 x float> } @sincos_zero_scalable_vector() {
+; CHECK-LABEL: define { <vscale x 2 x float>, <vscale x 2 x float> } @sincos_zero_scalable_vector() {
+; CHECK-NEXT: [[RET:%.*]] = call { <vscale x 2 x float>, <vscale x 2 x float> } @llvm.sincos.nxv2f32(<vscale x 2 x float> zeroinitializer)
+; CHECK-NEXT: ret { <vscale x 2 x float>, <vscale x 2 x float> } [[RET]]
+;
+ %ret = call { <vscale x 2 x float>, <vscale x 2 x float> } @llvm.sincos.nxv2f32(<vscale x 2 x float> zeroinitializer)
+ ret { <vscale x 2 x float>, <vscale x 2 x float> } %ret
+}
+
+define { float, float } @sincos_inf() {
+; CHECK-LABEL: define { float, float } @sincos_inf() {
+; CHECK-NEXT: [[RET:%.*]] = call { float, float } @llvm.sincos.f32(float 0x7FF0000000000000)
+; CHECK-NEXT: ret { float, float } [[RET]]
+;
+ %ret = call { float, float } @llvm.sincos.f32(float 0x7FF0000000000000)
+ ret { float, float } %ret
+}
+
+define { float, float } @sincos_neginf() {
+; CHECK-LABEL: define { float, float } @sincos_neginf() {
+; CHECK-NEXT: [[RET:%.*]] = call { float, float } @llvm.sincos.f32(float 0xFFF0000000000000)
+; CHECK-NEXT: ret { float, float } [[RET]]
+;
+ %ret = call { float, float } @llvm.sincos.f32(float 0xFFF0000000000000)
+ ret { float, float } %ret
+}
+
+define { float, float } @sincos_qnan() {
+; CHECK-LABEL: define { float, float } @sincos_qnan() {
+; CHECK-NEXT: [[RET:%.*]] = call { float, float } @llvm.sincos.f32(float 0x7FF8000000000000)
+; CHECK-NEXT: ret { float, float } [[RET]]
+;
+ %ret = call { float, float } @llvm.sincos.f32(float 0x7FF8000000000000)
+ ret { float, float } %ret
+}
+
+define { float, float } @sincos_snan() {
+; CHECK-LABEL: define { float, float } @sincos_snan() {
+; CHECK-NEXT: [[RET:%.*]] = call { float, float } @llvm.sincos.f32(float 0x7FF0000020000000)
+; CHECK-NEXT: ret { float, float } [[RET]]
+;
+ %ret = call { float, float } @llvm.sincos.f32(float bitcast (i32 2139095041 to float))
+ ret { float, float } %ret
+}
|
This calls into the existing constant folding for
llvm.sin
andllvm.cos
, which currently does not fold for any non-finite values, so most tests are negative tests at the moment.Note: The constant folding does not consider the
afn
fast-math flag and will produce the same result regardless of if the flag is set.This is a reland of #114527 that updates the syntax of one of the tests from:
<float 1.000000e+00, float 1.000000e+00>
tosplat (float 1.000000e+00)
.