Skip to content

Commit 31b7f1f

Browse files
authored
[GlobalISel] Add support for value/constants as inline asm memory operand (#161501)
InlineAsmLowering rejected inline assembly with memory reference inputs if the values passed to the inline asm weren't pointers. The DAG lowering however handled them just fine. This patch updates InlineAsmLowering to store such values on the stack, and then use the stack pointer as the "indirect" version of the operand.
1 parent 787f677 commit 31b7f1f

File tree

4 files changed

+227
-22
lines changed

4 files changed

+227
-22
lines changed

llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#include "llvm/CodeGen/GlobalISel/InlineAsmLowering.h"
1515
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
16+
#include "llvm/CodeGen/MachineFrameInfo.h"
1617
#include "llvm/CodeGen/MachineOperand.h"
1718
#include "llvm/CodeGen/MachineRegisterInfo.h"
1819
#include "llvm/CodeGen/TargetLowering.h"
@@ -454,26 +455,52 @@ bool InlineAsmLowering::lowerInlineAsm(
454455
}
455456

456457
if (OpInfo.ConstraintType == TargetLowering::C_Memory) {
457-
458-
if (!OpInfo.isIndirect) {
459-
LLVM_DEBUG(dbgs()
460-
<< "Cannot indirectify memory input operands yet\n");
461-
return false;
462-
}
463-
464-
assert(OpInfo.isIndirect && "Operand must be indirect to be a mem!");
465-
466458
const InlineAsm::ConstraintCode ConstraintID =
467459
TLI->getInlineAsmMemConstraint(OpInfo.ConstraintCode);
468460
InlineAsm::Flag OpFlags(InlineAsm::Kind::Mem, 1);
469461
OpFlags.setMemConstraint(ConstraintID);
470462
Inst.addImm(OpFlags);
463+
464+
if (OpInfo.isIndirect) {
465+
// already indirect
466+
ArrayRef<Register> SourceRegs =
467+
GetOrCreateVRegs(*OpInfo.CallOperandVal);
468+
if (SourceRegs.size() != 1) {
469+
LLVM_DEBUG(dbgs() << "Expected the memory input to fit into a "
470+
"single virtual register "
471+
"for constraint '"
472+
<< OpInfo.ConstraintCode << "'\n");
473+
return false;
474+
}
475+
Inst.addReg(SourceRegs[0]);
476+
break;
477+
}
478+
479+
// Needs to be made indirect. Store the value on the stack and use
480+
// a pointer to it.
481+
Value *OpVal = OpInfo.CallOperandVal;
482+
unsigned Bytes = DL.getTypeStoreSize(OpVal->getType());
483+
Align Alignment = DL.getPrefTypeAlign(OpVal->getType());
484+
int FrameIdx =
485+
MF.getFrameInfo().CreateStackObject(Bytes, Alignment, false);
486+
487+
unsigned AddrSpace = DL.getAllocaAddrSpace();
488+
LLT FramePtrTy =
489+
LLT::pointer(AddrSpace, DL.getPointerSizeInBits(AddrSpace));
490+
auto Ptr = MIRBuilder.buildFrameIndex(FramePtrTy, FrameIdx).getReg(0);
471491
ArrayRef<Register> SourceRegs =
472492
GetOrCreateVRegs(*OpInfo.CallOperandVal);
473-
assert(
474-
SourceRegs.size() == 1 &&
475-
"Expected the memory input to fit into a single virtual register");
476-
Inst.addReg(SourceRegs[0]);
493+
if (SourceRegs.size() != 1) {
494+
LLVM_DEBUG(dbgs() << "Expected the memory input to fit into a single "
495+
"virtual register "
496+
"for constraint '"
497+
<< OpInfo.ConstraintCode << "'\n");
498+
return false;
499+
}
500+
MIRBuilder.buildStore(SourceRegs[0], Ptr,
501+
MachinePointerInfo::getFixedStack(MF, FrameIdx),
502+
Alignment);
503+
Inst.addReg(Ptr);
477504
break;
478505
}
479506

llvm/test/CodeGen/AArch64/GlobalISel/arm64-fallback.ll

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,6 @@ define i64 @strict_align_feature(ptr %p) #0 {
3737

3838
attributes #0 = { "target-features"="+strict-align" }
3939

40-
; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to translate instruction: call
41-
; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for direct_mem
42-
; FALLBACK-WITH-REPORT-OUT-LABEL: direct_mem
43-
define void @direct_mem(i32 %x, i32 %y) {
44-
entry:
45-
tail call void asm sideeffect "", "imr,imr,~{memory}"(i32 %x, i32 %y)
46-
ret void
47-
}
48-
4940
; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to lower function{{.*}}scalable_arg
5041
; FALLBACK-WITH-REPORT-OUT-LABEL: scalable_arg
5142
define <vscale x 16 x i8> @scalable_arg(<vscale x 16 x i1> %pred, ptr %addr) #1 {

llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-inline-asm.ll

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,3 +258,96 @@ define i64 @test_input_with_matching_constraint_to_physical_register() {
258258
%1 = tail call i64 asm "", "={x2},0"(i64 0)
259259
ret i64 %1
260260
}
261+
262+
define void @test_indirectify_i32_value(i32 %x, i32 %y) {
263+
; CHECK-LABEL: name: test_indirectify_i32_value
264+
; CHECK: bb.1.entry:
265+
; CHECK-NEXT: liveins: $w0, $w1
266+
; CHECK-NEXT: {{ $}}
267+
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
268+
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $w1
269+
; CHECK-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0
270+
; CHECK-NEXT: G_STORE [[COPY]](s32), [[FRAME_INDEX]](p0) :: (store (s32) into %stack.0)
271+
; CHECK-NEXT: [[FRAME_INDEX1:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.1
272+
; CHECK-NEXT: G_STORE [[COPY1]](s32), [[FRAME_INDEX1]](p0) :: (store (s32) into %stack.1)
273+
; CHECK-NEXT: INLINEASM &"", 25 /* sideeffect mayload maystore attdialect */, {{[0-9]+}} /* mem:m */, [[FRAME_INDEX]](p0), 262158 /* mem:m */, [[FRAME_INDEX1]](p0)
274+
; CHECK-NEXT: RET_ReallyLR
275+
entry:
276+
tail call void asm sideeffect "", "imr,imr,~{memory}"(i32 %x, i32 %y)
277+
ret void
278+
}
279+
280+
define void @test_indirectify_i32_constant() {
281+
; CHECK-LABEL: name: test_indirectify_i32_constant
282+
; CHECK: bb.1.entry:
283+
; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 42
284+
; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
285+
; CHECK-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0
286+
; CHECK-NEXT: G_STORE [[C]](s32), [[FRAME_INDEX]](p0) :: (store (s32) into %stack.0)
287+
; CHECK-NEXT: [[FRAME_INDEX1:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.1
288+
; CHECK-NEXT: G_STORE [[C1]](s32), [[FRAME_INDEX1]](p0) :: (store (s32) into %stack.1)
289+
; CHECK-NEXT: INLINEASM &"", 25 /* sideeffect mayload maystore attdialect */, {{[0-9]+}} /* mem:m */, [[FRAME_INDEX]](p0), 262158 /* mem:m */, [[FRAME_INDEX1]](p0)
290+
; CHECK-NEXT: RET_ReallyLR
291+
entry:
292+
tail call void asm sideeffect "", "imr,imr,~{memory}"(i32 42, i32 0)
293+
ret void
294+
}
295+
296+
define void @test_indirectify_i16_value(i16 %val) {
297+
; CHECK-LABEL: name: test_indirectify_i16_value
298+
; CHECK: bb.1.entry:
299+
; CHECK-NEXT: liveins: $w0
300+
; CHECK-NEXT: {{ $}}
301+
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
302+
; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32)
303+
; CHECK-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0
304+
; CHECK-NEXT: G_STORE [[TRUNC]](s16), [[FRAME_INDEX]](p0) :: (store (s16) into %stack.0)
305+
; CHECK-NEXT: INLINEASM &"", 25 /* sideeffect mayload maystore attdialect */, {{[0-9]+}} /* mem:m */, [[FRAME_INDEX]](p0)
306+
; CHECK-NEXT: RET_ReallyLR
307+
entry:
308+
tail call void asm sideeffect "", "imr,~{memory}"(i16 %val)
309+
ret void
310+
}
311+
312+
define void @test_indirectify_i16_constant() {
313+
; CHECK-LABEL: name: test_indirectify_i16_constant
314+
; CHECK: bb.1.entry:
315+
; CHECK-NEXT: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 42
316+
; CHECK-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0
317+
; CHECK-NEXT: G_STORE [[C]](s16), [[FRAME_INDEX]](p0) :: (store (s16) into %stack.0)
318+
; CHECK-NEXT: INLINEASM &"", 25 /* sideeffect mayload maystore attdialect */, {{[0-9]+}} /* mem:m */, [[FRAME_INDEX]](p0)
319+
; CHECK-NEXT: RET_ReallyLR
320+
entry:
321+
tail call void asm sideeffect "", "imr,~{memory}"(i16 42)
322+
ret void
323+
}
324+
325+
define void @test_indirectify_i64_value(i64 %val) {
326+
; CHECK-LABEL: name: test_indirectify_i64_value
327+
; CHECK: bb.1.entry:
328+
; CHECK-NEXT: liveins: $x0
329+
; CHECK-NEXT: {{ $}}
330+
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
331+
; CHECK-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0
332+
; CHECK-NEXT: G_STORE [[COPY]](s64), [[FRAME_INDEX]](p0) :: (store (s64) into %stack.0)
333+
; CHECK-NEXT: INLINEASM &"", 25 /* sideeffect mayload maystore attdialect */, {{[0-9]+}} /* mem:m */, [[FRAME_INDEX]](p0)
334+
; CHECK-NEXT: RET_ReallyLR
335+
entry:
336+
tail call void asm sideeffect "", "imr,~{memory}"(i64 %val)
337+
ret void
338+
}
339+
340+
define void @test_indirectify_i64_constant() {
341+
; CHECK-LABEL: name: test_indirectify_i64_constant
342+
; CHECK: bb.1.entry:
343+
; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 42
344+
; CHECK-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0
345+
; CHECK-NEXT: G_STORE [[C]](s64), [[FRAME_INDEX]](p0) :: (store (s64) into %stack.0)
346+
; CHECK-NEXT: INLINEASM &"", 25 /* sideeffect mayload maystore attdialect */, {{[0-9]+}} /* mem:m */, [[FRAME_INDEX]](p0)
347+
; CHECK-NEXT: RET_ReallyLR
348+
entry:
349+
tail call void asm sideeffect "", "imr,~{memory}"(i64 42)
350+
ret void
351+
}
352+
353+
; TODO: add more types

llvm/test/CodeGen/AMDGPU/GlobalISel/irtranslator-inline-asm.ll

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,100 @@ define amdgpu_kernel void @asm_constraint_n_n() {
331331
ret void
332332
}
333333

334+
define void @test_indirectify_i32_value(i32 %x, i32 %y) {
335+
; CHECK-LABEL: name: test_indirectify_i32_value
336+
; CHECK: bb.1.entry:
337+
; CHECK-NEXT: liveins: $vgpr0, $vgpr1
338+
; CHECK-NEXT: {{ $}}
339+
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0
340+
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1
341+
; CHECK-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p5) = G_FRAME_INDEX %stack.0
342+
; CHECK-NEXT: G_STORE [[COPY]](s32), [[FRAME_INDEX]](p5) :: (store (s32) into %stack.0, addrspace 5)
343+
; CHECK-NEXT: [[FRAME_INDEX1:%[0-9]+]]:_(p5) = G_FRAME_INDEX %stack.1
344+
; CHECK-NEXT: G_STORE [[COPY1]](s32), [[FRAME_INDEX1]](p5) :: (store (s32) into %stack.1, addrspace 5)
345+
; CHECK-NEXT: INLINEASM &"", 25 /* sideeffect mayload maystore attdialect */, 262158 /* mem:m */, [[FRAME_INDEX]](p5), 262158 /* mem:m */, [[FRAME_INDEX1]](p5)
346+
; CHECK-NEXT: SI_RETURN
347+
entry:
348+
tail call void asm sideeffect "", "imr,imr,~{memory}"(i32 %x, i32 %y)
349+
ret void
350+
}
351+
352+
define void @test_indirectify_i32_constant() {
353+
; CHECK-LABEL: name: test_indirectify_i32_constant
354+
; CHECK: bb.1.entry:
355+
; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 42
356+
; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
357+
; CHECK-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p5) = G_FRAME_INDEX %stack.0
358+
; CHECK-NEXT: G_STORE [[C]](s32), [[FRAME_INDEX]](p5) :: (store (s32) into %stack.0, addrspace 5)
359+
; CHECK-NEXT: [[FRAME_INDEX1:%[0-9]+]]:_(p5) = G_FRAME_INDEX %stack.1
360+
; CHECK-NEXT: G_STORE [[C1]](s32), [[FRAME_INDEX1]](p5) :: (store (s32) into %stack.1, addrspace 5)
361+
; CHECK-NEXT: INLINEASM &"", 25 /* sideeffect mayload maystore attdialect */, 262158 /* mem:m */, [[FRAME_INDEX]](p5), 262158 /* mem:m */, [[FRAME_INDEX1]](p5)
362+
; CHECK-NEXT: SI_RETURN
363+
entry:
364+
tail call void asm sideeffect "", "imr,imr,~{memory}"(i32 42, i32 0)
365+
ret void
366+
}
367+
368+
369+
define void @test_indirectify_i16_value(i16 %val) {
370+
; CHECK-LABEL: name: test_indirectify_i16_value
371+
; CHECK: bb.1.entry:
372+
; CHECK-NEXT: liveins: $vgpr0
373+
; CHECK-NEXT: {{ $}}
374+
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0
375+
; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32)
376+
; CHECK-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p5) = G_FRAME_INDEX %stack.0
377+
; CHECK-NEXT: G_STORE [[TRUNC]](s16), [[FRAME_INDEX]](p5) :: (store (s16) into %stack.0, addrspace 5)
378+
; CHECK-NEXT: INLINEASM &"", 25 /* sideeffect mayload maystore attdialect */, 262158 /* mem:m */, [[FRAME_INDEX]](p5)
379+
; CHECK-NEXT: SI_RETURN
380+
entry:
381+
tail call void asm sideeffect "", "imr,~{memory}"(i16 %val)
382+
ret void
383+
}
384+
385+
define void @test_indirectify_i16_constant() {
386+
; CHECK-LABEL: name: test_indirectify_i16_constant
387+
; CHECK: bb.1.entry:
388+
; CHECK-NEXT: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 42
389+
; CHECK-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p5) = G_FRAME_INDEX %stack.0
390+
; CHECK-NEXT: G_STORE [[C]](s16), [[FRAME_INDEX]](p5) :: (store (s16) into %stack.0, addrspace 5)
391+
; CHECK-NEXT: INLINEASM &"", 25 /* sideeffect mayload maystore attdialect */, 262158 /* mem:m */, [[FRAME_INDEX]](p5)
392+
; CHECK-NEXT: SI_RETURN
393+
entry:
394+
tail call void asm sideeffect "", "imr,~{memory}"(i16 42)
395+
ret void
396+
}
397+
398+
define void @test_indirectify_i64_value(i64 %val) {
399+
; CHECK-LABEL: name: test_indirectify_i64_value
400+
; CHECK: bb.1.entry:
401+
; CHECK-NEXT: liveins: $vgpr0, $vgpr1
402+
; CHECK-NEXT: {{ $}}
403+
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0
404+
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1
405+
; CHECK-NEXT: [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY]](s32), [[COPY1]](s32)
406+
; CHECK-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p5) = G_FRAME_INDEX %stack.0
407+
; CHECK-NEXT: G_STORE [[MV]](s64), [[FRAME_INDEX]](p5) :: (store (s64) into %stack.0, addrspace 5)
408+
; CHECK-NEXT: INLINEASM &"", 25 /* sideeffect mayload maystore attdialect */, 262158 /* mem:m */, [[FRAME_INDEX]](p5)
409+
; CHECK-NEXT: SI_RETURN
410+
entry:
411+
tail call void asm sideeffect "", "imr,~{memory}"(i64 %val)
412+
ret void
413+
}
414+
415+
define void @test_indirectify_i64_constant() {
416+
; CHECK-LABEL: name: test_indirectify_i64_constant
417+
; CHECK: bb.1.entry:
418+
; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 42
419+
; CHECK-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p5) = G_FRAME_INDEX %stack.0
420+
; CHECK-NEXT: G_STORE [[C]](s64), [[FRAME_INDEX]](p5) :: (store (s64) into %stack.0, addrspace 5)
421+
; CHECK-NEXT: INLINEASM &"", 25 /* sideeffect mayload maystore attdialect */, 262158 /* mem:m */, [[FRAME_INDEX]](p5)
422+
; CHECK-NEXT: SI_RETURN
423+
entry:
424+
tail call void asm sideeffect "", "imr,~{memory}"(i64 42)
425+
ret void
426+
}
427+
334428
!llvm.module.flags = !{!1}
335429
!0 = !{i32 70}
336430
!1 = !{i32 1, !"amdhsa_code_object_version", i32 500}

0 commit comments

Comments
 (0)