Could you emit a target specific ISD opcode where the CopyToReg is created? Then you could isel that ISD opcode however you want.
That doesn't seem quite satisfactory to me, since a copy could potentially be created in many different places. Since reg copies are kept as a general COPY instruction all the way until after regalloc until the target is supposed to implement them, it seems reasonable to let the target provide a constrained regclass at some point if needed.
Adding a new TRI hook for this is one way, another one might be to view this as an isel finalization step and let the target also handle COPY instructions in FinalizeISel. It would simply be a matter then of constraining the register class.
It seems possible (but ugly) though to handle this with a backend hack, by using a target pseudo opcode that needs the constrained regclass and insert that as a user of the copyFromReg during instruction selection. That might be fine if there really is only this one single case of this problem, but that would surprise me.
To give some more context, here is one test case I am looking at:
define i32 @fun() {
%val = call i32 asm "blah", "={a0}, {a1}" (i32 0)
ret i32 %val
}
(llc -mtriple=s390x-linux-gnu -mcpu=z196 -O0)
# *** IR Dump After Finalize ISel and expand pseudo-instructions ***:
# Machine code for function fun: IsSSA, TracksLiveness
bb.0 (%ir-block.0):
%0:grx32bit = LHIMux 0
$a1 = COPY %0:grx32bit
INLINEASM &blah [attdialect], $0:[regdef], implicit-def $a0, $1:[reguse], $a1
%1:grx32bit = COPY $a0
$r2l = COPY %1:grx32bit
Return implicit $r2l
ISel here produces COPYs to/from the GRX32 registers (both low and high parts) where access registers a1/a0 are involved. This is then the problem since these COPYs can only be made with low-parts by the processor. This was the SelectionDAG:
SelectionDAG has 15 nodes:
t0: ch = EntryToken
t8: ch,glue = CopyToReg t0, Register:i32 $a1, Constant:i32<0>
t11: i32,ch,glue = CopyFromReg t15, Register:i32 $a0, t15:1
t13: ch,glue = CopyToReg t0, Register:i32 $r2l, t11
t15: ch,glue = inlineasm t8, TargetExternalSymbol:i64'blah', MDNode:ch<null>, TargetConstant:i64<0>, TargetConstant:i32<10>, Register:i32 $a0, TargetConstant:i32<9>,\
Register:i32 $a1, t8:1
t14: ch = Return Register:i32 $r2l, t13, t13:1
I can't simply select t8 here into a SAR (Set Access Register), because that would not provide the specific destination reg ($a1). So I tried replacing t8 with a target pseudo machine instruction opcode (CopyToAR) that looks identical on the DAG:
=> patched =>
SelectionDAG has 15 nodes:
t0: ch = EntryToken
t8: ch,glue = CopyToAR Register:i32 $a1, Constant:i32<0>, t0
t11: i32,ch,glue = CopyFromReg t15, Register:i32 $a0, t15:1
t13: ch,glue = CopyToReg t0, Register:i32 $r2l, t11
t15: ch,glue = inlineasm t8, TargetExternalSymbol:i64'blah', MDNode:ch<null>, TargetConstant:i64<0>, TargetConstant:i32<10>, Register:i32 $a0, TargetConstant:i32<9>,\
Register:i32 $a1, t8:1
t14: ch = Return Register:i32 $r2l, t13, t13:1
When instruction selection ends, the only difference between the DAGs is that the CopyToReg has changed opcode to the target pseudo instruction opcode CopyToAR. The idea was to then insert CopyToAR with a custom inserter. However, before that can happen InstrEmitter triggers an assert in EmitMachineNode in the "Scan the glue chain for any used physregs" clause. Here, the glue users are looped over and while a ISD::CopyToReg would simply be skipped, the target CopyToAR opcode is not. In this example, CopyToAR is glued to an inlineasm and therefore the call to F->getMachineOpcode() triggers the assert "Not a MachineInstr opcode!".
I did not yet try to do the same opcode replacement for ISD::CopyFromReg since at this point it was clear to me that these nodes have special handlings in InstrEmitter and it probably would be worrisome to have a target opcode that did *not* get the same treatment even if that would succeed.
My patch at https://reviews.llvm.org/D75014 now has two separate versions ("Diff 1" and "Diff 2") where the first one handles this in common code and the other one in the backend. Any comments and suggestions welcome!
/Jonas