[PATCH] D45376: Fix PR34170: Crash on inline asm with 64bit output in 32bit GPR
Thomas Preud'homme via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Thu Jun 21 07:50:49 PDT 2018
thopre updated this revision to Diff 152299.
thopre added a comment.
Herald added a reviewer: javed.absar.
Split the matching input handling into a separate patch.
Repository:
rL LLVM
https://reviews.llvm.org/D45376
Files:
lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
test/CodeGen/ARM/pr34170.ll
Index: test/CodeGen/ARM/pr34170.ll
===================================================================
--- /dev/null
+++ test/CodeGen/ARM/pr34170.ll
@@ -0,0 +1,13 @@
+; RUN: llc -mtriple armv7-arm-linux-gnueabihf -O2 -mcpu=cortex-a7 < %s | FileCheck %s
+
+; Check support for returning a double in GPR
+define double @zerobits_double() #0 {
+; CHECK-LABEL: zerobits_double
+; CHECK: mov r0, #0
+; CHECK-NEXT: mov r1, #0
+; CHECK: vmov d0, r0, r1
+ %1 = tail call double asm "mov ${0:Q}, #0\0Amov ${0:R}, #0", "=&r"()
+ ret double %1
+}
+
+attributes #0 = { nounwind "target-features"="+d16,+vfp2,+vfp3,-fp-only-sp" }
Index: lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
===================================================================
--- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -7142,27 +7142,37 @@
unsigned NumRegs = 1;
if (OpInfo.ConstraintVT != MVT::Other) {
- // If this is a FP input in an integer register (or visa versa) insert a bit
- // cast of the input value. More generally, handle any case where the input
- // value disagrees with the register class we plan to stick this in.
- if (OpInfo.Type == InlineAsm::isInput && PhysReg.second &&
+ // If this is a FP operand in an integer register (or visa versa), or more
+ // generally if the operand value disagrees with the register class we plan
+ // to stick it in, fix the operand type.
+ //
+ // If this is an input value, the bitcast to the new type is done now.
+ // Bitcast for output value is done at the end of visitInlineAsm().
+ if ((OpInfo.Type == InlineAsm::isOutput ||
+ OpInfo.Type == InlineAsm::isInput) &&
+ PhysReg.second &&
!TRI.isTypeLegalForClass(*PhysReg.second, OpInfo.ConstraintVT)) {
// Try to convert to the first EVT that the reg class contains. If the
// types are identical size, use a bitcast to convert (e.g. two differing
- // vector types).
+ // vector types). Note: output bitcast is done at the end of
+ // visitInlineAsm().
MVT RegVT = *TRI.legalclasstypes_begin(*PhysReg.second);
- if (RegVT.getSizeInBits() == OpInfo.CallOperand.getValueSizeInBits()) {
- OpInfo.CallOperand = DAG.getNode(ISD::BITCAST, DL,
- RegVT, OpInfo.CallOperand);
+ if (RegVT.getSizeInBits() == OpInfo.ConstraintVT.getSizeInBits()) {
+ // Exclude indirect inputs while they are unsupported because the code
+ // to perform the load is missing and thus OpInfo.CallOperand still
+ // refer to the input address rather than the pointed-to value.
+ if (OpInfo.Type == InlineAsm::isInput && !OpInfo.isIndirect)
+ OpInfo.CallOperand =
+ DAG.getNode(ISD::BITCAST, DL, RegVT, OpInfo.CallOperand);
OpInfo.ConstraintVT = RegVT;
+ // If the operand is a FP value and we want it in integer registers,
+ // use the corresponding integer type. This turns an f64 value into
+ // i64, which can be passed with two i32 values on a 32-bit machine.
} else if (RegVT.isInteger() && OpInfo.ConstraintVT.isFloatingPoint()) {
- // If the input is a FP value and we want it in FP registers, do a
- // bitcast to the corresponding integer type. This turns an f64 value
- // into i64, which can be passed with two i32 values on a 32-bit
- // machine.
RegVT = MVT::getIntegerVT(OpInfo.ConstraintVT.getSizeInBits());
- OpInfo.CallOperand = DAG.getNode(ISD::BITCAST, DL,
- RegVT, OpInfo.CallOperand);
+ if (OpInfo.Type == InlineAsm::isInput)
+ OpInfo.CallOperand =
+ DAG.getNode(ISD::BITCAST, DL, RegVT, OpInfo.CallOperand);
OpInfo.ConstraintVT = RegVT;
}
}
@@ -7674,12 +7684,18 @@
if (CS.getType()->isSingleValueType() && CS.getType()->isSized()) {
EVT ResultType = TLI.getValueType(DAG.getDataLayout(), CS.getType());
- // If any of the results of the inline asm is a vector, it may have the
- // wrong width/num elts. This can happen for register classes that can
- // contain multiple different value types. The preg or vreg allocated may
- // not have the same VT as was expected. Convert it to the right type
- // with bit_convert.
- if (ResultType != Val.getValueType() && Val.getValueType().isVector()) {
+ // If the type of the inline asm call site return value is different but
+ // has same size as the type of the asm output bitcast it. One example
+ // of this is for vectors with different width / number of elements.
+ // This can happen for register classes that can contain multiple
+ // different value types. The preg or vreg allocated may not have the
+ // same VT as was expected.
+ //
+ // This can also happen for a return value that disagrees with the
+ // register class it is put in, eg. a double in a general-purpose
+ // register on a 32-bit machine.
+ if (ResultType != Val.getValueType() &&
+ ResultType.getSizeInBits() == Val.getValueSizeInBits()) {
Val = DAG.getNode(ISD::BITCAST, getCurSDLoc(),
ResultType, Val);
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D45376.152299.patch
Type: text/x-patch
Size: 5294 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180621/b7017d15/attachment.bin>
More information about the llvm-commits
mailing list