diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -4679,6 +4679,22 @@ ARMcc, CCR, duplicateCmp(Cmp, DAG)); return DAG.getNode(ARMISD::VMOVDRR, dl, MVT::f64, Low, High); + } else if (VT == MVT::f16) { + uint64_t CC = cast(ARMcc)->getZExtValue(); + // CMOV can be selected only for the following condition codes. In the + // remaining cases, values are bitcast to and from i32 to make selection + // possible. + if (CC == ARMCC::GT || CC == ARMCC::GE || CC == ARMCC::EQ || + CC == ARMCC::VS) { + return DAG.getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal, ARMcc, CCR, + Cmp); + } else { + FalseVal = DAG.getNode(ARMISD::VMOVrh, dl, MVT::i32, FalseVal); + TrueVal = DAG.getNode(ARMISD::VMOVrh, dl, MVT::i32, TrueVal); + SDValue CMOV = DAG.getNode(ARMISD::CMOV, dl, MVT::i32, FalseVal, TrueVal, + ARMcc, CCR, Cmp); + return DAG.getNode(ARMISD::VMOVhr, dl, MVT::f16, CMOV); + } } else { return DAG.getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal, ARMcc, CCR, Cmp); diff --git a/llvm/test/CodeGen/ARM/cmov_fp16.ll b/llvm/test/CodeGen/ARM/cmov_fp16.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/ARM/cmov_fp16.ll @@ -0,0 +1,13 @@ +; RUN: llc -mtriple=thumbv8.1m.main-arm-none-eabi -mattr=+fullfp16 %s -filetype=null -o - +; RUN: llc -mtriple=armv8.2a-arm-none-eabi -mattr=+fullfp16 %s -filetype=null -o - + +define i32 @foo(i32 %x, i32 %y, i32 %a, i32 %b) #0 { +entry: + %x.half = uitofp i32 %x to half + %y.half = uitofp i32 %y to half + %cmp = icmp ult i32 %a, %b + %cond = select i1 %cmp, half %x.half, half %y.half + %0 = bitcast half %cond to i16 + %1 = zext i16 %0 to i32 + ret i32 %1 +}