Index: llvm/trunk/lib/Analysis/ValueTracking.cpp =================================================================== --- llvm/trunk/lib/Analysis/ValueTracking.cpp +++ llvm/trunk/lib/Analysis/ValueTracking.cpp @@ -1065,7 +1065,8 @@ } case Instruction::BitCast: { Type *SrcTy = I->getOperand(0)->getType(); - if ((SrcTy->isIntegerTy() || SrcTy->isPointerTy()) && + if ((SrcTy->isIntegerTy() || SrcTy->isPointerTy() || + SrcTy->isFloatingPointTy()) && // TODO: For now, not handling conversions like: // (bitcast i64 %x to <2 x i32>) !I->getType()->isVectorTy()) { @@ -1378,6 +1379,12 @@ KnownZero |= APInt::getHighBitsSet(BitWidth, BitWidth - LowBits); break; } + case Intrinsic::fabs: { + Type *Ty = II->getType(); + APInt SignBit = APInt::getSignBit(Ty->getScalarSizeInBits()); + KnownZero |= APInt::getSplat(Ty->getPrimitiveSizeInBits(), SignBit); + break; + } case Intrinsic::x86_sse42_crc32_64_64: KnownZero |= APInt::getHighBitsSet(64, 32); break; @@ -1477,8 +1484,9 @@ unsigned BitWidth = KnownZero.getBitWidth(); assert((V->getType()->isIntOrIntVectorTy() || + V->getType()->isFPOrFPVectorTy() || V->getType()->getScalarType()->isPointerTy()) && - "Not integer or pointer type!"); + "Not integer, floating point, or pointer type!"); assert((DL.getTypeSizeInBits(V->getType()->getScalarType()) == BitWidth) && (!V->getType()->isIntOrIntVectorTy() || V->getType()->getScalarSizeInBits() == BitWidth) && Index: llvm/trunk/test/Transforms/InstCombine/fabs.ll =================================================================== --- llvm/trunk/test/Transforms/InstCombine/fabs.ll +++ llvm/trunk/test/Transforms/InstCombine/fabs.ll @@ -41,6 +41,7 @@ declare float @llvm.fabs.f32(float) declare double @llvm.fabs.f64(double) declare fp128 @llvm.fabs.f128(fp128) +declare <4 x float> @llvm.fabs.v4f32(<4 x float>) define float @square_fabs_intrinsic_f32(float %x) { %mul = fmul float %x, %x @@ -98,3 +99,27 @@ ; CHECK-NEXT: ret float %sq } +; A scalar fabs op makes the sign bit zero, so masking off all of the other bits means we can return zero. + +define i32 @fabs_value_tracking_f32(float %x) { + %call = call float @llvm.fabs.f32(float %x) + %bc = bitcast float %call to i32 + %and = and i32 %bc, 2147483648 + ret i32 %and + +; CHECK-LABEL: fabs_value_tracking_f32( +; CHECK: ret i32 0 +} + +; TODO: A vector fabs op makes the sign bits zero, so masking off all of the other bits means we can return zero. + +define <4 x i32> @fabs_value_tracking_v4f32(<4 x float> %x) { + %call = call <4 x float> @llvm.fabs.v4f32(<4 x float> %x) + %bc = bitcast <4 x float> %call to <4 x i32> + %and = and <4 x i32> %bc, + ret <4 x i32> %and + +; CHECK-LABEL: fabs_value_tracking_v4f32( +; CHECK: ret <4 x i32> %and +} +