Skip to content

Commit

Permalink
[ARM] Skip inline asm memory operands in DAGToDAGISel
Browse files Browse the repository at this point in the history
Retry r275776 (no changes, we suspect the issue was with another commit).

The current logic for handling inline asm operands in DAGToDAGISel interprets
the operands by looking for constants, which should represent the flags
describing the kind of operand we're dealing with (immediate, memory, register
def etc). The operands representing actual data are skipped only if they are
non-const, with the exception of immediate operands which are skipped explicitly
when a flag describing an immediate is found.

The oversight is that memory operands may be const too (e.g. for device drivers
reading a fixed address), so we should explicitly skip the operand following a
flag describing a memory operand. If we don't, we risk interpreting that
constant as a flag, which is definitely not intended.

Fixes PR26038

Differential Revision: https://reviews.llvm.org/D22103

llvm-svn: 276101
rovka committed Jul 20, 2016
1 parent 10f8472 commit f345d40
Showing 2 changed files with 22 additions and 0 deletions.
11 changes: 11 additions & 0 deletions llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp
Original file line number Diff line number Diff line change
@@ -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;
11 changes: 11 additions & 0 deletions llvm/test/CodeGen/ARM/inlineasm3.ll
Original file line number Diff line number Diff line change
@@ -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
}

0 comments on commit f345d40

Please sign in to comment.