Index: llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -1720,7 +1720,7 @@ /// Return true if the cast from integer to FP can be proven to be exact for all /// possible inputs (the conversion does not lose any precision). -static bool isKnownExactCastIntToFP(CastInst &I) { +static bool isKnownExactCastIntToFP(CastInst &I, InstCombinerImpl &IC) { CastInst::CastOps Opcode = I.getOpcode(); assert((Opcode == CastInst::SIToFP || Opcode == CastInst::UIToFP) && "Unexpected cast"); @@ -1754,9 +1754,14 @@ return true; } - // TODO: // Try harder to find if the source integer type has less significant bits. // For example, compute number of sign bits or compute low bit mask. + KnownBits SrcKnown = llvm::computeKnownBits(Src, IC.getDataLayout()); + int LowBits = + (int)SrcTy->getScalarSizeInBits() - SrcKnown.countMinLeadingZeros(); + if (LowBits <= DestNumSigBits) + return true; + return false; } @@ -1937,7 +1942,7 @@ Value *Src = FPT.getOperand(0); if (isa(Src) || isa(Src)) { auto *FPCast = cast(Src); - if (isKnownExactCastIntToFP(*FPCast)) + if (isKnownExactCastIntToFP(*FPCast, *this)) return CastInst::Create(FPCast->getOpcode(), FPCast->getOperand(0), Ty); } @@ -1951,7 +1956,7 @@ Value *Src = FPExt.getOperand(0); if (isa(Src) || isa(Src)) { auto *FPCast = cast(Src); - if (isKnownExactCastIntToFP(*FPCast)) + if (isKnownExactCastIntToFP(*FPCast, *this)) return CastInst::Create(FPCast->getOpcode(), FPCast->getOperand(0), Ty); } @@ -1978,7 +1983,7 @@ // This means this is also safe for a signed input and unsigned output, since // a negative input would lead to undefined behavior. - if (!isKnownExactCastIntToFP(*OpI)) { + if (!isKnownExactCastIntToFP(*OpI, *this)) { // The first cast may not round exactly based on the source integer width // and FP width, but the overflow UB rules can still allow this to fold. // If the destination type is narrow, that means the intermediate FP value Index: llvm/test/Transforms/InstCombine/sitofp.ll =================================================================== --- llvm/test/Transforms/InstCombine/sitofp.ll +++ llvm/test/Transforms/InstCombine/sitofp.ll @@ -223,9 +223,7 @@ define i25 @masked_input(i25 %A) { ; CHECK-LABEL: @masked_input( ; CHECK-NEXT: [[M:%.*]] = and i25 [[A:%.*]], 65535 -; CHECK-NEXT: [[B:%.*]] = uitofp i25 [[M]] to float -; CHECK-NEXT: [[C:%.*]] = fptoui float [[B]] to i25 -; CHECK-NEXT: ret i25 [[C]] +; CHECK-NEXT: ret i25 [[M]] ; %m = and i25 %A, 65535 %B = uitofp i25 %m to float