Skip to content

Commit 70d9340

Browse files
committed
Treat ';' and '\n' as assembly instruction separators in
collectAsmInstrs This also fixes the incorrect treatment of '\n\t' as a separator for asm instructions.
1 parent f2e244f commit 70d9340

File tree

7 files changed

+52
-34
lines changed

7 files changed

+52
-34
lines changed

llvm/include/llvm/IR/InlineAsm.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,12 @@ class InlineAsm final : public Value {
8787

8888
StringRef getAsmString() const { return AsmString; }
8989
StringRef getConstraintString() const { return Constraints; }
90-
LLVM_ABI void collectAsmStrs(SmallVectorImpl<StringRef> &AsmStrs) const;
90+
91+
/// collectAsmInstrs - Parses the assembly instruction and collects individual
92+
/// instructions in a vector. Handles both '\n' and ';' as instruction
93+
/// separators. Trims comments (marked by '#' and "//") and whitespaces from
94+
/// instructions.
95+
LLVM_ABI SmallVector<StringRef> collectAsmInstrs() const;
9196

9297
/// This static method can be used by the parser to check to see if the
9398
/// specified constraint string is legal for the type.

llvm/lib/Analysis/InlineCost.cpp

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -793,33 +793,24 @@ class InlineCostCallAnalyzer final : public CallAnalyzer {
793793
void onInlineAsm(const InlineAsm &Arg) override {
794794
if (!InlineAsmInstrCost)
795795
return;
796-
SmallVector<StringRef, 4> AsmStrs;
797-
Arg.collectAsmStrs(AsmStrs);
798796
int SectionLevel = 0;
799797
int InlineAsmInstrCount = 0;
800-
for (StringRef AsmStr : AsmStrs) {
801-
// Trim whitespaces and comments.
802-
StringRef Trimmed = AsmStr.trim();
803-
size_t hashPos = Trimmed.find('#');
804-
if (hashPos != StringRef::npos)
805-
Trimmed = Trimmed.substr(0, hashPos);
806-
// Ignore comments.
807-
if (Trimmed.empty())
808-
continue;
798+
for (StringRef AsmInstr : Arg.collectAsmInstrs()) {
809799
// Filter out the outlined assembly instructions from the cost by keeping
810800
// track of the section level and only accounting for instrutions at
811801
// section level of zero. Note there will be duplication in outlined
812802
// sections too, but is not accounted in the inlining cost model.
813-
if (Trimmed.starts_with(".pushsection")) {
803+
if (AsmInstr.starts_with(".pushsection")) {
814804
++SectionLevel;
815805
continue;
816806
}
817-
if (Trimmed.starts_with(".popsection")) {
807+
if (AsmInstr.starts_with(".popsection")) {
818808
--SectionLevel;
819809
continue;
820810
}
821-
// Ignore directives and labels.
822-
if (Trimmed.starts_with(".") || Trimmed.contains(":"))
811+
// Labels are free. Note we only exclude labels that are not followed by
812+
// any other instruction.
813+
if (AsmInstr.ends_with(":"))
823814
continue;
824815
if (SectionLevel == 0)
825816
++InlineAsmInstrCount;

llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9989,8 +9989,7 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
99899989
}
99909990

99919991
int OpNo = -1;
9992-
SmallVector<StringRef> AsmStrs;
9993-
IA->collectAsmStrs(AsmStrs);
9992+
SmallVector<StringRef> AsmInstrs = IA->collectAsmInstrs();
99949993

99959994
// Second pass over the constraints: compute which constraint option to use.
99969995
for (SDISelAsmOperandInfo &OpInfo : ConstraintOperands) {
@@ -10034,7 +10033,7 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
1003410033
// label, so here we don't handle jmp function label now, but we need to
1003510034
// enhance it (especilly in PIC model) if we meet meaningful requirements.
1003610035
if (OpInfo.isIndirect && isFunction(OpInfo.CallOperand) &&
10037-
TLI.isInlineAsmTargetBranch(AsmStrs, OpNo) &&
10036+
TLI.isInlineAsmTargetBranch(AsmInstrs, OpNo) &&
1003810037
TM.getCodeModel() != CodeModel::Large) {
1003910038
OpInfo.isIndirect = false;
1004010039
OpInfo.ConstraintType = TargetLowering::C_Address;

llvm/lib/IR/InlineAsm.cpp

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -60,17 +60,41 @@ FunctionType *InlineAsm::getFunctionType() const {
6060
return FTy;
6161
}
6262

63-
void InlineAsm::collectAsmStrs(SmallVectorImpl<StringRef> &AsmStrs) const {
63+
SmallVector<StringRef> InlineAsm::collectAsmInstrs() const {
64+
if (AsmString.empty())
65+
return {};
6466
StringRef AsmStr(AsmString);
65-
AsmStrs.clear();
66-
67-
// TODO: 1) Unify delimiter for inline asm, we also meet other delimiters
68-
// for example "\0A", ";".
69-
// 2) Enhance StringRef. Some of the special delimiter ("\0") can't be
70-
// split in StringRef. Also empty StringRef can not call split (will stuck).
71-
if (AsmStr.empty())
72-
return;
73-
AsmStr.split(AsmStrs, "\n\t", -1, false);
67+
// First break the assembly string into lines.
68+
SmallVector<StringRef, 4> AsmLines;
69+
AsmStr.split(AsmLines, '\n', -1, false);
70+
71+
auto TrimComments = [&](StringRef &AsmLine) {
72+
for (auto CommentMarker : {"#", "//"}) {
73+
size_t MarkerPos = AsmLine.find(CommentMarker);
74+
if (MarkerPos != StringRef::npos)
75+
AsmLine = AsmLine.substr(0, MarkerPos);
76+
}
77+
};
78+
79+
SmallVector<StringRef, 4> AsmInstrs;
80+
AsmInstrs.reserve(AsmLines.size());
81+
for (StringRef &AsmLine : AsmLines) {
82+
// First remove the comments. Note it's important to do this before breaking
83+
// by ';' since the comment portion may include that character too.
84+
TrimComments(AsmLine);
85+
if (AsmLine.empty())
86+
continue;
87+
// Break by ';' to collect separate instructions in a single line.
88+
SmallVector<StringRef, 4> CurrentLineAsmInstrs;
89+
AsmLine.split(CurrentLineAsmInstrs, ';');
90+
for (StringRef S : CurrentLineAsmInstrs) {
91+
StringRef Trimmed = S.trim();
92+
if (Trimmed.empty())
93+
continue;
94+
AsmInstrs.push_back(Trimmed);
95+
}
96+
}
97+
return AsmInstrs;
7498
}
7599

76100
/// Parse - Analyze the specified string (e.g. "==&{eax}") and fill in the

llvm/test/CodeGen/X86/inline-asm-function-call-pic.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ define void @func() local_unnamed_addr #0 {
5959
entry:
6060
%call = tail call i32 @static_func()
6161
;; We test call, CALL, and jmp.
62-
tail call void asm sideeffect inteldialect "call ${0:P}\0A\09CALL ${1:P}\0A\09jmp ${1:P}\0A\09shr eax, $$0\0A\09shr ebx, $$0\0A\09shr ecx, $$0\0A\09shr edx, $$0\0A\09shr edi, $$0\0A\09shr esi, $$0\0A\09shr ebp, $$0\0A\09shr esp, $$0", "*m,*m,~{eax},~{ebp},~{ebx},~{ecx},~{edi},~{edx},~{flags},~{esi},~{esp},~{dirflag},~{fpsr},~{flags}"(ptr nonnull elementtype(i32 (...)) @static_func, ptr nonnull elementtype(i32 (...)) @extern_func) #0
62+
tail call void asm sideeffect inteldialect "call ${0:P}\0A\09CALL ${1:P}; jmp ${1:P}\0A\09shr eax, $$0\0Ashr ebx, $$0\0A\09shr ecx, $$0\0A\09shr edx, $$0; shr edi, $$0\0A\09shr esi, $$0\0A\09shr ebp, $$0\0A\09shr esp, $$0", "*m,*m,~{eax},~{ebp},~{ebx},~{ecx},~{edi},~{edx},~{flags},~{esi},~{esp},~{dirflag},~{fpsr},~{flags}"(ptr nonnull elementtype(i32 (...)) @static_func, ptr nonnull elementtype(i32 (...)) @extern_func) #0
6363
ret void
6464
}
6565

llvm/test/CodeGen/X86/inline-asm-p-constraint.ll

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,9 @@ define ptr @foo(ptr %Ptr) {
77
%Ptr.addr = alloca ptr, align 8
88
store ptr %Ptr, ptr %Ptr.addr, align 8
99
; CHECK: movq %rdi, -8(%rsp)
10-
%1 = tail call ptr asm "mov $1, $0\0A\09lea $2, $0", "=r,p,*m,~{dirflag},~{fpsr},~{flags}"(ptr %Ptr, ptr elementtype(ptr) %Ptr.addr)
10+
%1 = tail call ptr asm "mov $1, $0; lea $2, $0", "=r,p,*m,~{dirflag},~{fpsr},~{flags}"(ptr %Ptr, ptr elementtype(ptr) %Ptr.addr)
1111
; CHECK-NEXT: #APP
12-
; CHECK-NEXT: mov (%rdi), %rax
13-
; CHECK-NEXT: lea -8(%rsp), %rax
12+
; CHECK-NEXT: mov (%rdi), %rax; lea -8(%rsp), %rax
1413
; CHECK-NEXT: #NO_APP
1514
ret ptr %1
1615
; CHECK-NEXT: retq

llvm/test/Transforms/Inline/inline-call-with-asm-call.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ define void @caller(i32 %a, i1 %b) #0 {
2727
;; destination section and two assembly instructions in the outlined "other"
2828
;; section.
2929
define void @callee(i32 %a, i1 %b) {
30-
call void asm sideeffect "s_nop 1\0A\09.pushsection other\0A\09s_nop 2\0A\09s_nop 3\0A\09.popsection\0A\09s_nop 4\0A\09.align 32", ""()
30+
call void asm sideeffect "s_nop 1 # some comment ; still comment \09.pushsection other; s_nop 2 \0A s_nop 3 \0A.popsection\0A s_nop 4; label:\0A", ""()
3131
ret void
3232
}
3333
; CHECK: define void @callee

0 commit comments

Comments
 (0)