[AMDGPU] AMDGPUAsmParser fails to parse several instructions

Dear Developers,

I compile a OpenCL kernel, FFT, in AMDAPP SDK v2.5 using clang 3.8 + libclc and assembling the code with lld (The LLVM linker). The assembly code contains the following assembly codes (and lots of other similar format assembly) that fails to be parsed by AMDGPUAsmParser. It seems to me that both are valid instructions after looking at the SI instruction spec.

s_mov_b32 s0, 0xfe5163ab

v_mad_f32 v9, 0.5, v5, -v8

To reproduce this, I write this two lines in a text file and run

llvm-mc -arch=amdgcn -mcpu=kaveri input.s

The first line has the following error message:

sop1-playground.s:1:15: error: invalid immediate: only 32-bit values are legal
s_mov_b32 s0, 0xfe5163ab
^
sop1-playground.s:1:25: error: failed parsing operand.
s_mov_b32 s0, 0xfe5163ab
^

The part of stack dump:

#9 0x4711ee (anonymous namespace)::AMDGPUOperand::setModifiers(unsigned int) /mnt/dm-0/codebase/Compilers/LLVM/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp:185:21
#10 0x46ff6a (anonymous namespace)::AMDGPUAsmParser::parseOperand(llvm::SmallVectorImpl<std::unique_ptr<llvm::MCParsedAsmOperand, std::default_deletellvm::MCParsedAsmOperand > >&, llvm::StringRef) /mnt/dm-0/codebase/Compilers/LLVM/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp:1040:16
#11 0x46cd46 (anonymous namespace)::AMDGPUAsmParser::ParseInstruction(llvm::ParseInstructionInfo&, llvm::StringRef, llvm::SMLoc, llvm::SmallVectorImpl<std::unique_ptr<llvm::MCParsedAsmOperand, std::default_deletellvm::MCParsedAsmOperand > >&) /mnt/dm-0/codebase/Compilers/LLVM/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp:1085:43

The second line of the assembly has the assertion fail:

llvm-mc: /mnt/dm-0/codebase/Compilers/LLVM/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp:184: void (anonymous namespace)::AMDGPUOperand::setModifiers(unsigned int): Assertion `isReg()’ failed.

and reports that 0.5 is “error: invalid operand for instruction”

v_mad_f32 v9, 0.5, v5, -v8

^

Regards,

李弘宇 (Li, Hong-Yu)
Department of Computer Science & Information Engineering
National Taiwan University

Dear Developers,

I found out the information included in the last mail is incorrect. Sorry for misleading stack dump information. That information is generated when AMDGPUAsmParser parsing the following assembly:

v_mad_f32 v9, 0.5, v5, -v8

llvm-mc: /mnt/dm-0/codebase/Compilers/LLVM/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp:184: void (anonymous namespace)::AMDGPUOperand::setModifiers(unsigned int): Assertion `isReg()’ failed.
#0 0x6608ee llvm::sys::PrintStackTrace(llvm::raw_ostream&) /mnt/dm-0/codebase/Compilers/LLVM/llvm/lib/Support/Unix/Signals.inc:404:15
#1 0x661a29 PrintStackTraceSignalHandler(void*) /mnt/dm-0/codebase/Compilers/LLVM/llvm/lib/Support/Unix/Signals.inc:463:1
#2 0x660463 llvm::sys::RunSignalHandlers() /mnt/dm-0/codebase/Compilers/LLVM/llvm/lib/Support/Signals.cpp:35:5
#3 0x661c84 SignalHandler(int) /mnt/dm-0/codebase/Compilers/LLVM/llvm/lib/Support/Unix/Signals.inc:211:1
#4 0x7fb282371d60 __restore_rt (/usr/lib/libpthread.so.0+0x10d60)
#5 0x7fb2815445f8 __GI_raise (/usr/lib/libc.so.6+0x335f8)
#6 0x7fb281545a7a __GI_abort (/usr/lib/libc.so.6+0x34a7a)
#7 0x7fb28153d417 __assert_fail_base (/usr/lib/libc.so.6+0x2c417)
#8 0x7fb28153d4c2 (/usr/lib/libc.so.6+0x2c4c2)
#9 0x4711ee (anonymous namespace)::AMDGPUOperand::setModifiers(unsigned int) /mnt/dm-0/codebase/Compilers/LLVM/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp:185:21
#10 0x46ff6a (anonymous namespace)::AMDGPUAsmParser::parseOperand(llvm::SmallVectorImpl<std::unique_ptr<llvm::MCParsedAsmOperand, std::default_deletellvm::MCParsedAsmOperand > >&, llvm::StringRef) /mnt/dm-0/codebase/Compilers/LLVM/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp:1040:16
#11 0x46cd46 (anonymous namespace)::AMDGPUAsmParser::ParseInstruction(llvm::ParseInstructionInfo&, llvm::StringRef, llvm::SMLoc, llvm::SmallVectorImpl<std::unique_ptr<llvm::MCParsedAsmOperand, std::default_deletellvm::MCParsedAsmOperand > >&) /mnt/dm-0/codebase/Compilers/LLVM/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp:1085:43
#12 0x5ae9a7 (anonymous namespace)::AsmParser::parseStatement((anonymous namespace)::ParseStatementInfo&, llvm::MCAsmParserSemaCallback*) /mnt/dm-0/codebase/Compilers/LLVM/llvm/lib/MC/MCParser/AsmParser.cpp:1620:8
#13 0x5a4d76 (anonymous namespace)::AsmParser::Run(bool, bool) /mnt/dm-0/codebase/Compilers/LLVM/llvm/lib/MC/MCParser/AsmParser.cpp:654:9
#14 0x41274c AssembleInput(char const*, llvm::Target const*, llvm::SourceMgr&, llvm::MCContext&, llvm::MCStreamer&, llvm::MCAsmInfo&, llvm::MCSubtargetInfo&, llvm::MCInstrInfo&, llvm::MCTargetOptions&) /mnt/dm-0/codebase/Compilers/LLVM/llvm/tools/llvm-mc/llvm-mc.cpp:363:13
#15 0x41165a main /mnt/dm-0/codebase/Compilers/LLVM/llvm/tools/llvm-mc/llvm-mc.cpp:527:9
#16 0x7fb281531610 __libc_start_main (/usr/lib/libc.so.6+0x20610)
#17 0x410009 _start (/usr/local/bin/llvm-mc+0x410009)
Stack dump:
0. Program arguments: llvm-mc -arch=amdgcn -mcpu=SI sop1-playground.s
zsh: abort (core dumped) llvm-mc -arch=amdgcn -mcpu=SI sop1-playground.s

When the assembly code is s_mov_b32 s0, 0xfe5163ab, the error message is the following (and the program terminates without the assertion failed)

sop1-playground.s:1:15: error: invalid immediate: only 32-bit values are legal

s_mov_b32 s0, 0xfe5163ab
^
sop1-playground.s:1:25: error: failed parsing operand.
s_mov_b32 s0, 0xfe5163ab

^

Regards,

李弘宇 (Li, Hong-Yu)
Department of Computer Science & Information Engineering
National Taiwan University

The first line has the following error message:

sop1-playground.s:1:15: error: invalid immediate: only 32-bit values are legal
s_mov_b32 s0, 0xfe5163ab

I’ve fixed this problem in r251132.

The second line of the assembly has the assertion fail:

llvm-mc: /mnt/dm-0/codebase/Compilers/LLVM/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp:184: void (anonymous namespace)::AMDGPUOperand::setModifiers(unsigned int): Assertion `isReg()' failed.

and reports that 0.5 is "error: invalid operand for instruction"

v_mad_f32 v9, 0.5, v5, -v8

There is a bug with operand parsing when you have immediate operands and source modifiers. I haven’t fixed this yet, but you can work around it for now by not using the source modifier.

-Matt

Thanks you. I’m new to LLVM backend, so the help is much appreciated.

I have no idea what to do the work-around. To me the modifier is set when the register has absolute or negate.

Yes, this is what the modifiers are.

I traced the code and thought that the problem occurs in the for loop to empty the modifiers for each source (in the AMDGPUAsmParser::parseOperand around line 1040). If I add an if statement like

if(RegOp.isInlineImm()) // because 0.5 is this case
contiune;

before the statement to empty the modifier (RegOp.setModifiers(0);),

it obvious does not work and cause the other matching fails. Does it mean to modify other files in other places, such as the VOP3Inst in the SIInstrInfo.td, or is this nothing to do with the MatchOperandParserImpl method or the other tablegen’d files.

I’ll be grateful for any idea you might give me to work around this.

Regards,

The workaround is to either move the 0.5 into a register and use or to apply the negate to the other operand first, e.g.:

v_mov_b32 v0, 0.5
v_mad_f32 v9, v0, v5, -v8

which will have a smaller encoding than the alternative of doing the fneg first.

The crash is easy enough to fix by checking isReg() before the setModifiers, but then the instruction is incorrectly rejected. I’m not really sure what’s going on with that right now, but I’m guessing it has to do with the way the modifiers are part of the same parsed operand, but separate in the MCInst’s operands and the missing modifier operand isn’t being added for immediates. I’m not really sure the right way to fix this.

-Matt

It seems it’s being rejected here in AMDGPUGenAsmMatcher.inc

// ‘RegWithInputMods’ class
if (Kind == MCK_RegWithInputMods) {
if (Operand.isRegWithInputMods())
return MCTargetAsmParser::Match_Success;
}

Operand is actually an immediate. I would expect this to be reaching

// ‘VCSrc32’ class
if (Kind == MCK_VCSrc32) {
if (Operand.isVCSrc32())
return MCTargetAsmParser::Match_Success;
}

and passing here, but for some reason it isn’t.

Here’s a hacky patch which fixes it

0001-XXX-AMDGPU-Hack-to-fix-source-modifiers-with-immedia.patch (3.09 KB)