[PATCH] D70667: [ARM] Fix instruction selection for ARMISD::CMOV with f16 type

Victor Campos via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 25 05:35:48 PST 2019


vhscampos created this revision.
Herald added subscribers: llvm-commits, hiraditya, kristof.beyls.
Herald added a project: LLVM.

In the cases where the CMOV (f16) SDNode is used with condition codes
LT, LE, VC or NE, it is successfully selected into a VSEL instruction.

In the remaining cases, however, instruction selection fails since VSEL
does not support other condition codes.

This patch handles such cases by converting CMOV's arguments and return
values from f16 to i32 and back. This conversion is done via a simple
bitcast using ARM instructions.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D70667

Files:
  llvm/lib/Target/ARM/ARMISelLowering.cpp
  llvm/test/CodeGen/ARM/cmov_fp16.ll


Index: llvm/test/CodeGen/ARM/cmov_fp16.ll
===================================================================
--- /dev/null
+++ 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
+}
Index: llvm/lib/Target/ARM/ARMISelLowering.cpp
===================================================================
--- llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ 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<ConstantSDNode>(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);


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D70667.230882.patch
Type: text/x-patch
Size: 1964 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20191125/895fb23b/attachment.bin>


More information about the llvm-commits mailing list