From 2634222a9c47486895dc9da68921ed9fd43f2e45 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Mon, 3 Feb 2025 21:50:34 +0800 Subject: [PATCH 1/2] [InstCombine] Add pre-commit tests. NFC. --- .../InstCombine/fpclass-check-idioms.ll | 144 ++++++++++++++++++ 1 file changed, 144 insertions(+) diff --git a/llvm/test/Transforms/InstCombine/fpclass-check-idioms.ll b/llvm/test/Transforms/InstCombine/fpclass-check-idioms.ll index 66970a9d48ddf..9834d2b088bfb 100644 --- a/llvm/test/Transforms/InstCombine/fpclass-check-idioms.ll +++ b/llvm/test/Transforms/InstCombine/fpclass-check-idioms.ll @@ -566,6 +566,150 @@ define i1 @f32_fcnan_fcinf_noimplicitfloat_strictfp(float %a) strictfp #0 { ret i1 %cmp } +define i1 @f32_fcsubnormal_fczero(float %a) { +; CHECK-LABEL: define i1 @f32_fcsubnormal_fczero( +; CHECK-SAME: float [[A:%.*]]) { +; CHECK-NEXT: [[I32:%.*]] = bitcast float [[A]] to i32 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[I32]], 2139095040 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0 +; CHECK-NEXT: ret i1 [[CMP]] +; + %i32 = bitcast float %a to i32 + %and = and i32 %i32, 2139095040 + %cmp = icmp eq i32 %and, 0 + ret i1 %cmp +} + +define i1 @f32_not_fcsubnormal_fczero(float %a) { +; CHECK-LABEL: define i1 @f32_not_fcsubnormal_fczero( +; CHECK-SAME: float [[A:%.*]]) { +; CHECK-NEXT: [[I32:%.*]] = bitcast float [[A]] to i32 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[I32]], 2139095040 +; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[AND]], 0 +; CHECK-NEXT: ret i1 [[CMP]] +; + %i32 = bitcast float %a to i32 + %and = and i32 %i32, 2139095040 + %cmp = icmp ne i32 %and, 0 + ret i1 %cmp +} + +define <2 x i1> @f64_fcsubnormal_fczero_vec(<2 x double> %a) { +; CHECK-LABEL: define <2 x i1> @f64_fcsubnormal_fczero_vec( +; CHECK-SAME: <2 x double> [[A:%.*]]) { +; CHECK-NEXT: [[I64:%.*]] = bitcast <2 x double> [[A]] to <2 x i64> +; CHECK-NEXT: [[AND:%.*]] = and <2 x i64> [[I64]], splat (i64 9218868437227405312) +; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i64> [[AND]], zeroinitializer +; CHECK-NEXT: ret <2 x i1> [[CMP]] +; + %i64 = bitcast <2 x double> %a to <2 x i64> + %and = and <2 x i64> %i64, splat(i64 9218868437227405312) + %cmp = icmp eq <2 x i64> %and, zeroinitializer + ret <2 x i1> %cmp +} + +define <2 x i1> @f64_no_fcsubnormal_fczero_vec(<2 x double> %a) { +; CHECK-LABEL: define <2 x i1> @f64_no_fcsubnormal_fczero_vec( +; CHECK-SAME: <2 x double> [[A:%.*]]) { +; CHECK-NEXT: [[I64:%.*]] = bitcast <2 x double> [[A]] to <2 x i64> +; CHECK-NEXT: [[AND:%.*]] = and <2 x i64> [[I64]], splat (i64 9218868437227405312) +; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i64> [[AND]], zeroinitializer +; CHECK-NEXT: ret <2 x i1> [[CMP]] +; + %i64 = bitcast <2 x double> %a to <2 x i64> + %and = and <2 x i64> %i64, splat(i64 9218868437227405312) + %cmp = icmp ne <2 x i64> %and, zeroinitializer + ret <2 x i1> %cmp +} + +define i1 @f32_fcsubnormal_fczero_no_implicit_fp(float %a) #0 { +; CHECK-LABEL: define i1 @f32_fcsubnormal_fczero_no_implicit_fp( +; CHECK-SAME: float [[A:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: [[I32:%.*]] = bitcast float [[A]] to i32 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[I32]], 2139095040 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0 +; CHECK-NEXT: ret i1 [[CMP]] +; + %i32 = bitcast float %a to i32 + %and = and i32 %i32, 2139095040 + %cmp = icmp eq i32 %and, 0 + ret i1 %cmp +} + +define i1 @f32_fcsubnormal_fczero_invalid_constant1(float %a) { +; CHECK-LABEL: define i1 @f32_fcsubnormal_fczero_invalid_constant1( +; CHECK-SAME: float [[A:%.*]]) { +; CHECK-NEXT: [[I32:%.*]] = bitcast float [[A]] to i32 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[I32]], 2139095039 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0 +; CHECK-NEXT: ret i1 [[CMP]] +; + %i32 = bitcast float %a to i32 + %and = and i32 %i32, 2139095039 + %cmp = icmp eq i32 %and, 0 + ret i1 %cmp +} + +define i1 @f32_fcsubnormal_fczero_invalid_constant2(float %a) { +; CHECK-LABEL: define i1 @f32_fcsubnormal_fczero_invalid_constant2( +; CHECK-SAME: float [[A:%.*]]) { +; CHECK-NEXT: [[I32:%.*]] = bitcast float [[A]] to i32 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[I32]], 2139095040 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 2130706432 +; CHECK-NEXT: ret i1 [[CMP]] +; + %i32 = bitcast float %a to i32 + %and = and i32 %i32, 2139095040 + %cmp = icmp eq i32 %and, 2130706432 + ret i1 %cmp +} + +define i1 @ppc128_fcsubnormal_fczero(ppc_fp128 %a) { +; CHECK-LABEL: define i1 @ppc128_fcsubnormal_fczero( +; CHECK-SAME: ppc_fp128 [[A:%.*]]) { +; CHECK-NEXT: [[I128:%.*]] = bitcast ppc_fp128 [[A]] to i128 +; CHECK-NEXT: [[AND:%.*]] = and i128 [[I128]], 170058106710732674489630815774616584192 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i128 [[AND]], 0 +; CHECK-NEXT: ret i1 [[CMP]] +; + %i128 = bitcast ppc_fp128 %a to i128 + %and = and i128 %i128, 170058106710732674489630815774616584192 + %cmp = icmp eq i128 %and, 0 + ret i1 %cmp +} + +define i1 @f32_fcsubnormal_fczero_multiuse1(float %a) { +; CHECK-LABEL: define i1 @f32_fcsubnormal_fczero_multiuse1( +; CHECK-SAME: float [[A:%.*]]) { +; CHECK-NEXT: [[I32:%.*]] = bitcast float [[A]] to i32 +; CHECK-NEXT: call void @usei32(i32 [[I32]]) +; CHECK-NEXT: [[AND:%.*]] = and i32 [[I32]], 2139095040 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0 +; CHECK-NEXT: ret i1 [[CMP]] +; + %i32 = bitcast float %a to i32 + call void @usei32(i32 %i32) + %and = and i32 %i32, 2139095040 + %cmp = icmp eq i32 %and, 0 + ret i1 %cmp +} + +define i1 @f32_fcsubnormal_fczero_multiuse2(float %a) { +; CHECK-LABEL: define i1 @f32_fcsubnormal_fczero_multiuse2( +; CHECK-SAME: float [[A:%.*]]) { +; CHECK-NEXT: [[I32:%.*]] = bitcast float [[A]] to i32 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[I32]], 2139095040 +; CHECK-NEXT: call void @usei32(i32 [[AND]]) +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0 +; CHECK-NEXT: ret i1 [[CMP]] +; + %i32 = bitcast float %a to i32 + %and = and i32 %i32, 2139095040 + call void @usei32(i32 %and) + %cmp = icmp eq i32 %and, 0 + ret i1 %cmp +} + define i1 @f32_fcposinf_noimplicitfloat(float %a) #0 { ; CHECK-LABEL: define i1 @f32_fcposinf_noimplicitfloat( ; CHECK-SAME: float [[A:%.*]]) #[[ATTR1]] { From 85e2487c5918d7e58a9c9199176c75c46002f84a Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Mon, 3 Feb 2025 21:59:57 +0800 Subject: [PATCH 2/2] [InstCombine] Handle isSubnormalOrZero idiom --- .../InstCombine/InstCombineCompares.cpp | 12 +++++++++--- .../InstCombine/fpclass-check-idioms.ll | 16 ++++------------ 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index a8a5cb2b20d7a..83534059bfb69 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -1884,17 +1884,23 @@ Instruction *InstCombinerImpl::foldICmpAndConstConst(ICmpInst &Cmp, // llvm.is.fpclass(X, fcInf|fcNan) // (icmp ne (and (bitcast X to int), ExponentMask), ExponentMask) --> // llvm.is.fpclass(X, ~(fcInf|fcNan)) + // (icmp eq (and (bitcast X to int), ExponentMask), 0) --> + // llvm.is.fpclass(X, fcSubnormal|fcZero) + // (icmp ne (and (bitcast X to int), ExponentMask), 0) --> + // llvm.is.fpclass(X, ~(fcSubnormal|fcZero)) Value *V; if (!Cmp.getParent()->getParent()->hasFnAttribute( Attribute::NoImplicitFloat) && Cmp.isEquality() && match(X, m_OneUse(m_ElementWiseBitCast(m_Value(V))))) { Type *FPType = V->getType()->getScalarType(); - if (FPType->isIEEELikeFPTy() && C1 == *C2) { + if (FPType->isIEEELikeFPTy() && (C1.isZero() || C1 == *C2)) { APInt ExponentMask = APFloat::getInf(FPType->getFltSemantics()).bitcastToAPInt(); - if (C1 == ExponentMask) { - unsigned Mask = FPClassTest::fcNan | FPClassTest::fcInf; + if (*C2 == ExponentMask) { + unsigned Mask = C1.isZero() + ? FPClassTest::fcZero | FPClassTest::fcSubnormal + : FPClassTest::fcNan | FPClassTest::fcInf; if (isICMP_NE) Mask = ~Mask & fcAllFlags; return replaceInstUsesWith(Cmp, Builder.createIsFPClass(V, Mask)); diff --git a/llvm/test/Transforms/InstCombine/fpclass-check-idioms.ll b/llvm/test/Transforms/InstCombine/fpclass-check-idioms.ll index 9834d2b088bfb..bb5713a1a56ea 100644 --- a/llvm/test/Transforms/InstCombine/fpclass-check-idioms.ll +++ b/llvm/test/Transforms/InstCombine/fpclass-check-idioms.ll @@ -569,9 +569,7 @@ define i1 @f32_fcnan_fcinf_noimplicitfloat_strictfp(float %a) strictfp #0 { define i1 @f32_fcsubnormal_fczero(float %a) { ; CHECK-LABEL: define i1 @f32_fcsubnormal_fczero( ; CHECK-SAME: float [[A:%.*]]) { -; CHECK-NEXT: [[I32:%.*]] = bitcast float [[A]] to i32 -; CHECK-NEXT: [[AND:%.*]] = and i32 [[I32]], 2139095040 -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0 +; CHECK-NEXT: [[CMP:%.*]] = call i1 @llvm.is.fpclass.f32(float [[A]], i32 240) ; CHECK-NEXT: ret i1 [[CMP]] ; %i32 = bitcast float %a to i32 @@ -583,9 +581,7 @@ define i1 @f32_fcsubnormal_fczero(float %a) { define i1 @f32_not_fcsubnormal_fczero(float %a) { ; CHECK-LABEL: define i1 @f32_not_fcsubnormal_fczero( ; CHECK-SAME: float [[A:%.*]]) { -; CHECK-NEXT: [[I32:%.*]] = bitcast float [[A]] to i32 -; CHECK-NEXT: [[AND:%.*]] = and i32 [[I32]], 2139095040 -; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[AND]], 0 +; CHECK-NEXT: [[CMP:%.*]] = call i1 @llvm.is.fpclass.f32(float [[A]], i32 783) ; CHECK-NEXT: ret i1 [[CMP]] ; %i32 = bitcast float %a to i32 @@ -597,9 +593,7 @@ define i1 @f32_not_fcsubnormal_fczero(float %a) { define <2 x i1> @f64_fcsubnormal_fczero_vec(<2 x double> %a) { ; CHECK-LABEL: define <2 x i1> @f64_fcsubnormal_fczero_vec( ; CHECK-SAME: <2 x double> [[A:%.*]]) { -; CHECK-NEXT: [[I64:%.*]] = bitcast <2 x double> [[A]] to <2 x i64> -; CHECK-NEXT: [[AND:%.*]] = and <2 x i64> [[I64]], splat (i64 9218868437227405312) -; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i64> [[AND]], zeroinitializer +; CHECK-NEXT: [[CMP:%.*]] = call <2 x i1> @llvm.is.fpclass.v2f64(<2 x double> [[A]], i32 240) ; CHECK-NEXT: ret <2 x i1> [[CMP]] ; %i64 = bitcast <2 x double> %a to <2 x i64> @@ -611,9 +605,7 @@ define <2 x i1> @f64_fcsubnormal_fczero_vec(<2 x double> %a) { define <2 x i1> @f64_no_fcsubnormal_fczero_vec(<2 x double> %a) { ; CHECK-LABEL: define <2 x i1> @f64_no_fcsubnormal_fczero_vec( ; CHECK-SAME: <2 x double> [[A:%.*]]) { -; CHECK-NEXT: [[I64:%.*]] = bitcast <2 x double> [[A]] to <2 x i64> -; CHECK-NEXT: [[AND:%.*]] = and <2 x i64> [[I64]], splat (i64 9218868437227405312) -; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i64> [[AND]], zeroinitializer +; CHECK-NEXT: [[CMP:%.*]] = call <2 x i1> @llvm.is.fpclass.v2f64(<2 x double> [[A]], i32 783) ; CHECK-NEXT: ret <2 x i1> [[CMP]] ; %i64 = bitcast <2 x double> %a to <2 x i64>