This adds a fold for aggressive instcombine that converts smin(smax(fptosi(x))) into a llvm.fptosi.sat, providing that the saturation constants are correct and the cost of the llvm.fptosi.sat is lower.
Unfortunately, a llvm.fptosi.sat cannot always be converted back to a smin/smax/fptosi. The llvm.fptosi.sat intrinsic is more defined that the original, which produces poison if the original fptosi was out of range. The llvm.fptosi.sat will saturate any value, so needs to be expanded to a fptosi(fpmin(fpmax(x))), which can be worse for codegeneration depending on the target.
So this is an RFC change that is conditional on the backend reporting that the llvm.fptosi.sat is cheaper that the original smin+smax+fptost. This is a change to the way that AggressiveInstrcombine has worked in the past. Instead of just being a canonicalization pass, that canonicalization can be dependant on the target in certain specific cases. This concept can also be useful in other cases such as the table base cttz from D113291 and possibly funnel shifts? (although I know the details there less).
Hi @dmgreen, long time.
I'm updating our downstream compiler from llvm 12 to llvm 15 and this getCastInstrCost call is doing a rather strange thing, by asking the cost of a sign extend from i32 to i8, which seems awkward.
Instead of using the fixed Instruction::SExt, shouldn't it be using CastInst::getCastOpcode(IntTy, true, SatTy, true) here?
Reproducer:
Coming from a creduced code: