diff options
-rw-r--r-- | llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp | 11 | ||||
-rw-r--r-- | llvm/test/CodeGen/ARM/inlineasm3.ll | 11 |
2 files changed, 22 insertions, 0 deletions
diff --git a/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp b/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp index c5e1d976bbb..20db3d39bca 100644 --- a/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp +++ b/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp @@ -4264,6 +4264,17 @@ bool ARMDAGToDAGISel::tryInlineAsm(SDNode *N){ if (Changed && InlineAsm::isUseOperandTiedToDef(Flag, DefIdx)) IsTiedToChangedOp = OpChanged[DefIdx]; + // Memory operands to inline asm in the SelectionDAG are modeled with two + // operands: a constant of value InlineAsm::Kind_Mem followed by the input + // operand. If we get here and we have a Kind_Mem, skip the next operand (so + // it doesn't get misinterpreted), and continue. We do this here because + // it's important to update the OpChanged array correctly before moving on. + if (Kind == InlineAsm::Kind_Mem) { + SDValue op = N->getOperand(++i); + AsmNodeOperands.push_back(op); + continue; + } + if (Kind != InlineAsm::Kind_RegUse && Kind != InlineAsm::Kind_RegDef && Kind != InlineAsm::Kind_RegDefEarlyClobber) continue; diff --git a/llvm/test/CodeGen/ARM/inlineasm3.ll b/llvm/test/CodeGen/ARM/inlineasm3.ll index eb7ba59b69b..59706c4e418 100644 --- a/llvm/test/CodeGen/ARM/inlineasm3.ll +++ b/llvm/test/CodeGen/ARM/inlineasm3.ll @@ -121,3 +121,14 @@ entry: %0 = tail call <4 x i32> asm "vld1.s32 {${0:e}[], ${0:f}[]}, [$1]", "=w,r"(i32* %p) nounwind ret <4 x i32> %0 } + +; Bugzilla PR26038 + +define i32 @fn1() local_unnamed_addr nounwind { +; CHECK-LABEL: fn1 +entry: +; CHECK: mov [[addr:r[0-9]+]], #5 +; CHECK: ldrh {{.*}}[[addr]] + %0 = tail call i32 asm "ldrh $0, $1", "=r,*Q"(i8* inttoptr (i32 5 to i8*)) nounwind + ret i32 %0 +} |