Index: llvm/lib/Target/SystemZ/SystemZInstrFormats.td =================================================================== --- llvm/lib/Target/SystemZ/SystemZInstrFormats.td +++ llvm/lib/Target/SystemZ/SystemZInstrFormats.td @@ -3200,6 +3200,8 @@ let Constraints = "$R1 = $R1src"; let DisableEncoding = "$R1src"; let CCMaskLast = 1; + let NumOpsKey = !subst("loc", "sel", mnemonic); + let NumOpsValue = "2"; } // Like CondBinaryRRF, but used for the raw assembly form. The condition-code @@ -3239,6 +3241,8 @@ [(set cls1:$R1, (z_select_ccmask cls2:$R2, cls3:$R3, cond4:$valid, cond4:$M4))]> { let CCMaskLast = 1; + let NumOpsKey = mnemonic; + let NumOpsValue = "3"; } // Like CondBinaryRRFa, but used for the raw assembly form. The condition-code @@ -4789,7 +4793,8 @@ // Like CondBinaryRRF, but expanded after RA depending on the choice of // register. -class CondBinaryRRFPseudo +class CondBinaryRRFPseudo : Pseudo<(outs cls1:$R1), (ins cls1:$R1src, cls2:$R2, cond4:$valid, cond4:$M3), [(set cls1:$R1, (z_select_ccmask cls2:$R2, cls1:$R1src, @@ -4797,17 +4802,21 @@ let Constraints = "$R1 = $R1src"; let DisableEncoding = "$R1src"; let CCMaskLast = 1; + let NumOpsKey = !subst("loc", "sel", mnemonic); + let NumOpsValue = "2"; } // Like CondBinaryRRFa, but expanded after RA depending on the choice of // register. -class CondBinaryRRFaPseudo +class CondBinaryRRFaPseudo : Pseudo<(outs cls1:$R1), (ins cls3:$R3, cls2:$R2, cond4:$valid, cond4:$M4), [(set cls1:$R1, (z_select_ccmask cls2:$R2, cls3:$R3, cond4:$valid, cond4:$M4))]> { let CCMaskLast = 1; + let NumOpsKey = mnemonic; + let NumOpsValue = "3"; } // Like CondBinaryRIE, but expanded after RA depending on the choice of Index: llvm/lib/Target/SystemZ/SystemZInstrInfo.td =================================================================== --- llvm/lib/Target/SystemZ/SystemZInstrInfo.td +++ llvm/lib/Target/SystemZ/SystemZInstrInfo.td @@ -492,7 +492,7 @@ let isCommutable = 1 in { // Expands to SELR or SELFHR or a branch-and-move sequence, // depending on the choice of registers. - def SELRMux : CondBinaryRRFaPseudo; + def SELRMux : CondBinaryRRFaPseudo<"selrmux", GRX32, GRX32, GRX32>; defm SELFHR : CondBinaryRRFaPair<"selfhr", 0xB9C0, GRH32, GRH32, GRH32>; defm SELR : CondBinaryRRFaPair<"selr", 0xB9F0, GR32, GR32, GR32>; defm SELGR : CondBinaryRRFaPair<"selgr", 0xB9E3, GR64, GR64, GR64>; @@ -525,7 +525,7 @@ let isCommutable = 1 in { // Expands to LOCR or LOCFHR or a branch-and-move sequence, // depending on the choice of registers. - def LOCRMux : CondBinaryRRFPseudo; + def LOCRMux : CondBinaryRRFPseudo<"locrmux", GRX32, GRX32>; defm LOCFHR : CondBinaryRRFPair<"locfhr", 0xB9E0, GRH32, GRH32>; } Index: llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp =================================================================== --- llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp +++ llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp @@ -87,6 +87,52 @@ bool BaseImplRetVal = TargetRegisterInfo::getRegAllocationHints( VirtReg, Order, Hints, MF, VRM, Matrix); + if (VRM != nullptr) { + // Add any two address hints after any copy hints. + SmallSet TwoAddrHints; + for (auto &Use : MRI->reg_nodbg_instructions(VirtReg)) + if (SystemZ::getTwoOperandOpcode(Use.getOpcode()) != -1) { + const MachineOperand *VRRegMO = nullptr; + const MachineOperand *OtherMO = nullptr; + const MachineOperand *CommuMO = nullptr; + if (VirtReg == Use.getOperand(0).getReg()) { + VRRegMO = &Use.getOperand(0); + OtherMO = &Use.getOperand(1); + if (Use.isCommutable()) + CommuMO = &Use.getOperand(2); + } else if (VirtReg == Use.getOperand(1).getReg()) { + VRRegMO = &Use.getOperand(1); + OtherMO = &Use.getOperand(0); + } else if (VirtReg == Use.getOperand(2).getReg() && + Use.isCommutable()) { + VRRegMO = &Use.getOperand(2); + OtherMO = &Use.getOperand(0); + } else + continue; + + auto tryAddHint = [&](const MachineOperand *MO) -> void { + Register Reg = MO->getReg(); + Register PhysReg = + Register::isPhysicalRegister(Reg) ? Reg : VRM->getPhys(Reg); + if (PhysReg) { + if (MO->getSubReg()) + PhysReg = getSubReg(PhysReg, MO->getSubReg()); + if (VRRegMO->getSubReg()) + PhysReg = getMatchingSuperReg(PhysReg, VRRegMO->getSubReg(), + MRI->getRegClass(VirtReg)); + if (!MRI->isReserved(PhysReg) && !is_contained(Hints, PhysReg)) + TwoAddrHints.insert(PhysReg); + } + }; + tryAddHint(OtherMO); + if (CommuMO) + tryAddHint(CommuMO); + } + for (MCPhysReg OrderReg : Order) + if (TwoAddrHints.count(OrderReg)) + Hints.push_back(OrderReg); + } + if (MRI->getRegClass(VirtReg) == &SystemZ::GRX32BitRegClass) { SmallVector Worklist; SmallSet DoneRegs; @@ -143,52 +189,6 @@ } } - if (VRM == nullptr) - return BaseImplRetVal; - - // Add any two address hints after any copy hints. - SmallSet TwoAddrHints; - for (auto &Use : MRI->reg_nodbg_instructions(VirtReg)) - if (SystemZ::getTwoOperandOpcode(Use.getOpcode()) != -1) { - const MachineOperand *VRRegMO = nullptr; - const MachineOperand *OtherMO = nullptr; - const MachineOperand *CommuMO = nullptr; - if (VirtReg == Use.getOperand(0).getReg()) { - VRRegMO = &Use.getOperand(0); - OtherMO = &Use.getOperand(1); - if (Use.isCommutable()) - CommuMO = &Use.getOperand(2); - } else if (VirtReg == Use.getOperand(1).getReg()) { - VRRegMO = &Use.getOperand(1); - OtherMO = &Use.getOperand(0); - } else if (VirtReg == Use.getOperand(2).getReg() && Use.isCommutable()) { - VRRegMO = &Use.getOperand(2); - OtherMO = &Use.getOperand(0); - } else - continue; - - auto tryAddHint = [&](const MachineOperand *MO) -> void { - Register Reg = MO->getReg(); - Register PhysReg = - Register::isPhysicalRegister(Reg) ? Reg : VRM->getPhys(Reg); - if (PhysReg) { - if (MO->getSubReg()) - PhysReg = getSubReg(PhysReg, MO->getSubReg()); - if (VRRegMO->getSubReg()) - PhysReg = getMatchingSuperReg(PhysReg, VRRegMO->getSubReg(), - MRI->getRegClass(VirtReg)); - if (!MRI->isReserved(PhysReg) && !is_contained(Hints, PhysReg)) - TwoAddrHints.insert(PhysReg); - } - }; - tryAddHint(OtherMO); - if (CommuMO) - tryAddHint(CommuMO); - } - for (MCPhysReg OrderReg : Order) - if (TwoAddrHints.count(OrderReg)) - Hints.push_back(OrderReg); - return BaseImplRetVal; } Index: llvm/lib/Target/SystemZ/SystemZShortenInst.cpp =================================================================== --- llvm/lib/Target/SystemZ/SystemZShortenInst.cpp +++ llvm/lib/Target/SystemZ/SystemZShortenInst.cpp @@ -46,7 +46,6 @@ bool shortenOn001(MachineInstr &MI, unsigned Opcode); bool shortenOn001AddCC(MachineInstr &MI, unsigned Opcode); bool shortenFPConv(MachineInstr &MI, unsigned Opcode); - bool shortenSelect(MachineInstr &MI, unsigned Opcode); const SystemZInstrInfo *TII; const TargetRegisterInfo *TRI; @@ -176,23 +175,6 @@ return false; } -// MI is a three-operand select instruction. If one of the sources match -// the destination, convert to the equivalent load-on-condition. -bool SystemZShortenInst::shortenSelect(MachineInstr &MI, unsigned Opcode) { - if (MI.getOperand(0).getReg() == MI.getOperand(1).getReg()) { - MI.setDesc(TII->get(Opcode)); - MI.tieOperands(0, 1); - return true; - } - if (MI.getOperand(0).getReg() == MI.getOperand(2).getReg()) { - TII->commuteInstruction(MI, false, 1, 2); - MI.setDesc(TII->get(Opcode)); - MI.tieOperands(0, 1); - return true; - } - return false; -} - // Process all instructions in MBB. Return true if something changed. bool SystemZShortenInst::processBlock(MachineBasicBlock &MBB) { bool Changed = false; @@ -213,18 +195,6 @@ Changed |= shortenIIF(MI, SystemZ::LLIHL, SystemZ::LLIHH); break; - case SystemZ::SELR: - Changed |= shortenSelect(MI, SystemZ::LOCR); - break; - - case SystemZ::SELFHR: - Changed |= shortenSelect(MI, SystemZ::LOCFHR); - break; - - case SystemZ::SELGR: - Changed |= shortenSelect(MI, SystemZ::LOCGR); - break; - case SystemZ::WFADB: Changed |= shortenOn001AddCC(MI, SystemZ::ADBR); break; Index: llvm/test/CodeGen/SystemZ/cond-move-08.mir =================================================================== --- llvm/test/CodeGen/SystemZ/cond-move-08.mir +++ llvm/test/CodeGen/SystemZ/cond-move-08.mir @@ -2,7 +2,7 @@ # RUN: | FileCheck %s # # Test that regalloc manages (via regalloc hints) to avoid a LOCRMux jump -# sequence expansion, and a SELR instuction is emitted. +# sequence expansion, and a SELR/LOCR instuction is emitted. --- | ; ModuleID = 'tc.ll' @@ -78,7 +78,7 @@ ... -# CHECK: selr +# CHECK: locr # CHECK-NOT: risblg --- Index: llvm/test/CodeGen/SystemZ/cond-move-regalloc-hints-02.mir =================================================================== --- /dev/null +++ llvm/test/CodeGen/SystemZ/cond-move-regalloc-hints-02.mir @@ -0,0 +1,54 @@ +# RUN: llc -mtriple=s390x-linux-gnu -mcpu=z15 -start-before=greedy %s -o - \ +# RUN: | FileCheck %s +# +# Test that two-address reg alloc hints are given so that a SELR becomes LOCR. + + +--- | + define i32 @fun(i32 %arg, i32 %arg1, i32 %arg2, i32* %arg3) { ret i32 0 } + declare void @foo(i32) +... +# CHECK-LABEL: fun +# CHECK: locr + +--- +name: fun +alignment: 16 +tracksRegLiveness: true +registers: + - { id: 0, class: gr32bit } + - { id: 1, class: gr32bit } + - { id: 2, class: gr32bit } + - { id: 3, class: gr32bit } + - { id: 4, class: gr64bit } + - { id: 5, class: grx32bit } + - { id: 6, class: grx32bit } + - { id: 7, class: addr64bit } + - { id: 8, class: grx32bit } + - { id: 9, class: grx32bit } + - { id: 10, class: gr64bit } + - { id: 11, class: gr32bit } +frameInfo: + maxAlignment: 1 + hasCalls: true +machineFunctionInfo: {} +body: | + bb.0: + %5:grx32bit = LHIMux 88 + %8:grx32bit = LHIMux 77 + %9:grx32bit = LHIMux 66 + + bb.1: + %6:grx32bit = LLCMux undef %7:addr64bit, 0, $noreg :: (load 1 from `i8* undef`) + CHIMux %6, 1, implicit-def $cc + %11:gr32bit = SELRMux %8, %9:grx32bit, 14, 6, implicit killed $cc + CHIMux %6, 2, implicit-def $cc + %0:gr32bit = SELRMux %11, %5, 14, 8, implicit killed $cc + ADJCALLSTACKDOWN 0, 0 + %10:gr64bit = LGFR %0 + $r2d = COPY %10 + CallBRASL @foo, killed $r2d, csr_systemz, implicit-def dead $r14d, implicit-def dead $cc, implicit $fpc + ADJCALLSTACKUP 0, 0 + J %bb.1 + +...