See the example below where fptrunc & fabs are swapped. The issue is that fabs has the nninf tag, which becomes poison because its input is inf. Two solutions come to mind: drop nninf from fabs in the solution, or add fast-math flags to fptrunc. define half @test_shrink_intrin_fabs_fast_double_src(float %D) { %E = fabs fast float %D %F = fptrunc float %E to half ret half %F } => define half @test_shrink_intrin_fabs_fast_double_src(float %D) { %1 = fptrunc float %D to half %F = fabs fast half %1 ret half %F } Transformation doesn't verify! ERROR: Target is more poisonous than source Example: float %D = #x477ff080 (65520.5) Source: float %E = #x477ff080 (65520.5) half %F = #x7c00 (+oo) Target: half %1 = #x7c00 (+oo) half %F = poison Source value: #x7c00 (+oo) Target value: poison File: llvm/test/Transforms/InstCombine/double-float-shrink-2.ll A similar test also fails in Transforms/InstCombine/fpcast.ll (test4-fast)
The general direction is to allow FMF on any FP value, and we've seen real examples where it would make sense on FP casts. So adding FMF to fptrunc/fpext is probably what we need to do first...