Index: llvm/lib/Analysis/ValueTracking.cpp =================================================================== --- llvm/lib/Analysis/ValueTracking.cpp +++ llvm/lib/Analysis/ValueTracking.cpp @@ -3662,6 +3662,14 @@ break; case Intrinsic::canonicalize: case Intrinsic::arithmetic_fence: + case Intrinsic::floor: + case Intrinsic::ceil: + case Intrinsic::trunc: + case Intrinsic::rint: + case Intrinsic::nearbyint: + case Intrinsic::round: + case Intrinsic::roundeven: + case Intrinsic::fptrunc_round: return cannotBeOrderedLessThanZeroImpl(I->getOperand(0), TLI, SignBitOnly, Depth + 1); case Intrinsic::maxnum: { Value *V0 = I->getOperand(0), *V1 = I->getOperand(1); 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 @@ -277,7 +277,16 @@ } declare float @llvm.fabs.f32(float) +declare double @llvm.fabs.f64(double) declare float @llvm.canonicalize.f32(float) +declare float @llvm.floor.f32(float) +declare float @llvm.ceil.f32(float) +declare float @llvm.trunc.f32(float) +declare float @llvm.rint.f32(float) +declare float @llvm.nearbyint.f32(float) +declare float @llvm.round.f32(float) +declare float @llvm.roundeven.f32(float) +declare float @llvm.fptrunc.round.f32.f64(double, metadata) declare float @llvm.arithmetic.fence.f32(float) declare float @llvm.copysign.f32(float, float) declare <2 x float> @llvm.fabs.v2f32(<2 x float>) @@ -990,3 +999,179 @@ %cmp = fcmp nnan oge float %copysign, 0.0 ret i1 %cmp } + +; https://alive2.llvm.org/ce/z/Y-EyY3 +define i1 @floor_known_positive(float %a) { +; CHECK-LABEL: @floor_known_positive( +; CHECK-NEXT: ret i1 true +; + %fabs = call float @llvm.fabs.f32(float %a) + %known.positive = call float @llvm.floor.f32(float %fabs) + %cmp = fcmp nnan oge float %known.positive, 0.0 + ret i1 %cmp +} + +define i1 @floor_unknown_positive(float %unknown) { +; CHECK-LABEL: @floor_unknown_positive( +; CHECK-NEXT: [[OP:%.*]] = call float @llvm.floor.f32(float [[UNKNOWN:%.*]]) +; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan oge float [[OP]], 0.000000e+00 +; CHECK-NEXT: ret i1 [[CMP]] +; + %op = call float @llvm.floor.f32(float %unknown) + %cmp = fcmp nnan oge float %op, 0.0 + ret i1 %cmp +} + +; https://alive2.llvm.org/ce/z/3tBUoW +define i1 @ceil_known_positive(float %a) { +; CHECK-LABEL: @ceil_known_positive( +; CHECK-NEXT: ret i1 true +; + %fabs = call float @llvm.fabs.f32(float %a) + %known.positive = call float @llvm.ceil.f32(float %fabs) + %cmp = fcmp nnan oge float %known.positive, 0.0 + ret i1 %cmp +} + +define i1 @ceil_unknown_positive(float %unknown) { +; CHECK-LABEL: @ceil_unknown_positive( +; CHECK-NEXT: [[OP:%.*]] = call float @llvm.ceil.f32(float [[UNKNOWN:%.*]]) +; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan oge float [[OP]], 0.000000e+00 +; CHECK-NEXT: ret i1 [[CMP]] +; + + %op = call float @llvm.ceil.f32(float %unknown) + %cmp = fcmp nnan oge float %op, 0.0 + ret i1 %cmp +} + +; https://alive2.llvm.org/ce/z/RbyJPX +define i1 @trunc_known_positive(float %a) { +; CHECK-LABEL: @trunc_known_positive( +; CHECK-NEXT: ret i1 true +; + %fabs = call float @llvm.fabs.f32(float %a) + %known.positive = call float @llvm.trunc.f32(float %fabs) + %cmp = fcmp nnan oge float %known.positive, 0.0 + ret i1 %cmp +} + +define i1 @trunc_unknown_positive(float %unknown) { +; CHECK-LABEL: @trunc_unknown_positive( +; CHECK-NEXT: [[OP:%.*]] = call float @llvm.trunc.f32(float [[UNKNOWN:%.*]]) +; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan oge float [[OP]], 0.000000e+00 +; CHECK-NEXT: ret i1 [[CMP]] +; + %op = call float @llvm.trunc.f32(float %unknown) + %cmp = fcmp nnan oge float %op, 0.0 + ret i1 %cmp +} + +; https://alive2.llvm.org/ce/z/bjC2Jm +define i1 @rint_known_positive(float %a) { +; CHECK-LABEL: @rint_known_positive( +; CHECK-NEXT: ret i1 true +; + %fabs = call float @llvm.fabs.f32(float %a) + %known.positive = call float @llvm.rint.f32(float %fabs) + %cmp = fcmp nnan oge float %known.positive, 0.0 + ret i1 %cmp +} + +define i1 @rint_unknown_positive(float %unknown) { +; CHECK-LABEL: @rint_unknown_positive( +; CHECK-NEXT: [[OP:%.*]] = call float @llvm.rint.f32(float [[UNKNOWN:%.*]]) +; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan oge float [[OP]], 0.000000e+00 +; CHECK-NEXT: ret i1 [[CMP]] +; + %op = call float @llvm.rint.f32(float %unknown) + %cmp = fcmp nnan oge float %op, 0.0 + ret i1 %cmp +} + +; https://alive2.llvm.org/ce/z/dFiL9n +define i1 @nearbyint_known_positive(float %a) { +; CHECK-LABEL: @nearbyint_known_positive( +; CHECK-NEXT: ret i1 true +; + %fabs = call float @llvm.fabs.f32(float %a) + %known.positive = call float @llvm.nearbyint.f32(float %fabs) + %cmp = fcmp nnan oge float %known.positive, 0.0 + ret i1 %cmp +} + +define i1 @nearbyint_unknown_positive(float %unknown) { +; CHECK-LABEL: @nearbyint_unknown_positive( +; CHECK-NEXT: [[OP:%.*]] = call float @llvm.nearbyint.f32(float [[UNKNOWN:%.*]]) +; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan oge float [[OP]], 0.000000e+00 +; CHECK-NEXT: ret i1 [[CMP]] +; + %op = call float @llvm.nearbyint.f32(float %unknown) + %cmp = fcmp nnan oge float %op, 0.0 + ret i1 %cmp +} + +; https://alive2.llvm.org/ce/z/kPhS-d +define i1 @round_known_positive(float %a) { +; CHECK-LABEL: @round_known_positive( +; CHECK-NEXT: ret i1 true +; + %fabs = call float @llvm.fabs.f32(float %a) + %known.positive = call float @llvm.round.f32(float %fabs) + %cmp = fcmp nnan oge float %known.positive, 0.0 + ret i1 %cmp +} + +define i1 @round_unknown_positive(float %unknown) { +; CHECK-LABEL: @round_unknown_positive( +; CHECK-NEXT: [[OP:%.*]] = call float @llvm.round.f32(float [[UNKNOWN:%.*]]) +; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan oge float [[OP]], 0.000000e+00 +; CHECK-NEXT: ret i1 [[CMP]] +; + %op = call float @llvm.round.f32(float %unknown) + %cmp = fcmp nnan oge float %op, 0.0 + ret i1 %cmp +} + +; https://alive2.llvm.org/ce/z/Z_tfsu +define i1 @roundeven_known_positive(float %a) { +; CHECK-LABEL: @roundeven_known_positive( +; CHECK-NEXT: ret i1 true +; + %fabs = call float @llvm.fabs.f32(float %a) + %known.positive = call float @llvm.roundeven.f32(float %fabs) + %cmp = fcmp nnan oge float %known.positive, 0.0 + ret i1 %cmp +} + +define i1 @roundeven_unknown_positive(float %unknown) { +; CHECK-LABEL: @roundeven_unknown_positive( +; CHECK-NEXT: [[OP:%.*]] = call float @llvm.roundeven.f32(float [[UNKNOWN:%.*]]) +; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan oge float [[OP]], 0.000000e+00 +; CHECK-NEXT: ret i1 [[CMP]] +; + %op = call float @llvm.roundeven.f32(float %unknown) + %cmp = fcmp nnan oge float %op, 0.0 + ret i1 %cmp +} + +define i1 @fptrunc_round_known_positive(double %a) { +; CHECK-LABEL: @fptrunc_round_known_positive( +; CHECK-NEXT: ret i1 true +; + %fabs = call double @llvm.fabs.f64(double %a) + %known.positive = call float @llvm.fptrunc.round.f32.f64(double %fabs, metadata !"round.downward") + %cmp = fcmp nnan oge float %known.positive, 0.0 + ret i1 %cmp +} + +define i1 @fptrunc_round_unknown_positive(double %unknown) { +; CHECK-LABEL: @fptrunc_round_unknown_positive( +; CHECK-NEXT: [[OP:%.*]] = call float @llvm.fptrunc.round.f32.f64(double [[UNKNOWN:%.*]], metadata !"round.downward") +; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan oge float [[OP]], 0.000000e+00 +; CHECK-NEXT: ret i1 [[CMP]] +; + %op = call float @llvm.fptrunc.round.f32.f64(double %unknown, metadata !"round.downward") + %cmp = fcmp nnan oge float %op, 0.0 + ret i1 %cmp +}