diff options
Diffstat (limited to 'llvm/lib/Target/SystemZ/SystemZISelLowering.cpp')
| -rw-r--r-- | llvm/lib/Target/SystemZ/SystemZISelLowering.cpp | 340 |
1 files changed, 227 insertions, 113 deletions
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp index 603446755aaf..d70d48638b14 100644 --- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -285,10 +285,13 @@ SystemZTargetLowering::SystemZTargetLowering(const TargetMachine &TM, // Give LowerOperation the chance to replace 64-bit ORs with subregs. setOperationAction(ISD::OR, MVT::i64, Custom); - // FIXME: Can we support these natively? + // Expand 128 bit shifts without using a libcall. setOperationAction(ISD::SRL_PARTS, MVT::i64, Expand); setOperationAction(ISD::SHL_PARTS, MVT::i64, Expand); setOperationAction(ISD::SRA_PARTS, MVT::i64, Expand); + setLibcallName(RTLIB::SRL_I128, nullptr); + setLibcallName(RTLIB::SHL_I128, nullptr); + setLibcallName(RTLIB::SRA_I128, nullptr); // We have native instructions for i8, i16 and i32 extensions, but not i1. setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); @@ -850,7 +853,7 @@ bool SystemZTargetLowering::isLegalAddImmediate(int64_t Imm) const { } bool SystemZTargetLowering::allowsMisalignedMemoryAccesses( - EVT VT, unsigned, unsigned, MachineMemOperand::Flags, bool *Fast) const { + EVT VT, unsigned, Align, MachineMemOperand::Flags, bool *Fast) const { // Unaligned accesses should never be slower than the expanded version. // We check specifically for aligned accesses in the few cases where // they are required. @@ -1365,6 +1368,55 @@ static SDValue convertValVTToLocVT(SelectionDAG &DAG, const SDLoc &DL, } } +static SDValue lowerI128ToGR128(SelectionDAG &DAG, SDValue In) { + SDLoc DL(In); + SDValue Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i64, In, + DAG.getIntPtrConstant(0, DL)); + SDValue Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i64, In, + DAG.getIntPtrConstant(1, DL)); + SDNode *Pair = DAG.getMachineNode(SystemZ::PAIR128, DL, + MVT::Untyped, Hi, Lo); + return SDValue(Pair, 0); +} + +static SDValue lowerGR128ToI128(SelectionDAG &DAG, SDValue In) { + SDLoc DL(In); + SDValue Hi = DAG.getTargetExtractSubreg(SystemZ::subreg_h64, + DL, MVT::i64, In); + SDValue Lo = DAG.getTargetExtractSubreg(SystemZ::subreg_l64, + DL, MVT::i64, In); + return DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i128, Lo, Hi); +} + +bool SystemZTargetLowering::splitValueIntoRegisterParts( + SelectionDAG &DAG, const SDLoc &DL, SDValue Val, SDValue *Parts, + unsigned NumParts, MVT PartVT, Optional<CallingConv::ID> CC) const { + EVT ValueVT = Val.getValueType(); + assert((ValueVT != MVT::i128 || + ((NumParts == 1 && PartVT == MVT::Untyped) || + (NumParts == 2 && PartVT == MVT::i64))) && + "Unknown handling of i128 value."); + if (ValueVT == MVT::i128 && NumParts == 1) { + // Inline assembly operand. + Parts[0] = lowerI128ToGR128(DAG, Val); + return true; + } + return false; +} + +SDValue SystemZTargetLowering::joinRegisterPartsIntoValue( + SelectionDAG &DAG, const SDLoc &DL, const SDValue *Parts, unsigned NumParts, + MVT PartVT, EVT ValueVT, Optional<CallingConv::ID> CC) const { + assert((ValueVT != MVT::i128 || + ((NumParts == 1 && PartVT == MVT::Untyped) || + (NumParts == 2 && PartVT == MVT::i64))) && + "Unknown handling of i128 value."); + if (ValueVT == MVT::i128 && NumParts == 1) + // Inline assembly operand. + return lowerGR128ToI128(DAG, Parts[0]); + return SDValue(); +} + SDValue SystemZTargetLowering::LowerFormalArguments( SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL, @@ -1482,20 +1534,20 @@ SDValue SystemZTargetLowering::LowerFormalArguments( // ...and a similar frame index for the caller-allocated save area // that will be used to store the incoming registers. int64_t RegSaveOffset = - -SystemZMC::CallFrameSize + TFL->getRegSpillOffset(MF, SystemZ::R2D) - 16; + -SystemZMC::ELFCallFrameSize + TFL->getRegSpillOffset(MF, SystemZ::R2D) - 16; unsigned RegSaveIndex = MFI.CreateFixedObject(1, RegSaveOffset, true); FuncInfo->setRegSaveFrameIndex(RegSaveIndex); // Store the FPR varargs in the reserved frame slots. (We store the // GPRs as part of the prologue.) - if (NumFixedFPRs < SystemZ::NumArgFPRs && !useSoftFloat()) { - SDValue MemOps[SystemZ::NumArgFPRs]; - for (unsigned I = NumFixedFPRs; I < SystemZ::NumArgFPRs; ++I) { - unsigned Offset = TFL->getRegSpillOffset(MF, SystemZ::ArgFPRs[I]); + if (NumFixedFPRs < SystemZ::ELFNumArgFPRs && !useSoftFloat()) { + SDValue MemOps[SystemZ::ELFNumArgFPRs]; + for (unsigned I = NumFixedFPRs; I < SystemZ::ELFNumArgFPRs; ++I) { + unsigned Offset = TFL->getRegSpillOffset(MF, SystemZ::ELFArgFPRs[I]); int FI = - MFI.CreateFixedObject(8, -SystemZMC::CallFrameSize + Offset, true); + MFI.CreateFixedObject(8, -SystemZMC::ELFCallFrameSize + Offset, true); SDValue FIN = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); - unsigned VReg = MF.addLiveIn(SystemZ::ArgFPRs[I], + unsigned VReg = MF.addLiveIn(SystemZ::ELFArgFPRs[I], &SystemZ::FP64BitRegClass); SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, VReg, MVT::f64); MemOps[I] = DAG.getStore(ArgValue.getValue(1), DL, ArgValue, FIN, @@ -1504,7 +1556,7 @@ SDValue SystemZTargetLowering::LowerFormalArguments( // Join the stores, which are independent of one another. Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, makeArrayRef(&MemOps[NumFixedFPRs], - SystemZ::NumArgFPRs-NumFixedFPRs)); + SystemZ::ELFNumArgFPRs-NumFixedFPRs)); } } @@ -1547,6 +1599,7 @@ SystemZTargetLowering::LowerCall(CallLoweringInfo &CLI, bool IsVarArg = CLI.IsVarArg; MachineFunction &MF = DAG.getMachineFunction(); EVT PtrVT = getPointerTy(MF.getDataLayout()); + LLVMContext &Ctx = *DAG.getContext(); // Detect unsupported vector argument and return types. if (Subtarget.hasVector()) { @@ -1556,7 +1609,7 @@ SystemZTargetLowering::LowerCall(CallLoweringInfo &CLI, // Analyze the operands of the call, assigning locations to each operand. SmallVector<CCValAssign, 16> ArgLocs; - SystemZCCState ArgCCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext()); + SystemZCCState ArgCCInfo(CallConv, IsVarArg, MF, ArgLocs, Ctx); ArgCCInfo.AnalyzeCallOperands(Outs, CC_SystemZ); // We don't support GuaranteedTailCallOpt, only automatically-detected @@ -1581,14 +1634,25 @@ SystemZTargetLowering::LowerCall(CallLoweringInfo &CLI, if (VA.getLocInfo() == CCValAssign::Indirect) { // Store the argument in a stack slot and pass its address. - SDValue SpillSlot = DAG.CreateStackTemporary(Outs[I].ArgVT); + unsigned ArgIndex = Outs[I].OrigArgIndex; + EVT SlotVT; + if (I + 1 != E && Outs[I + 1].OrigArgIndex == ArgIndex) { + // Allocate the full stack space for a promoted (and split) argument. + Type *OrigArgType = CLI.Args[Outs[I].OrigArgIndex].Ty; + EVT OrigArgVT = getValueType(MF.getDataLayout(), OrigArgType); + MVT PartVT = getRegisterTypeForCallingConv(Ctx, CLI.CallConv, OrigArgVT); + unsigned N = getNumRegistersForCallingConv(Ctx, CLI.CallConv, OrigArgVT); + SlotVT = EVT::getIntegerVT(Ctx, PartVT.getSizeInBits() * N); + } else { + SlotVT = Outs[I].ArgVT; + } + SDValue SpillSlot = DAG.CreateStackTemporary(SlotVT); int FI = cast<FrameIndexSDNode>(SpillSlot)->getIndex(); MemOpChains.push_back( DAG.getStore(Chain, DL, ArgValue, SpillSlot, MachinePointerInfo::getFixedStack(MF, FI))); // If the original argument was split (e.g. i128), we need // to store all parts of it here (and pass just one address). - unsigned ArgIndex = Outs[I].OrigArgIndex; assert (Outs[I].PartOffset == 0); while (I + 1 != E && Outs[I + 1].OrigArgIndex == ArgIndex) { SDValue PartValue = OutVals[I + 1]; @@ -1598,6 +1662,8 @@ SystemZTargetLowering::LowerCall(CallLoweringInfo &CLI, MemOpChains.push_back( DAG.getStore(Chain, DL, PartValue, Address, MachinePointerInfo::getFixedStack(MF, FI))); + assert((PartOffset + PartValue.getValueType().getStoreSize() <= + SlotVT.getStoreSize()) && "Not enough space for argument part!"); ++I; } ArgValue = SpillSlot; @@ -1614,7 +1680,7 @@ SystemZTargetLowering::LowerCall(CallLoweringInfo &CLI, // floats are passed as right-justified 8-byte values. if (!StackPtr.getNode()) StackPtr = DAG.getCopyFromReg(Chain, DL, SystemZ::R15D, PtrVT); - unsigned Offset = SystemZMC::CallFrameSize + VA.getLocMemOffset(); + unsigned Offset = SystemZMC::ELFCallFrameSize + VA.getLocMemOffset(); if (VA.getLocVT() == MVT::i32 || VA.getLocVT() == MVT::f32) Offset += 4; SDValue Address = DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr, @@ -1691,7 +1757,7 @@ SystemZTargetLowering::LowerCall(CallLoweringInfo &CLI, // Assign locations to each value returned by this call. SmallVector<CCValAssign, 16> RetLocs; - CCState RetCCInfo(CallConv, IsVarArg, MF, RetLocs, *DAG.getContext()); + CCState RetCCInfo(CallConv, IsVarArg, MF, RetLocs, Ctx); RetCCInfo.AnalyzeCallResult(Ins, RetCC_SystemZ); // Copy all of the result registers out of their specified physreg. @@ -3264,12 +3330,10 @@ SDValue SystemZTargetLowering::lowerFRAMEADDR(SDValue Op, unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue(); EVT PtrVT = getPointerTy(DAG.getDataLayout()); - // Return null if the back chain is not present. - bool HasBackChain = MF.getFunction().hasFnAttribute("backchain"); - if (TFL->usePackedStack(MF) && !HasBackChain) - return DAG.getConstant(0, DL, PtrVT); - - // By definition, the frame address is the address of the back chain. + // By definition, the frame address is the address of the back chain. (In + // the case of packed stack without backchain, return the address where the + // backchain would have been stored. This will either be an unused space or + // contain a saved register). int BackChainIdx = TFL->getOrCreateFramePointerSaveIndex(MF); SDValue BackChain = DAG.getFrameIndex(BackChainIdx, PtrVT); @@ -3868,7 +3932,7 @@ SDValue SystemZTargetLowering::lowerATOMIC_STORE(SDValue Op, Node->getMemOperand()); // We have to enforce sequential consistency by performing a // serialization operation after the store. - if (Node->getOrdering() == AtomicOrdering::SequentiallyConsistent) + if (Node->getSuccessOrdering() == AtomicOrdering::SequentiallyConsistent) Chain = SDValue(DAG.getMachineNode(SystemZ::Serialize, SDLoc(Op), MVT::Other, Chain), 0); return Chain; @@ -4042,7 +4106,10 @@ SDValue SystemZTargetLowering::lowerATOMIC_CMP_SWAP(SDValue Op, SDValue Success = emitSETCC(DAG, DL, AtomicOp.getValue(1), SystemZ::CCMASK_ICMP, SystemZ::CCMASK_CMP_EQ); - DAG.ReplaceAllUsesOfValueWith(Op.getValue(0), AtomicOp.getValue(0)); + // emitAtomicCmpSwapW() will zero extend the result (original value). + SDValue OrigVal = DAG.getNode(ISD::AssertZext, DL, WideVT, AtomicOp.getValue(0), + DAG.getValueType(NarrowVT)); + DAG.ReplaceAllUsesOfValueWith(Op.getValue(0), OrigVal); DAG.ReplaceAllUsesOfValueWith(Op.getValue(1), Success); DAG.ReplaceAllUsesOfValueWith(Op.getValue(2), AtomicOp.getValue(2)); return SDValue(); @@ -5471,27 +5538,6 @@ SDValue SystemZTargetLowering::LowerOperation(SDValue Op, // Lower operations with invalid operand or result types (currently used // only for 128-bit integer types). - -static SDValue lowerI128ToGR128(SelectionDAG &DAG, SDValue In) { - SDLoc DL(In); - SDValue Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i64, In, - DAG.getIntPtrConstant(0, DL)); - SDValue Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i64, In, - DAG.getIntPtrConstant(1, DL)); - SDNode *Pair = DAG.getMachineNode(SystemZ::PAIR128, DL, - MVT::Untyped, Hi, Lo); - return SDValue(Pair, 0); -} - -static SDValue lowerGR128ToI128(SelectionDAG &DAG, SDValue In) { - SDLoc DL(In); - SDValue Hi = DAG.getTargetExtractSubreg(SystemZ::subreg_h64, - DL, MVT::i64, In); - SDValue Lo = DAG.getTargetExtractSubreg(SystemZ::subreg_l64, - DL, MVT::i64, In); - return DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i128, Lo, Hi); -} - void SystemZTargetLowering::LowerOperationWrapper(SDNode *N, SmallVectorImpl<SDValue> &Results, @@ -5519,7 +5565,7 @@ SystemZTargetLowering::LowerOperationWrapper(SDNode *N, DL, Tys, Ops, MVT::i128, MMO); // We have to enforce sequential consistency by performing a // serialization operation after the store. - if (cast<AtomicSDNode>(N)->getOrdering() == + if (cast<AtomicSDNode>(N)->getSuccessOrdering() == AtomicOrdering::SequentiallyConsistent) Res = SDValue(DAG.getMachineNode(SystemZ::Serialize, DL, MVT::Other, Res), 0); @@ -7377,7 +7423,7 @@ MachineBasicBlock *SystemZTargetLowering::emitAtomicLoadBinary( // StartMBB: // ... // %OrigVal = L Disp(%Base) - // # fall through to LoopMMB + // # fall through to LoopMBB MBB = StartMBB; BuildMI(MBB, DL, TII->get(LOpcode), OrigVal).add(Base).addImm(Disp).addReg(0); MBB->addSuccessor(LoopMBB); @@ -7389,7 +7435,7 @@ MachineBasicBlock *SystemZTargetLowering::emitAtomicLoadBinary( // %NewVal = RLL %RotatedNewVal, 0(%NegBitShift) // %Dest = CS %OldVal, %NewVal, Disp(%Base) // JNE LoopMBB - // # fall through to DoneMMB + // # fall through to DoneMBB MBB = LoopMBB; BuildMI(MBB, DL, TII->get(SystemZ::PHI), OldVal) .addReg(OrigVal).addMBB(StartMBB) @@ -7497,7 +7543,7 @@ MachineBasicBlock *SystemZTargetLowering::emitAtomicLoadMinMax( // StartMBB: // ... // %OrigVal = L Disp(%Base) - // # fall through to LoopMMB + // # fall through to LoopMBB MBB = StartMBB; BuildMI(MBB, DL, TII->get(LOpcode), OrigVal).add(Base).addImm(Disp).addReg(0); MBB->addSuccessor(LoopMBB); @@ -7523,7 +7569,7 @@ MachineBasicBlock *SystemZTargetLowering::emitAtomicLoadMinMax( // UseAltMBB: // %RotatedAltVal = RISBG %RotatedOldVal, %Src2, 32, 31 + BitSize, 0 - // # fall through to UpdateMMB + // # fall through to UpdateMBB MBB = UseAltMBB; if (IsSubWord) BuildMI(MBB, DL, TII->get(SystemZ::RISBG32), RotatedAltVal) @@ -7537,7 +7583,7 @@ MachineBasicBlock *SystemZTargetLowering::emitAtomicLoadMinMax( // %NewVal = RLL %RotatedNewVal, 0(%NegBitShift) // %Dest = CS %OldVal, %NewVal, Disp(%Base) // JNE LoopMBB - // # fall through to DoneMMB + // # fall through to DoneMBB MBB = UpdateMBB; BuildMI(MBB, DL, TII->get(SystemZ::PHI), RotatedNewVal) .addReg(RotatedOldVal).addMBB(LoopMBB) @@ -7564,7 +7610,6 @@ MachineBasicBlock *SystemZTargetLowering::emitAtomicLoadMinMax( MachineBasicBlock * SystemZTargetLowering::emitAtomicCmpSwapW(MachineInstr &MI, MachineBasicBlock *MBB) const { - MachineFunction &MF = *MBB->getParent(); const SystemZInstrInfo *TII = static_cast<const SystemZInstrInfo *>(Subtarget.getInstrInfo()); @@ -7574,7 +7619,7 @@ SystemZTargetLowering::emitAtomicCmpSwapW(MachineInstr &MI, Register Dest = MI.getOperand(0).getReg(); MachineOperand Base = earlyUseOperand(MI.getOperand(1)); int64_t Disp = MI.getOperand(2).getImm(); - Register OrigCmpVal = MI.getOperand(3).getReg(); + Register CmpVal = MI.getOperand(3).getReg(); Register OrigSwapVal = MI.getOperand(4).getReg(); Register BitShift = MI.getOperand(5).getReg(); Register NegBitShift = MI.getOperand(6).getReg(); @@ -7583,19 +7628,19 @@ SystemZTargetLowering::emitAtomicCmpSwapW(MachineInstr &MI, const TargetRegisterClass *RC = &SystemZ::GR32BitRegClass; - // Get the right opcodes for the displacement. + // Get the right opcodes for the displacement and zero-extension. unsigned LOpcode = TII->getOpcodeForOffset(SystemZ::L, Disp); unsigned CSOpcode = TII->getOpcodeForOffset(SystemZ::CS, Disp); + unsigned ZExtOpcode = BitSize == 8 ? SystemZ::LLCR : SystemZ::LLHR; assert(LOpcode && CSOpcode && "Displacement out of range"); // Create virtual registers for temporary results. Register OrigOldVal = MRI.createVirtualRegister(RC); Register OldVal = MRI.createVirtualRegister(RC); - Register CmpVal = MRI.createVirtualRegister(RC); Register SwapVal = MRI.createVirtualRegister(RC); Register StoreVal = MRI.createVirtualRegister(RC); + Register OldValRot = MRI.createVirtualRegister(RC); Register RetryOldVal = MRI.createVirtualRegister(RC); - Register RetryCmpVal = MRI.createVirtualRegister(RC); Register RetrySwapVal = MRI.createVirtualRegister(RC); // Insert 2 basic blocks for the loop. @@ -7607,7 +7652,7 @@ SystemZTargetLowering::emitAtomicCmpSwapW(MachineInstr &MI, // StartMBB: // ... // %OrigOldVal = L Disp(%Base) - // # fall through to LoopMMB + // # fall through to LoopMBB MBB = StartMBB; BuildMI(MBB, DL, TII->get(LOpcode), OrigOldVal) .add(Base) @@ -7617,34 +7662,32 @@ SystemZTargetLowering::emitAtomicCmpSwapW(MachineInstr &MI, // LoopMBB: // %OldVal = phi [ %OrigOldVal, EntryBB ], [ %RetryOldVal, SetMBB ] - // %CmpVal = phi [ %OrigCmpVal, EntryBB ], [ %RetryCmpVal, SetMBB ] // %SwapVal = phi [ %OrigSwapVal, EntryBB ], [ %RetrySwapVal, SetMBB ] - // %Dest = RLL %OldVal, BitSize(%BitShift) + // %OldValRot = RLL %OldVal, BitSize(%BitShift) // ^^ The low BitSize bits contain the field // of interest. - // %RetryCmpVal = RISBG32 %CmpVal, %Dest, 32, 63-BitSize, 0 + // %RetrySwapVal = RISBG32 %SwapVal, %OldValRot, 32, 63-BitSize, 0 // ^^ Replace the upper 32-BitSize bits of the - // comparison value with those that we loaded, - // so that we can use a full word comparison. - // CR %Dest, %RetryCmpVal + // swap value with those that we loaded and rotated. + // %Dest = LL[CH] %OldValRot + // CR %Dest, %CmpVal // JNE DoneMBB // # Fall through to SetMBB MBB = LoopMBB; BuildMI(MBB, DL, TII->get(SystemZ::PHI), OldVal) .addReg(OrigOldVal).addMBB(StartMBB) .addReg(RetryOldVal).addMBB(SetMBB); - BuildMI(MBB, DL, TII->get(SystemZ::PHI), CmpVal) - .addReg(OrigCmpVal).addMBB(StartMBB) - .addReg(RetryCmpVal).addMBB(SetMBB); BuildMI(MBB, DL, TII->get(SystemZ::PHI), SwapVal) .addReg(OrigSwapVal).addMBB(StartMBB) .addReg(RetrySwapVal).addMBB(SetMBB); - BuildMI(MBB, DL, TII->get(SystemZ::RLL), Dest) + BuildMI(MBB, DL, TII->get(SystemZ::RLL), OldValRot) .addReg(OldVal).addReg(BitShift).addImm(BitSize); - BuildMI(MBB, DL, TII->get(SystemZ::RISBG32), RetryCmpVal) - .addReg(CmpVal).addReg(Dest).addImm(32).addImm(63 - BitSize).addImm(0); + BuildMI(MBB, DL, TII->get(SystemZ::RISBG32), RetrySwapVal) + .addReg(SwapVal).addReg(OldValRot).addImm(32).addImm(63 - BitSize).addImm(0); + BuildMI(MBB, DL, TII->get(ZExtOpcode), Dest) + .addReg(OldValRot); BuildMI(MBB, DL, TII->get(SystemZ::CR)) - .addReg(Dest).addReg(RetryCmpVal); + .addReg(Dest).addReg(CmpVal); BuildMI(MBB, DL, TII->get(SystemZ::BRC)) .addImm(SystemZ::CCMASK_ICMP) .addImm(SystemZ::CCMASK_CMP_NE).addMBB(DoneMBB); @@ -7652,17 +7695,12 @@ SystemZTargetLowering::emitAtomicCmpSwapW(MachineInstr &MI, MBB->addSuccessor(SetMBB); // SetMBB: - // %RetrySwapVal = RISBG32 %SwapVal, %Dest, 32, 63-BitSize, 0 - // ^^ Replace the upper 32-BitSize bits of the new - // value with those that we loaded. - // %StoreVal = RLL %RetrySwapVal, -BitSize(%NegBitShift) + // %StoreVal = RLL %RetrySwapVal, -BitSize(%NegBitShift) // ^^ Rotate the new field to its proper position. - // %RetryOldVal = CS %Dest, %StoreVal, Disp(%Base) + // %RetryOldVal = CS %OldVal, %StoreVal, Disp(%Base) // JNE LoopMBB - // # fall through to ExitMMB + // # fall through to ExitMBB MBB = SetMBB; - BuildMI(MBB, DL, TII->get(SystemZ::RISBG32), RetrySwapVal) - .addReg(SwapVal).addReg(Dest).addImm(32).addImm(63 - BitSize).addImm(0); BuildMI(MBB, DL, TII->get(SystemZ::RLL), StoreVal) .addReg(RetrySwapVal).addReg(NegBitShift).addImm(-BitSize); BuildMI(MBB, DL, TII->get(CSOpcode), RetryOldVal) @@ -7757,43 +7795,99 @@ MachineBasicBlock *SystemZTargetLowering::emitMemMemWrapper( uint64_t DestDisp = MI.getOperand(1).getImm(); MachineOperand SrcBase = earlyUseOperand(MI.getOperand(2)); uint64_t SrcDisp = MI.getOperand(3).getImm(); - uint64_t Length = MI.getOperand(4).getImm(); + MachineOperand &LengthMO = MI.getOperand(4); + uint64_t ImmLength = LengthMO.isImm() ? LengthMO.getImm() : 0; + Register LenMinus1Reg = + LengthMO.isReg() ? LengthMO.getReg() : SystemZ::NoRegister; // When generating more than one CLC, all but the last will need to // branch to the end when a difference is found. - MachineBasicBlock *EndMBB = (Length > 256 && Opcode == SystemZ::CLC ? - SystemZ::splitBlockAfter(MI, MBB) : nullptr); + MachineBasicBlock *EndMBB = (ImmLength > 256 && Opcode == SystemZ::CLC + ? SystemZ::splitBlockAfter(MI, MBB) + : nullptr); // Check for the loop form, in which operand 5 is the trip count. if (MI.getNumExplicitOperands() > 5) { + Register StartCountReg = MI.getOperand(5).getReg(); bool HaveSingleBase = DestBase.isIdenticalTo(SrcBase); - Register StartCountReg = MI.getOperand(5).getReg(); - Register StartSrcReg = forceReg(MI, SrcBase, TII); - Register StartDestReg = (HaveSingleBase ? StartSrcReg : - forceReg(MI, DestBase, TII)); + auto loadZeroAddress = [&]() -> MachineOperand { + Register Reg = MRI.createVirtualRegister(&SystemZ::ADDR64BitRegClass); + BuildMI(*MBB, MI, DL, TII->get(SystemZ::LGHI), Reg).addImm(0); + return MachineOperand::CreateReg(Reg, false); + }; + if (DestBase.isReg() && DestBase.getReg() == SystemZ::NoRegister) + DestBase = loadZeroAddress(); + if (SrcBase.isReg() && SrcBase.getReg() == SystemZ::NoRegister) + SrcBase = HaveSingleBase ? DestBase : loadZeroAddress(); + + MachineBasicBlock *StartMBB = nullptr; + MachineBasicBlock *LoopMBB = nullptr; + MachineBasicBlock *NextMBB = nullptr; + MachineBasicBlock *DoneMBB = nullptr; + MachineBasicBlock *AllDoneMBB = nullptr; + + Register StartSrcReg = forceReg(MI, SrcBase, TII); + Register StartDestReg = + (HaveSingleBase ? StartSrcReg : forceReg(MI, DestBase, TII)); const TargetRegisterClass *RC = &SystemZ::ADDR64BitRegClass; Register ThisSrcReg = MRI.createVirtualRegister(RC); - Register ThisDestReg = (HaveSingleBase ? ThisSrcReg : - MRI.createVirtualRegister(RC)); + Register ThisDestReg = + (HaveSingleBase ? ThisSrcReg : MRI.createVirtualRegister(RC)); Register NextSrcReg = MRI.createVirtualRegister(RC); - Register NextDestReg = (HaveSingleBase ? NextSrcReg : - MRI.createVirtualRegister(RC)); - + Register NextDestReg = + (HaveSingleBase ? NextSrcReg : MRI.createVirtualRegister(RC)); RC = &SystemZ::GR64BitRegClass; Register ThisCountReg = MRI.createVirtualRegister(RC); Register NextCountReg = MRI.createVirtualRegister(RC); - MachineBasicBlock *StartMBB = MBB; - MachineBasicBlock *DoneMBB = SystemZ::splitBlockBefore(MI, MBB); - MachineBasicBlock *LoopMBB = SystemZ::emitBlockAfter(StartMBB); - MachineBasicBlock *NextMBB = - (EndMBB ? SystemZ::emitBlockAfter(LoopMBB) : LoopMBB); + if (LengthMO.isReg()) { + AllDoneMBB = SystemZ::splitBlockBefore(MI, MBB); + StartMBB = SystemZ::emitBlockAfter(MBB); + LoopMBB = SystemZ::emitBlockAfter(StartMBB); + NextMBB = LoopMBB; + DoneMBB = SystemZ::emitBlockAfter(LoopMBB); - // StartMBB: - // # fall through to LoopMMB - MBB->addSuccessor(LoopMBB); + // MBB: + // # Jump to AllDoneMBB if LenMinus1Reg is -1, or fall thru to StartMBB. + BuildMI(MBB, DL, TII->get(SystemZ::CGHI)) + .addReg(LenMinus1Reg).addImm(-1); + BuildMI(MBB, DL, TII->get(SystemZ::BRC)) + .addImm(SystemZ::CCMASK_ICMP).addImm(SystemZ::CCMASK_CMP_EQ) + .addMBB(AllDoneMBB); + MBB->addSuccessor(AllDoneMBB); + MBB->addSuccessor(StartMBB); + + // StartMBB: + // # Jump to DoneMBB if %StartCountReg is zero, or fall through to LoopMBB. + MBB = StartMBB; + BuildMI(MBB, DL, TII->get(SystemZ::CGHI)) + .addReg(StartCountReg).addImm(0); + BuildMI(MBB, DL, TII->get(SystemZ::BRC)) + .addImm(SystemZ::CCMASK_ICMP).addImm(SystemZ::CCMASK_CMP_EQ) + .addMBB(DoneMBB); + MBB->addSuccessor(DoneMBB); + MBB->addSuccessor(LoopMBB); + } + else { + StartMBB = MBB; + DoneMBB = SystemZ::splitBlockBefore(MI, MBB); + LoopMBB = SystemZ::emitBlockAfter(StartMBB); + NextMBB = (EndMBB ? SystemZ::emitBlockAfter(LoopMBB) : LoopMBB); + + // StartMBB: + // # fall through to LoopMBB + MBB->addSuccessor(LoopMBB); + + DestBase = MachineOperand::CreateReg(NextDestReg, false); + SrcBase = MachineOperand::CreateReg(NextSrcReg, false); + ImmLength &= 255; + if (EndMBB && !ImmLength) + // If the loop handled the whole CLC range, DoneMBB will be empty with + // CC live-through into EndMBB, so add it as live-in. + DoneMBB->addLiveIn(SystemZ::CC); + } // LoopMBB: // %ThisDestReg = phi [ %StartDestReg, StartMBB ], @@ -7808,7 +7902,6 @@ MachineBasicBlock *SystemZTargetLowering::emitMemMemWrapper( // // The prefetch is used only for MVC. The JLH is used only for CLC. MBB = LoopMBB; - BuildMI(MBB, DL, TII->get(SystemZ::PHI), ThisDestReg) .addReg(StartDestReg).addMBB(StartMBB) .addReg(NextDestReg).addMBB(NextMBB); @@ -7840,11 +7933,10 @@ MachineBasicBlock *SystemZTargetLowering::emitMemMemWrapper( // %NextCountReg = AGHI %ThisCountReg, -1 // CGHI %NextCountReg, 0 // JLH LoopMBB - // # fall through to DoneMMB + // # fall through to DoneMBB // // The AGHI, CGHI and JLH should be converted to BRCTG by later passes. MBB = NextMBB; - BuildMI(MBB, DL, TII->get(SystemZ::LA), NextDestReg) .addReg(ThisDestReg).addImm(256).addReg(0); if (!HaveSingleBase) @@ -7860,18 +7952,39 @@ MachineBasicBlock *SystemZTargetLowering::emitMemMemWrapper( MBB->addSuccessor(LoopMBB); MBB->addSuccessor(DoneMBB); - DestBase = MachineOperand::CreateReg(NextDestReg, false); - SrcBase = MachineOperand::CreateReg(NextSrcReg, false); - Length &= 255; - if (EndMBB && !Length) - // If the loop handled the whole CLC range, DoneMBB will be empty with - // CC live-through into EndMBB, so add it as live-in. - DoneMBB->addLiveIn(SystemZ::CC); MBB = DoneMBB; + if (LengthMO.isReg()) { + // DoneMBB: + // # Make PHIs for RemDestReg/RemSrcReg as the loop may or may not run. + // # Use EXecute Relative Long for the remainder of the bytes. The target + // instruction of the EXRL will have a length field of 1 since 0 is an + // illegal value. The number of bytes processed becomes (%LenMinus1Reg & + // 0xff) + 1. + // # Fall through to AllDoneMBB. + Register RemSrcReg = MRI.createVirtualRegister(&SystemZ::ADDR64BitRegClass); + Register RemDestReg = HaveSingleBase ? RemSrcReg + : MRI.createVirtualRegister(&SystemZ::ADDR64BitRegClass); + BuildMI(MBB, DL, TII->get(SystemZ::PHI), RemDestReg) + .addReg(StartDestReg).addMBB(StartMBB) + .addReg(NextDestReg).addMBB(LoopMBB); + if (!HaveSingleBase) + BuildMI(MBB, DL, TII->get(SystemZ::PHI), RemSrcReg) + .addReg(StartSrcReg).addMBB(StartMBB) + .addReg(NextSrcReg).addMBB(LoopMBB); + MRI.constrainRegClass(LenMinus1Reg, &SystemZ::ADDR64BitRegClass); + BuildMI(MBB, DL, TII->get(SystemZ::EXRL_Pseudo)) + .addImm(Opcode) + .addReg(LenMinus1Reg) + .addReg(RemDestReg).addImm(DestDisp) + .addReg(RemSrcReg).addImm(SrcDisp); + MBB->addSuccessor(AllDoneMBB); + MBB = AllDoneMBB; + } } + // Handle any remaining bytes with straight-line code. - while (Length > 0) { - uint64_t ThisLength = std::min(Length, uint64_t(256)); + while (ImmLength > 0) { + uint64_t ThisLength = std::min(ImmLength, uint64_t(256)); // The previous iteration might have created out-of-range displacements. // Apply them using LAY if so. if (!isUInt<12>(DestDisp)) { @@ -7901,10 +8014,10 @@ MachineBasicBlock *SystemZTargetLowering::emitMemMemWrapper( .setMemRefs(MI.memoperands()); DestDisp += ThisLength; SrcDisp += ThisLength; - Length -= ThisLength; + ImmLength -= ThisLength; // If there's another CLC to go, branch to the end if a difference // was found. - if (EndMBB && Length > 0) { + if (EndMBB && ImmLength > 0) { MachineBasicBlock *NextMBB = SystemZ::splitBlockBefore(MI, MBB); BuildMI(MBB, DL, TII->get(SystemZ::BRC)) .addImm(SystemZ::CCMASK_ICMP).addImm(SystemZ::CCMASK_CMP_NE) @@ -7949,7 +8062,7 @@ MachineBasicBlock *SystemZTargetLowering::emitStringWrapper( MachineBasicBlock *LoopMBB = SystemZ::emitBlockAfter(StartMBB); // StartMBB: - // # fall through to LoopMMB + // # fall through to LoopMBB MBB->addSuccessor(LoopMBB); // LoopMBB: @@ -7958,7 +8071,7 @@ MachineBasicBlock *SystemZTargetLowering::emitStringWrapper( // R0L = %CharReg // %End1Reg, %End2Reg = CLST %This1Reg, %This2Reg -- uses R0L // JO LoopMBB - // # fall through to DoneMMB + // # fall through to DoneMBB // // The load of R0L can be hoisted by post-RA LICM. MBB = LoopMBB; @@ -8395,6 +8508,7 @@ MachineBasicBlock *SystemZTargetLowering::EmitInstrWithCustomInserter( return emitMemMemWrapper(MI, MBB, SystemZ::OC); case SystemZ::XCSequence: case SystemZ::XCLoop: + case SystemZ::XCLoopVarLen: return emitMemMemWrapper(MI, MBB, SystemZ::XC); case SystemZ::CLCSequence: case SystemZ::CLCLoop: |
