mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-18 18:42:46 +02:00
[InstCombine] fold fcmp-of-copysign idiom
As discussed in: https://llvm.org/PR49179 ...this pattern shows up in library code. There are several potential generalizations as noted, but we need to be careful that we get FP special-values right, and it's not clear how much variation we should expect to see from this exact idiom.
This commit is contained in:
parent
06ead2a50a
commit
a2b8bdd4e5
@ -6267,6 +6267,26 @@ Instruction *InstCombinerImpl::visitFCmpInst(FCmpInst &I) {
|
||||
}
|
||||
}
|
||||
|
||||
// Convert a sign-bit test of an FP value into a cast and integer compare.
|
||||
// TODO: Simplify if the copysign constant is 0.0 or NaN.
|
||||
// TODO: Handle non-zero compare constants.
|
||||
// TODO: Handle other predicates.
|
||||
const APFloat *C;
|
||||
if (match(Op0, m_OneUse(m_Intrinsic<Intrinsic::copysign>(m_APFloat(C),
|
||||
m_Value(X)))) &&
|
||||
match(Op1, m_AnyZeroFP()) && !C->isZero() && !C->isNaN()) {
|
||||
Type *IntType = Builder.getIntNTy(X->getType()->getScalarSizeInBits());
|
||||
if (auto *VecTy = dyn_cast<VectorType>(OpType))
|
||||
IntType = VectorType::get(IntType, VecTy->getElementCount());
|
||||
|
||||
// copysign(non-zero constant, X) < 0.0 --> (bitcast X) < 0
|
||||
if (Pred == FCmpInst::FCMP_OLT) {
|
||||
Value *IntX = Builder.CreateBitCast(X, IntType);
|
||||
return new ICmpInst(ICmpInst::ICMP_SLT, IntX,
|
||||
ConstantInt::getNullValue(IntType));
|
||||
}
|
||||
}
|
||||
|
||||
if (I.getType()->isVectorTy())
|
||||
if (Instruction *Res = foldVectorCmp(I, Builder))
|
||||
return Res;
|
||||
|
@ -583,8 +583,8 @@ define <2 x i1> @test27_recipX_gt_vecsplat(<2 x float> %X) {
|
||||
|
||||
define i1 @is_signbit_set(double %x) {
|
||||
; CHECK-LABEL: @is_signbit_set(
|
||||
; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double 1.000000e+00, double [[X:%.*]])
|
||||
; CHECK-NEXT: [[R:%.*]] = fcmp olt double [[S]], 0.000000e+00
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = bitcast double [[X:%.*]] to i64
|
||||
; CHECK-NEXT: [[R:%.*]] = icmp slt i64 [[TMP1]], 0
|
||||
; CHECK-NEXT: ret i1 [[R]]
|
||||
;
|
||||
%s = call double @llvm.copysign.f64(double 1.0, double %x)
|
||||
@ -592,10 +592,12 @@ define i1 @is_signbit_set(double %x) {
|
||||
ret i1 %r
|
||||
}
|
||||
|
||||
; Vectors are ok; the sign of zero in the compare doesn't matter; the copysign constant can be any non-zero number.
|
||||
|
||||
define <2 x i1> @is_signbit_set_anyzero(<2 x double> %x) {
|
||||
; CHECK-LABEL: @is_signbit_set_anyzero(
|
||||
; CHECK-NEXT: [[S:%.*]] = call <2 x double> @llvm.copysign.v2f64(<2 x double> <double 4.200000e+01, double 4.200000e+01>, <2 x double> [[X:%.*]])
|
||||
; CHECK-NEXT: [[R:%.*]] = fcmp olt <2 x double> [[S]], zeroinitializer
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x double> [[X:%.*]] to <2 x i64>
|
||||
; CHECK-NEXT: [[R:%.*]] = icmp slt <2 x i64> [[TMP1]], zeroinitializer
|
||||
; CHECK-NEXT: ret <2 x i1> [[R]]
|
||||
;
|
||||
%s = call <2 x double> @llvm.copysign.v2f64(<2 x double> <double 42.0, double 42.0>, <2 x double> %x)
|
||||
@ -603,6 +605,8 @@ define <2 x i1> @is_signbit_set_anyzero(<2 x double> %x) {
|
||||
ret <2 x i1> %r
|
||||
}
|
||||
|
||||
; TODO: Handle different predicates.
|
||||
|
||||
define i1 @is_signbit_clear(double %x) {
|
||||
; CHECK-LABEL: @is_signbit_clear(
|
||||
; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double -4.200000e+01, double [[X:%.*]])
|
||||
@ -614,6 +618,8 @@ define i1 @is_signbit_clear(double %x) {
|
||||
ret i1 %r
|
||||
}
|
||||
|
||||
; Negative test - uses
|
||||
|
||||
define i1 @is_signbit_set_extra_use(double %x, double* %p) {
|
||||
; CHECK-LABEL: @is_signbit_set_extra_use(
|
||||
; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double 1.000000e+00, double [[X:%.*]])
|
||||
@ -627,6 +633,8 @@ define i1 @is_signbit_set_extra_use(double %x, double* %p) {
|
||||
ret i1 %r
|
||||
}
|
||||
|
||||
; TODO: Handle non-zero compare constant.
|
||||
|
||||
define i1 @is_signbit_clear_nonzero(double %x) {
|
||||
; CHECK-LABEL: @is_signbit_clear_nonzero(
|
||||
; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double -4.200000e+01, double [[X:%.*]])
|
||||
@ -638,6 +646,8 @@ define i1 @is_signbit_clear_nonzero(double %x) {
|
||||
ret i1 %r
|
||||
}
|
||||
|
||||
; TODO: Handle zero copysign constant.
|
||||
|
||||
define i1 @is_signbit_set_simplify_zero(double %x) {
|
||||
; CHECK-LABEL: @is_signbit_set_simplify_zero(
|
||||
; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double 0.000000e+00, double [[X:%.*]])
|
||||
@ -649,6 +659,8 @@ define i1 @is_signbit_set_simplify_zero(double %x) {
|
||||
ret i1 %r
|
||||
}
|
||||
|
||||
; TODO: Handle NaN copysign constant.
|
||||
|
||||
define i1 @is_signbit_set_simplify_nan(double %x) {
|
||||
; CHECK-LABEL: @is_signbit_set_simplify_nan(
|
||||
; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double 0xFFFFFFFFFFFFFFFF, double [[X:%.*]])
|
||||
|
Loading…
Reference in New Issue
Block a user