I’m working through a bug in my Target where inline asm doesn’t seem to be handled properly. The most minimal example that shows this is below. In summary, it seems like when operands are added to the inlineasm node, the wrong operands are picked. When casting to a smaller integer type (truncating, etc), and passing that as an operand to an inline asm call, the original variable is used, not the truncated one.
Llvm function:
define void @inline_asm_trunc(i32 %x) {
%y = trunc i32 %x to i8
call void asm sideeffect "drvl $0", "r"(i8 %y)
ret void
}
The very first generated DAG ends up being the following:
Initial selection DAG: %bb.0 'inline_asm_trunc:'
SelectionDAG has 12 nodes:
t0: ch = EntryToken
t2: i32,ch = CopyFromReg t0, Register:i32 %0
t3: i8 = truncate t2
t8: ch,glue = CopyToReg t0, Register:i32 %1, t2
t10: ch,glue = inlineasm t8, TargetExternalSymbol:i32'drvl $0', MDNode:ch<null>, TargetConstant:i32<1>, TargetConstant:i32<65545>, Register:i32 %1, t8:1
t11: ch = P2RET t10
t3 is skipped over, despite that being the expected node to use as an operand in the inlineasm node. Is this expected behavior and there’s something I’m missing about how inlineasm works, and I need to add extra flags or code to handle it or something? Or is this a bug in creating inlineasm nodes?
I don’t have any custom inline asm code (other than supporting the ‘r’ constraint), just relying on the library code to do it all. Also, my target doesn’t have any special support for i8 or i16 types, registers are all 32 bits wide, so not sure if always using a 32 bit register class is causing it to choose the non-truncated value.