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;
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
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:%.*]], <i32 2147483647, i32 2147483647>
+; 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>
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
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
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