<div dir="ltr"><div class="gmail_default" style="font-family:verdana,sans-serif">Hi,</div><div class="gmail_default" style="font-family:verdana,sans-serif"><br></div><div class="gmail_default"><div class="gmail_default"><font face="verdana, sans-serif">It appears that this patch crashes llvm under some circumstances. The crash goes away if the patch is reverted.</font></div><div class="gmail_default"><font face="verdana, sans-serif"><br></font></div><div class="gmail_default"><font face="verdana, sans-serif">Reproduction:</font></div><div class="gmail_default"><font face="verdana, sans-serif"><br></font></div><div class="gmail_default"><font face="verdana, sans-serif">test.cc:</font></div><div class="gmail_default"><font face="verdana, sans-serif"><br></font></div><div class="gmail_default"><font face="verdana, sans-serif">```</font></div><div class="gmail_default"><font face="verdana, sans-serif">float asmfunc(int a, int b) {</font></div><div class="gmail_default"><font face="verdana, sans-serif">  float read_value;</font></div><div class="gmail_default"><font face="verdana, sans-serif">  asm("" : "=r"(read_value), "=r"(a));</font></div><div class="gmail_default"><font face="verdana, sans-serif">  return read_value;</font></div><div class="gmail_default"><font face="verdana, sans-serif">}</font></div><div class="gmail_default"><font face="verdana, sans-serif">int B_X;</font></div><div class="gmail_default"><font face="verdana, sans-serif">void kFCNorm(int a, float b) {</font></div><div class="gmail_default"><font face="verdana, sans-serif">  B_X = asmfunc(a, B_X) * b;</font></div><div class="gmail_default"><font face="verdana, sans-serif">}</font></div><div class="gmail_default"><font face="verdana, sans-serif">```</font></div><div class="gmail_default"><font face="verdana, sans-serif"><br></font></div><div class="gmail_default"><font face="verdana, sans-serif">```</font></div><div class="gmail_default"><font face="verdana, sans-serif">$ clang -S -O3 test.cc -o - `</font></div><div class="gmail_default"><font face="verdana, sans-serif">...</font></div><div class="gmail_default"><font face="verdana, sans-serif">clang-7: <redacted>/repo/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:4489: llvm::SDValue llvm::SelectionDAG::getNode(unsigned int, const llvm::SDLoc &, llvm::EVT, llvm::SDValue, llvm::SDValue, const llvm::SDNodeFlags): Assertion `VT.isFloatingPoint() && "This operator only applies to FP types!"' failed.</font></div><div class="gmail_default"><font face="verdana, sans-serif">```</font></div></div></div><br><div class="gmail_quote"><div dir="ltr">On Wed, Jul 25, 2018 at 4:11 AM Thomas Preud'homme via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: thopre<br>
Date: Wed Jul 25 04:11:12 2018<br>
New Revision: 337903<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=337903&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=337903&view=rev</a><br>
Log:<br>
Fix PR34170: Crash on inline asm with 64bit output in 32bit GPR<br>
<br>
Add support for inline assembly with output operand that do not<br>
naturally go in the register class it is constrained to (eg. double in a<br>
32-bit GPR as in the PR).<br>
<br>
Added:<br>
    llvm/trunk/test/CodeGen/ARM/inline-asm-operand-implicit-cast.ll<br>
Modified:<br>
    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp<br>
<br>
Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp?rev=337903&r1=337902&r2=337903&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp?rev=337903&r1=337902&r2=337903&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (original)<br>
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp Wed Jul 25 04:11:12 2018<br>
@@ -7185,27 +7185,37 @@ static void GetRegistersForValue(Selecti<br>
<br>
   unsigned NumRegs = 1;<br>
   if (OpInfo.ConstraintVT != MVT::Other) {<br>
-    // If this is a FP input in an integer register (or visa versa) insert a bit<br>
-    // cast of the input value.  More generally, handle any case where the input<br>
-    // value disagrees with the register class we plan to stick this in.<br>
-    if (OpInfo.Type == InlineAsm::isInput && PhysReg.second &&<br>
+    // If this is a FP operand in an integer register (or visa versa), or more<br>
+    // generally if the operand value disagrees with the register class we plan<br>
+    // to stick it in, fix the operand type.<br>
+    //<br>
+    // If this is an input value, the bitcast to the new type is done now.<br>
+    // Bitcast for output value is done at the end of visitInlineAsm().<br>
+    if ((OpInfo.Type == InlineAsm::isOutput ||<br>
+         OpInfo.Type == InlineAsm::isInput) &&<br>
+        PhysReg.second &&<br>
         !TRI.isTypeLegalForClass(*PhysReg.second, OpInfo.ConstraintVT)) {<br>
       // Try to convert to the first EVT that the reg class contains.  If the<br>
       // types are identical size, use a bitcast to convert (e.g. two differing<br>
-      // vector types).<br>
+      // vector types).  Note: output bitcast is done at the end of<br>
+      // visitInlineAsm().<br>
       MVT RegVT = *TRI.legalclasstypes_begin(*PhysReg.second);<br>
-      if (RegVT.getSizeInBits() == OpInfo.CallOperand.getValueSizeInBits()) {<br>
-        OpInfo.CallOperand = DAG.getNode(ISD::BITCAST, DL,<br>
-                                         RegVT, OpInfo.CallOperand);<br>
+      if (RegVT.getSizeInBits() == OpInfo.ConstraintVT.getSizeInBits()) {<br>
+        // Exclude indirect inputs while they are unsupported because the code<br>
+        // to perform the load is missing and thus OpInfo.CallOperand still<br>
+        // refer to the input address rather than the pointed-to value.<br>
+        if (OpInfo.Type == InlineAsm::isInput && !OpInfo.isIndirect)<br>
+          OpInfo.CallOperand =<br>
+              DAG.getNode(ISD::BITCAST, DL, RegVT, OpInfo.CallOperand);<br>
         OpInfo.ConstraintVT = RegVT;<br>
+        // If the operand is a FP value and we want it in integer registers,<br>
+        // use the corresponding integer type. This turns an f64 value into<br>
+        // i64, which can be passed with two i32 values on a 32-bit machine.<br>
       } else if (RegVT.isInteger() && OpInfo.ConstraintVT.isFloatingPoint()) {<br>
-        // If the input is a FP value and we want it in FP registers, do a<br>
-        // bitcast to the corresponding integer type.  This turns an f64 value<br>
-        // into i64, which can be passed with two i32 values on a 32-bit<br>
-        // machine.<br>
         RegVT = MVT::getIntegerVT(OpInfo.ConstraintVT.getSizeInBits());<br>
-        OpInfo.CallOperand = DAG.getNode(ISD::BITCAST, DL,<br>
-                                         RegVT, OpInfo.CallOperand);<br>
+        if (OpInfo.Type == InlineAsm::isInput)<br>
+          OpInfo.CallOperand =<br>
+              DAG.getNode(ISD::BITCAST, DL, RegVT, OpInfo.CallOperand);<br>
         OpInfo.ConstraintVT = RegVT;<br>
       }<br>
     }<br>
@@ -7717,12 +7727,18 @@ void SelectionDAGBuilder::visitInlineAsm<br>
     if (CS.getType()->isSingleValueType() && CS.getType()->isSized()) {<br>
       EVT ResultType = TLI.getValueType(DAG.getDataLayout(), CS.getType());<br>
<br>
-      // If any of the results of the inline asm is a vector, it may have the<br>
-      // wrong width/num elts.  This can happen for register classes that can<br>
-      // contain multiple different value types.  The preg or vreg allocated may<br>
-      // not have the same VT as was expected.  Convert it to the right type<br>
-      // with bit_convert.<br>
-      if (ResultType != Val.getValueType() && Val.getValueType().isVector()) {<br>
+      // If the type of the inline asm call site return value is different but<br>
+      // has same size as the type of the asm output bitcast it.  One example<br>
+      // of this is for vectors with different width / number of elements.<br>
+      // This can happen for register classes that can contain multiple<br>
+      // different value types.  The preg or vreg allocated may not have the<br>
+      // same VT as was expected.<br>
+      //<br>
+      // This can also happen for a return value that disagrees with the<br>
+      // register class it is put in, eg. a double in a general-purpose<br>
+      // register on a 32-bit machine.<br>
+      if (ResultType != Val.getValueType() &&<br>
+          ResultType.getSizeInBits() == Val.getValueSizeInBits()) {<br>
         Val = DAG.getNode(ISD::BITCAST, getCurSDLoc(),<br>
                           ResultType, Val);<br>
<br>
<br>
Added: llvm/trunk/test/CodeGen/ARM/inline-asm-operand-implicit-cast.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/inline-asm-operand-implicit-cast.ll?rev=337903&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/inline-asm-operand-implicit-cast.ll?rev=337903&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/ARM/inline-asm-operand-implicit-cast.ll (added)<br>
+++ llvm/trunk/test/CodeGen/ARM/inline-asm-operand-implicit-cast.ll Wed Jul 25 04:11:12 2018<br>
@@ -0,0 +1,42 @@<br>
+; RUN: llc -mtriple armv7-arm-linux-gnueabihf -O2 -mcpu=cortex-a7 < %s | FileCheck %s<br>
+<br>
+; Check support for returning a float in GPR with soft float ABI<br>
+define arm_aapcscc float @zerobits_float_soft() #0 {<br>
+; CHECK-LABEL: zerobits_float_soft<br>
+; CHECK: mov r0, #0<br>
+  %1 = tail call float asm "mov ${0}, #0", "=&r"()<br>
+  ret float %1<br>
+}<br>
+<br>
+; Check support for returning a double in GPR with soft float ABI<br>
+define arm_aapcscc double @zerobits_double_soft() #0 {<br>
+; CHECK-LABEL: zerobits_double_soft<br>
+; CHECK: mov r0, #0<br>
+; CHECK-NEXT: mov r1, #0<br>
+  %1 = tail call double asm "mov ${0:Q}, #0\0Amov ${0:R}, #0", "=&r"()<br>
+  ret double %1<br>
+}<br>
+<br>
+attributes #0 = { nounwind "target-features"="+d16,+vfp2,+vfp3,-fp-only-sp" "use-soft-float"="true" }<br>
+<br>
+<br>
+; Check support for returning a float in GPR with hard float ABI<br>
+define float @zerobits_float_hard() #1 {<br>
+; CHECK-LABEL: zerobits_float_hard<br>
+; CHECK: mov r0, #0<br>
+; CHECK: vmov s0, r0<br>
+  %1 = tail call float asm "mov ${0}, #0", "=&r"()<br>
+  ret float %1<br>
+}<br>
+<br>
+; Check support for returning a double in GPR with hard float ABI<br>
+define double @zerobits_double_hard() #1 {<br>
+; CHECK-LABEL: zerobits_double_hard<br>
+; CHECK: mov r0, #0<br>
+; CHECK-NEXT: mov r1, #0<br>
+; CHECK: vmov d0, r0, r1<br>
+  %1 = tail call double asm "mov ${0:Q}, #0\0Amov ${0:R}, #0", "=&r"()<br>
+  ret double %1<br>
+}<br>
+<br>
+attributes #1 = { nounwind "target-features"="+d16,+vfp2,+vfp3,-fp-only-sp" "use-soft-float"="false" }<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br clear="all"><div><br></div>-- <br><div dir="ltr" class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr">--Artem Belevich</div></div>