incorrect reg class assigned after isel

Hi,

I have a problem with a small test-case that needs to return an fp128 by storing it to memory, and would appreciate any help.

LowerReturn() builds an ISD::store, which later gets morphed to SystemZ::STX. The register class for this opcode is a sub-set of the i64 reg-class - without R0, which is not used as an address register. The reg class does not get constrained, so it remains GR64Bit, instead of ADDR64Bit, which is wrong.

I am not sure what the proper handling is:

Adding the SystemZ::ADDR64BitRegClass in TargetLowering did not seem to help.

I thought somewhere MRI->constrainRegClass() was supposed to be called at any register operand that have a too big RC (as in this case), or an extra COPY into the smaller RC should be emitted. To me, this should be done by the method that morphs the node, or at a later point during instruction emission.

/Jonas

test case:
/llc -verify-machineinstrs -mtriple=s390x-linux-gnu rc_fail.ll

*** IR Dump After Module Verifier ***
define fp128 @f14(fp128 %r3) {
   %y = fadd fp128 %r3, %r3
   ret fp128 %y
}

=== f14
Initial selection DAG: BB#0 'f14:'
SelectionDAG has 13 nodes:
   t0: ch = EntryToken
     t4: i64,ch = CopyFromReg t0, Register:i64 %vreg1
   t6: f128,ch = load<LD16[<unknown>](align=8)> t0, t4, undef:i64
   t10: i64 = Constant<0>
         t2: i64,ch = CopyFromReg t0, Register:i64 %vreg0
       t8: ch = CopyToReg t0, Register:i64 %vreg2, t2
       t9: f128 = fadd t6, t6
     t11: ch = store<ST16[<unknown>](align=8)> t8, t9, Register:i64 %vreg2, undef:i64
   t12: ch = SystemZISD::RET_FLAG t11

Optimized legalized selection DAG: BB#0 'f14:'
SelectionDAG has 12 nodes:
   t0: ch = EntryToken
     t4: i64,ch = CopyFromReg t0, Register:i64 %vreg1
   t6: f128,ch = load<LD16[<unknown>](align=8)> t0, t4, undef:i64
         t2: i64,ch = CopyFromReg t0, Register:i64 %vreg0
       t8: ch = CopyToReg t0, Register:i64 %vreg2, t2
       t9: f128 = fadd t6, t6
     t11: ch = store<ST16[<unknown>](align=8)> t8, t9, Register:i64 %vreg2, undef:i64
   t12: ch = SystemZISD::RET_FLAG t11

Morphed node: t11: ch = STX<Mem:ST16[<unknown>](align=8)> t9, Register:i64 %vreg2, TargetConstant:i64<0>, Register:i64 %noreg, t8

# After Instruction Selection
# Machine code for function f14: SSA
Function Live Ins: %R2D in %vreg0, %R3D in %vreg1

BB#0: derived from LLVM BB %0
     Live Ins: %R2D %R3D
         %vreg1<def> = COPY %R3D; ADDR64Bit:%vreg1
         %vreg0<def> = COPY %R2D; GR64Bit:%vreg0
         %vreg3<def> = LX %vreg1, 0, %noreg; mem:LD16[<unknown>](align=8) FP128Bit:%vreg3 ADDR64Bit:%vreg1
         %vreg4<def,tied1> = AXBR %vreg3<tied0>, %vreg3, %CC<imp-def,dead>; FP128Bit:%vreg4,%vreg3,%vreg3
         %vreg2<def> = COPY %vreg0; GR64Bit:%vreg2,%vreg0
         STX %vreg4<kill>, %vreg2, 0, %noreg; mem:ST16[<unknown>](align=8) FP128Bit:%vreg4 GR64Bit:%vreg2
         Return

# End machine code for function f14.

*** Bad machine code: Illegal virtual register for instruction ***
- function: f14
- basic block: BB#0 (0x43aad40)
- instruction: STX- operand 1: %vreg2
Expected a ADDR64Bit register, but got a GR64Bit register
LLVM ERROR: Found 1 machine code errors.

rc_fail.ll (78 Bytes)