Index: lib/Transforms/InstCombine/InstCombineAndOrXor.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -1748,7 +1748,7 @@ // E.g. (icmp sgt x, n) | (icmp slt x, 0) --> icmp ugt x, n if (Value *V = simplifyRangeCheck(RHS, LHS, /*Inverted=*/true)) return V; - + // This only handles icmp of constants: (icmp1 A, C1) | (icmp2 B, C2). if (!LHSCst || !RHSCst) return nullptr; @@ -2748,5 +2748,18 @@ } } + // If we are XORing the sign bit of a floating-point value, convert + // this to fsub from -0.0, then cast back to integer. + ConstantInt *CI; + if (CastInst *Op0C = dyn_cast(Op0)) { + Type *SrcTy = Op0C->getOperand(0)->getType(); + if (isa(Op0C) && SrcTy->isFloatingPointTy() && + match(Op1, m_ConstantInt(CI)) && CI->isMinValue(true)) { + Value *Call = Builder->CreateFSub( + ConstantFP::getNegativeZero(SrcTy), Op0C->getOperand(0)); + return CastInst::CreateBitOrPointerCast(Call, I.getType()); + } + } + return Changed ? &I : nullptr; } Index: test/Transforms/InstCombine/xor2.ll =================================================================== --- test/Transforms/InstCombine/xor2.ll +++ test/Transforms/InstCombine/xor2.ll @@ -23,7 +23,7 @@ define i32 @test2(i32 %tmp1) { ; CHECK-LABEL: @test2( ; CHECK-NEXT: and i32 %tmp1, 32 -; CHECK-NEXT: or i32 %ovm, 8 +; CHECK-NEXT: or i32 %ovm, 8 ; CHECK-NEXT: ret i32 %ovm = and i32 %tmp1, 32 %ov3 = add i32 %ovm, 145 @@ -36,7 +36,7 @@ ; CHECK-NEXT: and i32 %tmp1, 32 ; CHECK-NEXT: or i32 %ovm, 8 ; CHECK-NEXT: ret i32 - %ovm = or i32 %tmp1, 145 + %ovm = or i32 %tmp1, 145 %ov31 = and i32 %ovm, 177 %ov110 = xor i32 %ov31, 153 ret i32 %ov110 @@ -68,7 +68,7 @@ } ; defect-1 in rdar://12329730 -; Simplify (X^Y) -> X or Y in the user's context if we know that +; Simplify (X^Y) -> X or Y in the user's context if we know that ; only bits from X or Y are demanded. ; e.g. the "x ^ 1234" can be optimized into x in the context of "t >> 16". ; Put in other word, t >> 16 -> x >> 16. @@ -172,3 +172,46 @@ ; CHECK-NEXT: %[[xor:.*]] = xor i32 %[[and]], %c ; CHECK-NEXT: ret i32 %[[xor]] } + + +define i64 @fsub_double(double %x) { +; CHECK-LABEL: @fsub_double( +; CHECK-NEXT: %1 = fsub double -0.000000e+00, %x +; CHECK-NEXT: %xor = bitcast double %1 to i64 +; CHECK-NEXT: ret i64 %xor + %bc = bitcast double %x to i64 + %xor = xor i64 %bc, -9223372036854775808 + ret i64 %xor +} + +define i64 @fsub_double_swap(double %x) { +; CHECK-LABEL: @fsub_double_swap( +; CHECK-NEXT: %1 = fsub double -0.000000e+00, %x +; CHECK-NEXT: %xor = bitcast double %1 to i64 +; CHECK-NEXT: ret i64 %xor + %bc = bitcast double %x to i64 + %xor = xor i64 -9223372036854775808, %bc + ret i64 %xor +} + +define i32 @fsub_float(float %x) { +; CHECK-LABEL: @fsub_float( +; CHECK-NEXT: %1 = fsub float -0.000000e+00, %x +; CHECK-NEXT: %xor = bitcast float %1 to i32 +; CHECK-NEXT: ret i32 %xor + %bc = bitcast float %x to i32 + %xor = xor i32 %bc, -2147483648 + ret i32 %xor +} + +; Make sure that only a bitcast is transformed. + +define i64 @fsub_double_not_bitcast(double %x) { +; CHECK-LABEL: @fsub_double_not_bitcast( +; CHECK-NEXT: %bc = fptoui double %x to i64 +; CHECK-NEXT: %xor = xor i64 %bc, -9223372036854775808 +; CHECK-NEXT: ret i64 %xor + %bc = fptoui double %x to i64 + %xor = xor i64 %bc, -9223372036854775808 + ret i64 %xor +}