Index: llvm/lib/Analysis/ValueTracking.cpp =================================================================== --- llvm/lib/Analysis/ValueTracking.cpp +++ llvm/lib/Analysis/ValueTracking.cpp @@ -3694,7 +3694,10 @@ case Intrinsic::exp2: case Intrinsic::fabs: return true; - + case Intrinsic::copysign: + // Only the sign operand matters. + return cannotBeOrderedLessThanZeroImpl(I->getOperand(1), TLI, true, + Depth + 1); case Intrinsic::sqrt: // sqrt(x) is always >= -0 or NaN. Moreover, sqrt(x) == -0 iff x == -0. if (!SignBitOnly) Index: llvm/test/Transforms/InstSimplify/floating-point-arithmetic.ll =================================================================== --- llvm/test/Transforms/InstSimplify/floating-point-arithmetic.ll +++ llvm/test/Transforms/InstSimplify/floating-point-arithmetic.ll @@ -279,6 +279,7 @@ declare float @llvm.fabs.f32(float) declare float @llvm.canonicalize.f32(float) declare float @llvm.arithmetic.fence.f32(float) +declare float @llvm.copysign.f32(float, float) declare <2 x float> @llvm.fabs.v2f32(<2 x float>) declare float @llvm.sqrt.f32(float) declare float @llvm.maxnum.f32(float, float) @@ -955,3 +956,37 @@ %cmp = fcmp nnan oge float %known.positive, 0.0 ret i1 %cmp } + +define i1 @copysign_known_positive_maybe_neg0(float %unknown, float %sign) { +; CHECK-LABEL: @copysign_known_positive_maybe_neg0( +; CHECK-NEXT: [[SQRT:%.*]] = call nnan ninf float @llvm.sqrt.f32(float [[SIGN:%.*]]) +; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[UNKNOWN:%.*]], float [[SQRT]]) +; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan oge float [[COPYSIGN]], 0.000000e+00 +; CHECK-NEXT: ret i1 [[CMP]] +; + %sqrt = call ninf nnan float @llvm.sqrt.f32(float %sign) + %copysign = call float @llvm.copysign.f32(float %unknown, float %sqrt) + %cmp = fcmp nnan oge float %copysign, 0.0 + ret i1 %cmp +} + +define i1 @copysign_known_positive(float %unknown, float %sign) { +; CHECK-LABEL: @copysign_known_positive( +; CHECK-NEXT: ret i1 true +; + %sqrt = call ninf nnan nsz float @llvm.sqrt.f32(float %sign) + %copysign = call float @llvm.copysign.f32(float %unknown, float %sqrt) + %cmp = fcmp nnan oge float %copysign, 0.0 + ret i1 %cmp +} + +define i1 @copysign_unknown_positive(float %unknown, float %unknown.sign) { +; CHECK-LABEL: @copysign_unknown_positive( +; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[UNKNOWN:%.*]], float [[UNKNOWN_SIGN:%.*]]) +; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan oge float [[COPYSIGN]], 0.000000e+00 +; CHECK-NEXT: ret i1 [[CMP]] +; + %copysign = call float @llvm.copysign.f32(float %unknown, float %unknown.sign) + %cmp = fcmp nnan oge float %copysign, 0.0 + ret i1 %cmp +}