Skip to content

Commit 46505b3

Browse files
authored
[SelectionDAG] use HandleSDNode instead of SDValue during SelectInlineAsmMemoryOperands (#85081)
SelectInlineAsmMemoryOperands - change the vector of SDValue into a list of SDNodeHandle. Fixes issues where x86 might call replaceAllUses when matching address. Fixes #82431 - see #82431 for more information.
1 parent aa94a43 commit 46505b3

File tree

2 files changed

+80
-27
lines changed

2 files changed

+80
-27
lines changed

llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2220,24 +2220,27 @@ bool SelectionDAGISel::CheckOrMask(SDValue LHS, ConstantSDNode *RHS,
22202220
/// by tblgen. Others should not call it.
22212221
void SelectionDAGISel::SelectInlineAsmMemoryOperands(std::vector<SDValue> &Ops,
22222222
const SDLoc &DL) {
2223-
std::vector<SDValue> InOps;
2224-
std::swap(InOps, Ops);
2223+
// Change the vector of SDValue into a list of SDNodeHandle for x86 might call
2224+
// replaceAllUses when matching address.
22252225

2226-
Ops.push_back(InOps[InlineAsm::Op_InputChain]); // 0
2227-
Ops.push_back(InOps[InlineAsm::Op_AsmString]); // 1
2228-
Ops.push_back(InOps[InlineAsm::Op_MDNode]); // 2, !srcloc
2229-
Ops.push_back(InOps[InlineAsm::Op_ExtraInfo]); // 3 (SideEffect, AlignStack)
2226+
std::list<HandleSDNode> Handles;
22302227

2231-
unsigned i = InlineAsm::Op_FirstOperand, e = InOps.size();
2232-
if (InOps[e-1].getValueType() == MVT::Glue)
2228+
Handles.emplace_back(Ops[InlineAsm::Op_InputChain]); // 0
2229+
Handles.emplace_back(Ops[InlineAsm::Op_AsmString]); // 1
2230+
Handles.emplace_back(Ops[InlineAsm::Op_MDNode]); // 2, !srcloc
2231+
Handles.emplace_back(
2232+
Ops[InlineAsm::Op_ExtraInfo]); // 3 (SideEffect, AlignStack)
2233+
2234+
unsigned i = InlineAsm::Op_FirstOperand, e = Ops.size();
2235+
if (Ops[e - 1].getValueType() == MVT::Glue)
22332236
--e; // Don't process a glue operand if it is here.
22342237

22352238
while (i != e) {
2236-
InlineAsm::Flag Flags(InOps[i]->getAsZExtVal());
2239+
InlineAsm::Flag Flags(Ops[i]->getAsZExtVal());
22372240
if (!Flags.isMemKind() && !Flags.isFuncKind()) {
22382241
// Just skip over this operand, copying the operands verbatim.
2239-
Ops.insert(Ops.end(), InOps.begin() + i,
2240-
InOps.begin() + i + Flags.getNumOperandRegisters() + 1);
2242+
Handles.insert(Handles.end(), Ops.begin() + i,
2243+
Ops.begin() + i + Flags.getNumOperandRegisters() + 1);
22412244
i += Flags.getNumOperandRegisters() + 1;
22422245
} else {
22432246
assert(Flags.getNumOperandRegisters() == 1 &&
@@ -2247,18 +2250,18 @@ void SelectionDAGISel::SelectInlineAsmMemoryOperands(std::vector<SDValue> &Ops,
22472250
if (Flags.isUseOperandTiedToDef(TiedToOperand)) {
22482251
// We need the constraint ID from the operand this is tied to.
22492252
unsigned CurOp = InlineAsm::Op_FirstOperand;
2250-
Flags = InlineAsm::Flag(InOps[CurOp]->getAsZExtVal());
2253+
Flags = InlineAsm::Flag(Ops[CurOp]->getAsZExtVal());
22512254
for (; TiedToOperand; --TiedToOperand) {
22522255
CurOp += Flags.getNumOperandRegisters() + 1;
2253-
Flags = InlineAsm::Flag(InOps[CurOp]->getAsZExtVal());
2256+
Flags = InlineAsm::Flag(Ops[CurOp]->getAsZExtVal());
22542257
}
22552258
}
22562259

22572260
// Otherwise, this is a memory operand. Ask the target to select it.
22582261
std::vector<SDValue> SelOps;
22592262
const InlineAsm::ConstraintCode ConstraintID =
22602263
Flags.getMemoryConstraintID();
2261-
if (SelectInlineAsmMemoryOperand(InOps[i+1], ConstraintID, SelOps))
2264+
if (SelectInlineAsmMemoryOperand(Ops[i + 1], ConstraintID, SelOps))
22622265
report_fatal_error("Could not match memory address. Inline asm"
22632266
" failure!");
22642267

@@ -2267,15 +2270,19 @@ void SelectionDAGISel::SelectInlineAsmMemoryOperands(std::vector<SDValue> &Ops,
22672270
: InlineAsm::Kind::Func,
22682271
SelOps.size());
22692272
Flags.setMemConstraint(ConstraintID);
2270-
Ops.push_back(CurDAG->getTargetConstant(Flags, DL, MVT::i32));
2271-
llvm::append_range(Ops, SelOps);
2273+
Handles.emplace_back(CurDAG->getTargetConstant(Flags, DL, MVT::i32));
2274+
Handles.insert(Handles.end(), SelOps.begin(), SelOps.end());
22722275
i += 2;
22732276
}
22742277
}
22752278

22762279
// Add the glue input back if present.
2277-
if (e != InOps.size())
2278-
Ops.push_back(InOps.back());
2280+
if (e != Ops.size())
2281+
Handles.emplace_back(Ops.back());
2282+
2283+
Ops.clear();
2284+
for (auto &handle : Handles)
2285+
Ops.push_back(handle.getValue());
22792286
}
22802287

22812288
/// findGlueUse - Return use of MVT::Glue value produced by the specified
Lines changed: 55 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,47 @@
11
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
2-
; RUN: llc -mtriple=x86_64-unknown-linux-gnu -O0 < %s | FileCheck %s
2+
; RUN: llc -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s
33

44
; A bug in X86DAGToDAGISel::matchAddressRecursively create a zext SDValue which
55
; is quickly replaced by other SDValue but already pushed into vector for later
66
; calling for SelectionDAGISel::Select_INLINEASM getNode builder, see issue
77
; 82431 for more infomation.
88

9-
define void @PR82431(i8 %call, ptr %b) {
10-
; CHECK-LABEL: PR82431:
9+
define i64 @PR82431_0(i8 %call, ptr %b) {
10+
; CHECK-LABEL: PR82431_0:
1111
; CHECK: # %bb.0: # %entry
12-
; CHECK-NEXT: movb %dil, %al
13-
; CHECK-NEXT: addb $1, %al
14-
; CHECK-NEXT: movzbl %al, %eax
15-
; CHECK-NEXT: # kill: def $rax killed $eax
16-
; CHECK-NEXT: shlq $3, %rax
17-
; CHECK-NEXT: addq %rax, %rsi
12+
; CHECK-NEXT: movzbl %dil, %eax
13+
; CHECK-NEXT: movq 8(%rsi,%rax,8), %rax
14+
; CHECK-NEXT: retq
15+
entry:
16+
%narrow = add nuw i8 %call, 1
17+
%idxprom = zext i8 %narrow to i64
18+
%arrayidx = getelementptr [1 x i64], ptr %b, i64 0, i64 %idxprom
19+
%ret_val = load i64, ptr %arrayidx
20+
ret i64 %ret_val
21+
}
22+
23+
define i32 @PR82431_1(i32 %0, ptr %f) {
24+
; CHECK-LABEL: PR82431_1:
25+
; CHECK: # %bb.0: # %entry
26+
; CHECK-NEXT: # kill: def $edi killed $edi def $rdi
27+
; CHECK-NEXT: addl %edi, %edi
28+
; CHECK-NEXT: andl $8, %edi
29+
; CHECK-NEXT: movl 4(%rsi,%rdi), %eax
30+
; CHECK-NEXT: retq
31+
entry:
32+
%shr = lshr i32 %0, 1
33+
%and = and i32 %shr, 2
34+
%add = or i32 %and, 1
35+
%idxprom = zext i32 %add to i64
36+
%arrayidx = getelementptr [0 x i32], ptr %f, i64 0, i64 %idxprom
37+
%ret_val = load i32, ptr %arrayidx
38+
ret i32 %ret_val
39+
}
40+
41+
define void @PR82431_2(i8 %call, ptr %b) {
42+
; CHECK-LABEL: PR82431_2:
43+
; CHECK: # %bb.0: # %entry
44+
; CHECK-NEXT: movzbl %dil, %eax
1845
; CHECK-NEXT: #APP
1946
; CHECK-NEXT: #NO_APP
2047
; CHECK-NEXT: retq
@@ -25,3 +52,22 @@ entry:
2552
tail call void asm "", "=*m,*m,~{dirflag},~{fpsr},~{flags}"(ptr elementtype(i64) %arrayidx, ptr elementtype(i64) %arrayidx)
2653
ret void
2754
}
55+
56+
define void @PR82431_3(i32 %0, ptr %f) {
57+
; CHECK-LABEL: PR82431_3:
58+
; CHECK: # %bb.0: # %entry
59+
; CHECK-NEXT: # kill: def $edi killed $edi def $rdi
60+
; CHECK-NEXT: addl %edi, %edi
61+
; CHECK-NEXT: andl $8, %edi
62+
; CHECK-NEXT: #APP
63+
; CHECK-NEXT: #NO_APP
64+
; CHECK-NEXT: retq
65+
entry:
66+
%shr = lshr i32 %0, 1
67+
%and = and i32 %shr, 2
68+
%add = or i32 %and, 1
69+
%idxprom = zext i32 %add to i64
70+
%arrayidx = getelementptr [0 x i32], ptr %f, i64 0, i64 %idxprom
71+
tail call void asm "", "=*m,*m,~{dirflag},~{fpsr},~{flags}"(ptr elementtype(i32) %arrayidx, ptr elementtype(i32) %arrayidx)
72+
ret void
73+
}

0 commit comments

Comments
 (0)