Index: llvm/lib/CodeGen/TwoAddressInstructionPass.cpp =================================================================== --- llvm/lib/CodeGen/TwoAddressInstructionPass.cpp +++ llvm/lib/CodeGen/TwoAddressInstructionPass.cpp @@ -1408,6 +1408,7 @@ // Return true if any tied operands where found, including the trivial ones. bool TwoAddressInstructionPass:: collectTiedOperands(MachineInstr *MI, TiedOperandMap &TiedOperands) { + const MCInstrDesc &MCID = MI->getDesc(); bool AnyOps = false; unsigned NumOps = MI->getNumOperands(); @@ -1428,9 +1429,16 @@ // Deal with undef uses immediately - simply rewrite the src operand. if (SrcMO.isUndef() && !DstMO.getSubReg()) { - // Constrain the DstReg register class if required. + // Constrain the DstReg register class if required. We need the + // tied register to satisify the constraints of both source and dest. + // For some target independent opcodes, we don't have a regclass in + // the MCID, and have to use the actual regclass of the source. + // This may be much more restrictive than actually required. if (DstReg.isVirtual()) { - const TargetRegisterClass *RC = MRI->getRegClass(SrcReg); + const TargetRegisterClass *RC = TII->getRegClass(MCID, SrcIdx, + TRI, *MF); + if (!RC) + RC = MRI->getRegClass(SrcReg); MRI->constrainRegClass(DstReg, RC); } SrcMO.setReg(DstReg); Index: llvm/test/CodeGen/RISCV/twoaddress-undef-regclass-constraint.mir =================================================================== --- /dev/null +++ llvm/test/CodeGen/RISCV/twoaddress-undef-regclass-constraint.mir @@ -0,0 +1,108 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -mtriple=riscv32 -mattr=+d,+zfh,+zvfh,+v,+m -target-abi=ilp32d -run-pass twoaddressinstruction -run-pass machineverifier %s -o - | FileCheck %s + +--- | + source_filename = "" + target datalayout = "e-m:e-p:32:32-i64:64-n32-S128" + target triple = "riscv32" + + define <2 x i64> @vp_bitreverse_v2i64() #0 { + ret <2 x i64> zeroinitializer + } + + attributes #0 = { "target-features"="+d,+zfh,+zvfh,+v,+m" } + +... +--- +name: vp_bitreverse_v2i64 +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +failedISel: false +tracksRegLiveness: true +hasWinCFI: false +callsEHReturn: false +callsUnwindInit: false +hasEHCatchret: false +hasEHScopes: false +hasEHFunclets: false +isOutlined: false +debugInstrRef: false +failsVerification: false +tracksDebugUserValues: false +registers: + - { id: 0, class: vr, preferred-register: '' } + - { id: 1, class: vr, preferred-register: '' } + - { id: 2, class: gprnox0, preferred-register: '' } + - { id: 5, class: vrnov0, preferred-register: '' } + - { id: 17, class: vr, preferred-register: '' } + - { id: 18, class: vr, preferred-register: '' } + - { id: 19, class: vr, preferred-register: '' } + - { id: 20, class: vr, preferred-register: '' } + - { id: 21, class: vr, preferred-register: '' } + - { id: 22, class: vr, preferred-register: '' } + - { id: 23, class: vr, preferred-register: '' } + - { id: 24, class: gpr, preferred-register: '' } + - { id: 25, class: vrnov0, preferred-register: '' } +liveins: + - { reg: '$v8', virtual-reg: '%0' } + - { reg: '$v0', virtual-reg: '%1' } + - { reg: '$x10', virtual-reg: '%2' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 1 + adjustsStack: false + hasCalls: false + stackProtector: '' + functionContext: '' + maxCallFrameSize: 4294967295 + cvBytesOfCalleeSavedRegisters: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + hasTailCall: false + localFrameSize: 0 + savePoint: '' + restorePoint: '' +fixedStack: [] +stack: [] +entry_values: [] +callSites: [] +debugValueSubstitutions: [] +constants: [] +machineFunctionInfo: + varArgsFrameIndex: 0 + varArgsSaveSize: 0 +body: | + bb.0 (%ir-block.0): + liveins: $v8, $v0, $x10 + + + ; CHECK-LABEL: name: vp_bitreverse_v2i64 + ; CHECK: liveins: $v8, $v0, $x10 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: dead $x0 = PseudoVSETIVLI 4, 208 /* e32, m1, ta, ma */, implicit-def $vl, implicit-def $vtype + ; CHECK-NEXT: [[PseudoVMV_V_I_M1_:%[0-9]+]]:vr = PseudoVMV_V_I_M1 undef [[PseudoVMV_V_I_M1_]], 0, 4, 5 /* e32 */, 0 /* tu, mu */, implicit $vl, implicit $vtype + ; CHECK-NEXT: [[PseudoVMV_V_I_MF8_:%[0-9]+]]:vr = PseudoVMV_V_I_MF8 undef [[PseudoVMV_V_I_MF8_]], 5, 1, 3 /* e8 */, 0 /* tu, mu */, implicit $vl, implicit $vtype + ; CHECK-NEXT: [[LUI:%[0-9]+]]:gpr = LUI 1044480 + ; CHECK-NEXT: $v0 = COPY killed [[PseudoVMV_V_I_MF8_]] + ; CHECK-NEXT: [[PseudoVMERGE_VXM_M1_:%[0-9]+]]:vrnov0 = PseudoVMERGE_VXM_M1 undef [[PseudoVMERGE_VXM_M1_]], killed [[PseudoVMV_V_I_M1_]], killed [[LUI]], killed $v0, 4, 5 /* e32 */, implicit $vl, implicit $vtype + ; CHECK-NEXT: $v8 = COPY killed [[PseudoVMERGE_VXM_M1_]] + ; CHECK-NEXT: PseudoRET implicit killed $v8 + dead $x0 = PseudoVSETIVLI 4, 208 /* e32, m1, ta, ma */, implicit-def $vl, implicit-def $vtype + %17:vr = PseudoVMV_V_I_M1 undef %5:vrnov0, 0, 4, 5 /* e32 */, 0 /* tu, mu */, implicit $vl, implicit $vtype + %19:vr = PseudoVMV_V_I_MF8 undef %5:vrnov0, 5, 1, 3 /* e8 */, 0 /* tu, mu */, implicit $vl, implicit $vtype + %24:gpr = LUI 1044480 + $v0 = COPY killed %19 + %25:vrnov0 = PseudoVMERGE_VXM_M1 undef %5:vrnov0, killed %17, killed %24, killed $v0, 4, 5 /* e32 */, implicit $vl, implicit $vtype + $v8 = COPY killed %25 + PseudoRET implicit killed $v8 + +...