[llvm] [InstCombine] Fold isnan idioms (PR #101510)
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 1 09:24:21 PDT 2024
================
@@ -647,6 +637,221 @@ define i1 @f32_fcposinf_multiuse_strictfp(float %a) strictfp {
ret i1 %cmp
}
+define i1 @isnan_idiom(double %x) {
+; CHECK-LABEL: define i1 @isnan_idiom(
+; CHECK-SAME: double [[X:%.*]]) {
+; CHECK-NEXT: [[RET:%.*]] = fcmp uno double [[X]], 0.000000e+00
+; CHECK-NEXT: ret i1 [[RET]]
+;
+ %bits = bitcast double %x to i64
+ %mask1 = and i64 %bits, 9218868437227405312
+ %cond1 = icmp eq i64 %mask1, 9218868437227405312
+ %mask2 = and i64 %bits, 4503599627370495
+ %cond2 = icmp ne i64 %mask2, 0
+ %ret = and i1 %cond1, %cond2
+ ret i1 %ret
+}
+
+define <2 x i1> @isnan_idiom_vec(<2 x double> %x) {
+; CHECK-LABEL: define <2 x i1> @isnan_idiom_vec(
+; CHECK-SAME: <2 x double> [[X:%.*]]) {
+; CHECK-NEXT: [[RET:%.*]] = fcmp uno <2 x double> [[X]], zeroinitializer
+; CHECK-NEXT: ret <2 x i1> [[RET]]
+;
+ %bits = bitcast <2 x double> %x to <2 x i64>
+ %mask1 = and <2 x i64> %bits, splat(i64 9218868437227405312)
+ %cond1 = icmp eq <2 x i64> %mask1, splat(i64 9218868437227405312)
+ %mask2 = and <2 x i64> %bits, splat(i64 4503599627370495)
+ %cond2 = icmp ne <2 x i64> %mask2, zeroinitializer
+ %ret = and <2 x i1> %cond1, %cond2
+ ret <2 x i1> %ret
+}
+
+define i1 @isnan_idiom_commuted(double %x) {
+; CHECK-LABEL: define i1 @isnan_idiom_commuted(
+; CHECK-SAME: double [[X:%.*]]) {
+; CHECK-NEXT: [[RET:%.*]] = fcmp uno double [[X]], 0.000000e+00
+; CHECK-NEXT: ret i1 [[RET]]
+;
+ %bits = bitcast double %x to i64
+ %mask1 = and i64 %bits, 9218868437227405312
+ %cond1 = icmp eq i64 %mask1, 9218868437227405312
+ %mask2 = and i64 %bits, 4503599627370495
+ %cond2 = icmp ne i64 %mask2, 0
+ %ret = and i1 %cond2, %cond1
+ ret i1 %ret
+}
+
+define i1 @isnotnan_idiom(double %x) {
+; CHECK-LABEL: define i1 @isnotnan_idiom(
+; CHECK-SAME: double [[X:%.*]]) {
+; CHECK-NEXT: [[RET:%.*]] = fcmp ord double [[X]], 0.000000e+00
+; CHECK-NEXT: ret i1 [[RET]]
+;
+ %bits = bitcast double %x to i64
+ %mask1 = and i64 %bits, 9218868437227405312
+ %cond1 = icmp ne i64 %mask1, 9218868437227405312
+ %mask2 = and i64 %bits, 4503599627370495
+ %cond2 = icmp eq i64 %mask2, 0
+ %ret = or i1 %cond1, %cond2
+ ret i1 %ret
+}
+
+; negative tests
+
+define i1 @isnan_idiom_no_implicit(double %x) noimplicitfloat {
+; CHECK-LABEL: define i1 @isnan_idiom_no_implicit(
+; CHECK-SAME: double [[X:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT: [[BITS:%.*]] = bitcast double [[X]] to i64
+; CHECK-NEXT: [[MASK1:%.*]] = and i64 [[BITS]], 9218868437227405312
+; CHECK-NEXT: [[COND1:%.*]] = icmp eq i64 [[MASK1]], 9218868437227405312
+; CHECK-NEXT: [[MASK2:%.*]] = and i64 [[BITS]], 4503599627370495
+; CHECK-NEXT: [[COND2:%.*]] = icmp ne i64 [[MASK2]], 0
+; CHECK-NEXT: [[RET:%.*]] = and i1 [[COND1]], [[COND2]]
+; CHECK-NEXT: ret i1 [[RET]]
+;
+ %bits = bitcast double %x to i64
+ %mask1 = and i64 %bits, 9218868437227405312
+ %cond1 = icmp eq i64 %mask1, 9218868437227405312
+ %mask2 = and i64 %bits, 4503599627370495
+ %cond2 = icmp ne i64 %mask2, 0
+ %ret = and i1 %cond1, %cond2
+ ret i1 %ret
+}
+
+define i1 @isnan_idiom_wrong_pred1(double %x) {
+; CHECK-LABEL: define i1 @isnan_idiom_wrong_pred1(
+; CHECK-SAME: double [[X:%.*]]) {
+; CHECK-NEXT: [[BITS:%.*]] = bitcast double [[X]] to i64
+; CHECK-NEXT: [[MASK1:%.*]] = and i64 [[BITS]], 9218868437227405312
+; CHECK-NEXT: [[COND1:%.*]] = icmp ne i64 [[MASK1]], 9218868437227405312
+; CHECK-NEXT: [[MASK2:%.*]] = and i64 [[BITS]], 4503599627370495
+; CHECK-NEXT: [[COND2:%.*]] = icmp ne i64 [[MASK2]], 0
+; CHECK-NEXT: [[RET:%.*]] = and i1 [[COND1]], [[COND2]]
+; CHECK-NEXT: ret i1 [[RET]]
+;
+ %bits = bitcast double %x to i64
+ %mask1 = and i64 %bits, 9218868437227405312
+ %cond1 = icmp ne i64 %mask1, 9218868437227405312
+ %mask2 = and i64 %bits, 4503599627370495
+ %cond2 = icmp ne i64 %mask2, 0
+ %ret = and i1 %cond1, %cond2
+ ret i1 %ret
+}
+
+define i1 @isnan_idiom_wrong_pred2(double %x) {
+; CHECK-LABEL: define i1 @isnan_idiom_wrong_pred2(
+; CHECK-SAME: double [[X:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.fabs.f64(double [[X]])
+; CHECK-NEXT: [[RET:%.*]] = fcmp oeq double [[TMP1]], 0x7FF0000000000000
+; CHECK-NEXT: ret i1 [[RET]]
+;
+ %bits = bitcast double %x to i64
+ %mask1 = and i64 %bits, 9218868437227405312
+ %cond1 = icmp eq i64 %mask1, 9218868437227405312
+ %mask2 = and i64 %bits, 4503599627370495
+ %cond2 = icmp eq i64 %mask2, 0
+ %ret = and i1 %cond1, %cond2
+ ret i1 %ret
+}
+
+define i1 @isnan_idiom_wrong_pred3(double %x) {
+; CHECK-LABEL: define i1 @isnan_idiom_wrong_pred3(
+; CHECK-SAME: double [[X:%.*]]) {
+; CHECK-NEXT: [[BITS:%.*]] = bitcast double [[X]] to i64
+; CHECK-NEXT: [[MASK1:%.*]] = and i64 [[BITS]], 9218868437227405312
+; CHECK-NEXT: [[COND1:%.*]] = icmp eq i64 [[MASK1]], 9218868437227405312
+; CHECK-NEXT: [[MASK2:%.*]] = and i64 [[BITS]], 4503599627370495
+; CHECK-NEXT: [[COND2:%.*]] = icmp ne i64 [[MASK2]], 0
+; CHECK-NEXT: [[RET:%.*]] = or i1 [[COND1]], [[COND2]]
+; CHECK-NEXT: ret i1 [[RET]]
+;
+ %bits = bitcast double %x to i64
+ %mask1 = and i64 %bits, 9218868437227405312
+ %cond1 = icmp eq i64 %mask1, 9218868437227405312
+ %mask2 = and i64 %bits, 4503599627370495
+ %cond2 = icmp ne i64 %mask2, 0
+ %ret = or i1 %cond1, %cond2
+ ret i1 %ret
+}
+
+define i1 @isnan_idiom_wrong_mask1(double %x) {
+; CHECK-LABEL: define i1 @isnan_idiom_wrong_mask1(
+; CHECK-SAME: double [[X:%.*]]) {
+; CHECK-NEXT: [[BITS:%.*]] = bitcast double [[X]] to i64
+; CHECK-NEXT: [[MASK1:%.*]] = and i64 [[BITS]], 9218868437227405311
+; CHECK-NEXT: [[COND1:%.*]] = icmp eq i64 [[MASK1]], 9218868437227405311
+; CHECK-NEXT: ret i1 [[COND1]]
+;
+ %bits = bitcast double %x to i64
+ %mask1 = and i64 %bits, 9218868437227405311
+ %cond1 = icmp eq i64 %mask1, 9218868437227405311
+ %mask2 = and i64 %bits, 4503599627370495
+ %cond2 = icmp ne i64 %mask2, 0
+ %ret = and i1 %cond1, %cond2
+ ret i1 %ret
+}
+
+define i1 @isnan_idiom_wrong_mask2(double %x) {
+; CHECK-LABEL: define i1 @isnan_idiom_wrong_mask2(
+; CHECK-SAME: double [[X:%.*]]) {
+; CHECK-NEXT: [[BITS:%.*]] = bitcast double [[X]] to i64
+; CHECK-NEXT: [[MASK1:%.*]] = and i64 [[BITS]], 9218868437227405312
+; CHECK-NEXT: [[COND1:%.*]] = icmp eq i64 [[MASK1]], 9218868437227405312
+; CHECK-NEXT: [[MASK2:%.*]] = and i64 [[BITS]], 4503599627370494
+; CHECK-NEXT: [[COND2:%.*]] = icmp ne i64 [[MASK2]], 0
+; CHECK-NEXT: [[RET:%.*]] = and i1 [[COND1]], [[COND2]]
+; CHECK-NEXT: ret i1 [[RET]]
+;
+ %bits = bitcast double %x to i64
+ %mask1 = and i64 %bits, 9218868437227405312
+ %cond1 = icmp eq i64 %mask1, 9218868437227405312
+ %mask2 = and i64 %bits, 4503599627370494
+ %cond2 = icmp ne i64 %mask2, 0
+ %ret = and i1 %cond1, %cond2
+ ret i1 %ret
+}
+
+define i1 @isnan_idiom_wrong_mask3(double %x) {
+; CHECK-LABEL: define i1 @isnan_idiom_wrong_mask3(
+; CHECK-SAME: double [[X:%.*]]) {
+; CHECK-NEXT: [[BITS:%.*]] = bitcast double [[X]] to i64
+; CHECK-NEXT: [[MASK1:%.*]] = and i64 [[BITS]], 9218868437227405312
+; CHECK-NEXT: [[COND1:%.*]] = icmp eq i64 [[MASK1]], 9218868437227405312
+; CHECK-NEXT: [[MASK2:%.*]] = and i64 [[BITS]], 4503599627370495
+; CHECK-NEXT: [[COND2:%.*]] = icmp ne i64 [[MASK2]], 4503599627370495
+; CHECK-NEXT: [[RET:%.*]] = and i1 [[COND1]], [[COND2]]
+; CHECK-NEXT: ret i1 [[RET]]
+;
+ %bits = bitcast double %x to i64
+ %mask1 = and i64 %bits, 9218868437227405312
+ %cond1 = icmp eq i64 %mask1, 9218868437227405312
+ %mask2 = and i64 %bits, 4503599627370495
+ %cond2 = icmp ne i64 %mask2, 4503599627370495
+ %ret = and i1 %cond1, %cond2
+ ret i1 %ret
+}
+
+define i1 @isnan_idiom_invalid_bitcast(<2 x float> %x) {
+; CHECK-LABEL: define i1 @isnan_idiom_invalid_bitcast(
+; CHECK-SAME: <2 x float> [[X:%.*]]) {
+; CHECK-NEXT: [[BITS:%.*]] = bitcast <2 x float> [[X]] to i64
+; CHECK-NEXT: [[MASK1:%.*]] = and i64 [[BITS]], 9218868437227405312
+; CHECK-NEXT: [[COND1:%.*]] = icmp eq i64 [[MASK1]], 9218868437227405312
+; CHECK-NEXT: [[MASK2:%.*]] = and i64 [[BITS]], 4503599627370495
+; CHECK-NEXT: [[COND2:%.*]] = icmp ne i64 [[MASK2]], 0
+; CHECK-NEXT: [[RET:%.*]] = and i1 [[COND1]], [[COND2]]
+; CHECK-NEXT: ret i1 [[RET]]
+;
+ %bits = bitcast <2 x float> %x to i64
+ %mask1 = and i64 %bits, 9218868437227405312
+ %cond1 = icmp eq i64 %mask1, 9218868437227405312
+ %mask2 = and i64 %bits, 4503599627370495
+ %cond2 = icmp ne i64 %mask2, 0
+ %ret = and i1 %cond1, %cond2
+ ret i1 %ret
+}
+
----------------
arsenm wrote:
Negative test for the ppcf128 case?
https://github.com/llvm/llvm-project/pull/101510
More information about the llvm-commits
mailing list