From 482777123427622f15837cdbda97080798f6cc85 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Fri, 26 Aug 2022 11:15:09 -0400 Subject: [PATCH] [InstCombine] fold test of equality to 0.0 with bitcast operand fcmp oeq/une (bitcast X), 0.0 --> (and X, SignMaskC) ==/!= 0 https://alive2.llvm.org/ce/z/ZKATGN --- .../Transforms/InstCombine/InstCombineCompares.cpp | 19 +++++++++++++++++++ llvm/test/Transforms/InstCombine/fcmp.ll | 14 ++++++++++---- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index fd45257..4a0ba31 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -6888,6 +6888,25 @@ Instruction *InstCombinerImpl::visitFCmpInst(FCmpInst &I) { if (match(Op1, m_AnyZeroFP()) && !match(Op1, m_PosZeroFP())) return replaceOperand(I, 1, ConstantFP::getNullValue(OpType)); + // Ignore signbit of bitcasted int when comparing equality to FP 0.0: + // fcmp oeq/une (bitcast X), 0.0 --> (and X, SignMaskC) ==/!= 0 + if (match(Op1, m_PosZeroFP()) && + match(Op0, m_OneUse(m_BitCast(m_Value(X)))) && + X->getType()->getScalarSizeInBits() == OpType->getScalarSizeInBits()) { + ICmpInst::Predicate IntPred = ICmpInst::BAD_ICMP_PREDICATE; + if (Pred == FCmpInst::FCMP_OEQ) + IntPred = ICmpInst::ICMP_EQ; + else if (Pred == FCmpInst::FCMP_UNE) + IntPred = ICmpInst::ICMP_NE; + + if (IntPred != ICmpInst::BAD_ICMP_PREDICATE) { + Type *IntTy = X->getType(); + const APInt &SignMask = ~APInt::getSignMask(IntTy->getScalarSizeInBits()); + Value *MaskX = Builder.CreateAnd(X, ConstantInt::get(IntTy, SignMask)); + return new ICmpInst(IntPred, MaskX, ConstantInt::getNullValue(IntTy)); + } + } + // Handle fcmp with instruction LHS and constant RHS. Instruction *LHSI; Constant *RHSC; diff --git a/llvm/test/Transforms/InstCombine/fcmp.ll b/llvm/test/Transforms/InstCombine/fcmp.ll index 1d4a2c1..198a715 100644 --- a/llvm/test/Transforms/InstCombine/fcmp.ll +++ b/llvm/test/Transforms/InstCombine/fcmp.ll @@ -1215,8 +1215,8 @@ define i1 @fneg_une_swap(float %p) { define i1 @bitcast_eq0(i32 %x) { ; CHECK-LABEL: @bitcast_eq0( -; CHECK-NEXT: [[F:%.*]] = bitcast i32 [[X:%.*]] to float -; CHECK-NEXT: [[R:%.*]] = fcmp oeq float [[F]], 0.000000e+00 +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], 2147483647 +; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[TMP1]], 0 ; CHECK-NEXT: ret i1 [[R]] ; %f = bitcast i32 %x to float @@ -1226,8 +1226,8 @@ define i1 @bitcast_eq0(i32 %x) { define <2 x i1> @bitcast_ne0(<2 x i32> %x) { ; CHECK-LABEL: @bitcast_ne0( -; CHECK-NEXT: [[F:%.*]] = bitcast <2 x i32> [[X:%.*]] to <2 x float> -; CHECK-NEXT: [[R:%.*]] = fcmp une <2 x float> [[F]], zeroinitializer +; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[X:%.*]], +; CHECK-NEXT: [[R:%.*]] = icmp ne <2 x i32> [[TMP1]], zeroinitializer ; CHECK-NEXT: ret <2 x i1> [[R]] ; %f = bitcast <2 x i32> %x to <2 x float> @@ -1235,6 +1235,8 @@ define <2 x i1> @bitcast_ne0(<2 x i32> %x) { ret <2 x i1> %r } +; negative test - extra use + define i1 @bitcast_eq0_use(i32 %x) { ; CHECK-LABEL: @bitcast_eq0_use( ; CHECK-NEXT: [[F:%.*]] = bitcast i32 [[X:%.*]] to float @@ -1248,6 +1250,8 @@ define i1 @bitcast_eq0_use(i32 %x) { ret i1 %r } +; negative test - this could be transformed, but requires a new bitcast + define i1 @bitcast_nonint_eq0(<2 x i16> %x) { ; CHECK-LABEL: @bitcast_nonint_eq0( ; CHECK-NEXT: [[F:%.*]] = bitcast <2 x i16> [[X:%.*]] to float @@ -1259,6 +1263,8 @@ define i1 @bitcast_nonint_eq0(<2 x i16> %x) { ret i1 %r } +; negative test - wrong predicate + define i1 @bitcast_gt0(i32 %x) { ; CHECK-LABEL: @bitcast_gt0( ; CHECK-NEXT: [[F:%.*]] = bitcast i32 [[X:%.*]] to float -- 2.7.4