[X86] Lower bf16->f32/f64 fpext without a GPR round-trip (#218359)
`fpext bfloat to float/double` currently lowers `ISD::BF16_TO_FP` via the
generic target-independent expansion (extend to i32, shl 16, bitcast to
f32), which always forces the value out of its XMM register into a GPR
and back.
Fixes #155270
Add a custom `BF16_TO_FP` lowering (mirroring the existing `FP_TO_BF16`
function) for f32/f64 results that does
the shift in-register instead.
Only on targets with SSE2 or higher otherwise still falls back to the
existing generic expansion.
The updated lowering then for the example
```llvm
define float @src32(bfloat %a0) {
%res = fpext bfloat %a0 to float
ret float %res
}
define double @src64(bfloat %a0) {
%res = fpext bfloat %a0 to double
ret double %res
}
```
generates
```asm
src32:
pslld $16, %xmm0
retq
src64:
pslld $16, %xmm0
cvtss2sd %xmm0, %xmm0
retq
```
instead of the previous roundtrip
```asm
src32:
pextrw $0, %xmm0, %eax
shll $16, %eax
movd %eax, %xmm0
retq
src64:
pextrw $0, %xmm0, %eax
shll $16, %eax
movd %eax, %xmm0
cvtss2sd %xmm0, %xmm0
retq
```
AI used for generating and cleaning up comments and reviewing the code.