Index: include/llvm/CodeGen/MachineRegisterInfo.h =================================================================== --- include/llvm/CodeGen/MachineRegisterInfo.h +++ include/llvm/CodeGen/MachineRegisterInfo.h @@ -84,14 +84,14 @@ /// all registers that were disabled are removed from the list. SmallVector UpdatedCSRs; - /// RegAllocHints - This vector records register allocation hints for virtual - /// registers. For each virtual register, it keeps a register and hint type - /// pair making up the allocation hint. Hint type is target specific except - /// for the value 0 which means the second value of the pair is the preferred - /// register for allocation. For example, if the hint is <0, 1024>, it means - /// the allocator should prefer the physical register allocated to the virtual - /// register of the hint. - IndexedMap, VirtReg2IndexFunctor> RegAllocHints; + /// RegAllocHints - This vector records register allocation hints for + /// virtual registers. For each virtual register, it keeps a pair of hint + /// type and hints vector making up the allocation hints. Hint type is + /// target specific except for the value 0. If the hinted register is + /// virtual, it means the allocator should prefer the physical register + /// allocated to it if any. + IndexedMap>, + VirtReg2IndexFunctor> RegAllocHints; /// PhysRegUseDefLists - This is an array of the head of the use/def list for /// physical registers. @@ -704,11 +704,22 @@ void clearVirtRegs(); /// setRegAllocationHint - Specify a register allocation hint for the - /// specified virtual register. + /// specified virtual register. Any previous hints are cleared. void setRegAllocationHint(unsigned VReg, unsigned Type, unsigned PrefReg) { assert(TargetRegisterInfo::isVirtualRegister(VReg)); RegAllocHints[VReg].first = Type; - RegAllocHints[VReg].second = PrefReg; + RegAllocHints[VReg].second.clear(); + RegAllocHints[VReg].second.push_back(PrefReg); + } + + /// addRegAllocationHint - Add a register allocation hint to the hints + /// vector for VReg. Currently assumes any VReg getting hints by calling + /// this will only have target independent hints. + void addRegAllocationHint(unsigned VReg, unsigned PrefReg) { + assert(TargetRegisterInfo::isVirtualRegister(VReg)); + assert(RegAllocHints[VReg].first == 0 && + "Only adding multiple copy hints for now"); + RegAllocHints[VReg].second.push_back(PrefReg); } /// Specify the preferred register allocation hint for the specified virtual @@ -718,10 +729,21 @@ } /// getRegAllocationHint - Return the register allocation hint for the - /// specified virtual register. + /// specified virtual register. If there are many hints, this returns the + /// one with the greatest weight. std::pair getRegAllocationHint(unsigned VReg) const { assert(TargetRegisterInfo::isVirtualRegister(VReg)); + unsigned BestHint = (RegAllocHints[VReg].second.size() ? + RegAllocHints[VReg].second[0] : 0); + return std::pair(RegAllocHints[VReg].first, BestHint); + } + + /// getRegAllocationHints - Return a reference to the vector of all + /// register allocation hints for VReg. + const std::pair > + &getRegAllocationHints(unsigned VReg) const { + assert(TargetRegisterInfo::isVirtualRegister(VReg)); return RegAllocHints[VReg]; } Index: lib/CodeGen/CalcSpillWeights.cpp =================================================================== --- lib/CodeGen/CalcSpillWeights.cpp +++ lib/CodeGen/CalcSpillWeights.cpp @@ -63,14 +63,16 @@ if (TargetRegisterInfo::isVirtualRegister(hreg)) return sub == hsub ? hreg : 0; + unsigned CopiedPReg = (hsub ? tri.getSubReg(hreg, hsub) : hreg); const TargetRegisterClass *rc = mri.getRegClass(reg); + if (rc->contains(CopiedPReg)) + return CopiedPReg; - // Only allow physreg hints in rc. - if (sub == 0) - return rc->contains(hreg) ? hreg : 0; + // Check if reg:sub matches so that a super register could be hinted. + if (sub) + return tri.getMatchingSuperReg(CopiedPReg, sub, rc); - // reg:sub should match the physreg hreg. - return tri.getMatchingSuperReg(hreg, sub, rc); + return 0; } // Check if all values in LI are rematerializable @@ -138,16 +140,30 @@ unsigned numInstr = 0; // Number of instructions using li SmallPtrSet visited; - // Find the best physreg hint and the best virtreg hint. - float bestPhys = 0, bestVirt = 0; - unsigned hintPhys = 0, hintVirt = 0; - // Don't recompute a target specific hint. bool noHint = mri.getRegAllocationHint(li.reg).first != 0; // Don't recompute spill weight for an unspillable register. bool Spillable = li.isSpillable(); + // CopyHint is a sortable hint derived from a COPY instruction. + struct CopyHint { + unsigned Reg; + float Weight; + bool IsPhys; + CopyHint(unsigned R, float W, bool P) : Reg(R), Weight(W), IsPhys(P) {} + bool operator<(const CopyHint &rhs) const { + // Always prefer any physreg hint. + if (IsPhys != rhs.IsPhys) + return (IsPhys && !rhs.IsPhys); + if (Weight > rhs.Weight) + return true; + // (just for the purpose of maintaining the set) + return Reg < rhs.Reg; + } + }; + + std::set CopyHints; for (MachineRegisterInfo::reg_instr_iterator I = mri.reg_instr_begin(li.reg), E = mri.reg_instr_end(); I != E; ) { @@ -190,27 +206,18 @@ // // FIXME: we probably shouldn't use floats at all. volatile float hweight = Hint[hint] += weight; - if (TargetRegisterInfo::isPhysicalRegister(hint)) { - if (hweight > bestPhys && mri.isAllocatable(hint)) { - bestPhys = hweight; - hintPhys = hint; - } - } else { - if (hweight > bestVirt) { - bestVirt = hweight; - hintVirt = hint; - } - } + CopyHints.insert(CopyHint(hint, hweight, tri.isPhysicalRegister(hint))); } Hint.clear(); - // Always prefer the physreg hint. - if (unsigned hint = hintPhys ? hintPhys : hintVirt) { - mri.setRegAllocationHint(li.reg, 0, hint); + // Pass all the sorted copy hints to mri. + for (auto &Hint : CopyHints) + mri.addRegAllocationHint(li.reg, Hint.Reg); + + if (CopyHints.size()) // Weakly boost the spill weight of hinted registers. totalWeight *= 1.01F; - } // If the live interval was already unspillable, leave it that way. if (!Spillable) Index: lib/CodeGen/TargetRegisterInfo.cpp =================================================================== --- lib/CodeGen/TargetRegisterInfo.cpp +++ lib/CodeGen/TargetRegisterInfo.cpp @@ -368,31 +368,35 @@ const VirtRegMap *VRM, const LiveRegMatrix *Matrix) const { const MachineRegisterInfo &MRI = MF.getRegInfo(); - std::pair Hint = MRI.getRegAllocationHint(VirtReg); + const std::pair> &Hints_MRI = + MRI.getRegAllocationHints(VirtReg); // Hints with HintType != 0 were set by target-dependent code. // Such targets must provide their own implementation of // TRI::getRegAllocationHints to interpret those hint types. - assert(Hint.first == 0 && "Target must implement TRI::getRegAllocationHints"); - - // Target-independent hints are either a physical or a virtual register. - unsigned Phys = Hint.second; - if (VRM && isVirtualRegister(Phys)) - Phys = VRM->getPhys(Phys); - - // Check that Phys is a valid hint in VirtReg's register class. - if (!isPhysicalRegister(Phys)) - return; - if (MRI.isReserved(Phys)) - return; - // Check that Phys is in the allocation order. We shouldn't heed hints - // from VirtReg's register class if they aren't in the allocation order. The - // target probably has a reason for removing the register. - if (!is_contained(Order, Phys)) - return; - - // All clear, tell the register allocator to prefer this register. - Hints.push_back(Phys); + assert(Hints_MRI.first == 0 && + "Target must implement TRI::getRegAllocationHints"); + + for (auto Reg : Hints_MRI.second) { + // Target-independent hints are either a physical or a virtual register. + unsigned Phys = Reg; + if (VRM && isVirtualRegister(Phys)) + Phys = VRM->getPhys(Phys); + + // Check that Phys is a valid hint in VirtReg's register class. + if (!isPhysicalRegister(Phys)) + return; + if (MRI.isReserved(Phys)) + return; + // Check that Phys is in the allocation order. We shouldn't heed hints + // from VirtReg's register class if they aren't in the allocation order. The + // target probably has a reason for removing the register. + if (!is_contained(Order, Phys)) + return; + + // All clear, tell the register allocator to prefer this register. + Hints.push_back(Phys); + } } bool TargetRegisterInfo::canRealignStack(const MachineFunction &MF) const { Index: test/CodeGen/SystemZ/call-05.ll =================================================================== --- test/CodeGen/SystemZ/call-05.ll +++ test/CodeGen/SystemZ/call-05.ll @@ -374,9 +374,8 @@ ; intervening lgr. define void @f21(i32 %val1, i32 %val2, void()* %fun) { ; CHECK-LABEL: f21: -; CHECK: crjhe %r2, %r3 ; CHECK: lgr %r1, %r4 -; CHECK: br %r1 +; CHECK: crbl %r2, %r3, 0(%r1) ; CHECK: br %r14 %cond = icmp slt i32 %val1, %val2; br i1 %cond, label %a, label %b; Index: test/CodeGen/SystemZ/call-args-coalesce.mir =================================================================== --- /dev/null +++ test/CodeGen/SystemZ/call-args-coalesce.mir @@ -0,0 +1,45 @@ +# RUN: llc -mtriple=s390x-linux-gnu -start-before=greedy %s -o - | FileCheck %s +# Test that %r2d is copied directly to %r1d + +--- | + + define void @f5(void (i32, i32, i32, i32)* %foo) { + tail call void %foo(i32 1, i32 2, i32 3, i32 4) + ret void + } + + ; Function Attrs: nounwind + declare void @llvm.stackprotector(i8*, i8**) #0 + + attributes #0 = { nounwind } + +... + +# CHECK: lgr %r1, %r2 +# CHECK-NOT: lgr + +--- +name: f5 +alignment: 2 +tracksRegLiveness: true +registers: + - { id: 0, class: gr64bit } + - { id: 1, class: gr32bit } + - { id: 2, class: gr32bit } + - { id: 3, class: gr32bit } + - { id: 4, class: gr32bit } +liveins: + - { reg: '%r2d', virtual-reg: '%0' } +body: | + bb.0 (%ir-block.0): + liveins: %r2d + + %0 = COPY %r2d + %r2l = LHI 1 + %r3l = LHI 2 + %r4l = LHI 3 + %r5l = LHI 4 + %r1d = COPY %0 + CallBR csr_systemz, implicit %r1d, implicit %r2l, implicit killed %r3l, implicit killed %r4l, implicit killed %r5l + +... Index: test/CodeGen/SystemZ/fp-sqrt-01.ll =================================================================== --- test/CodeGen/SystemZ/fp-sqrt-01.ll +++ test/CodeGen/SystemZ/fp-sqrt-01.ll @@ -159,11 +159,10 @@ ; Check that a call to the normal sqrtf function is lowered. define float @f8(float %dummy, float %val) { ; CHECK-LABEL: f8: -; CHECK: sqebr %f0, %f2 -; CHECK: cebr %f0, %f0 -; CHECK: bnor %r14 -; CHECK: {{ler|ldr}} %f0, %f2 -; CHECK: jg sqrtf@PLT +; CHECK: sqebr %f1, %f0 +; CHECK: cebr %f1, %f1 +; CHECK: jgo sqrtf@PLT +; CHECK: {{ler|ldr}} %f0, %f1 %res = tail call float @sqrtf(float %val) ret float %res } Index: test/CodeGen/SystemZ/fp-sqrt-02.ll =================================================================== --- test/CodeGen/SystemZ/fp-sqrt-02.ll +++ test/CodeGen/SystemZ/fp-sqrt-02.ll @@ -159,11 +159,10 @@ ; Check that a call to the normal sqrt function is lowered. define double @f8(double %dummy, double %val) { ; CHECK-LABEL: f8: -; CHECK: sqdbr %f0, %f2 -; CHECK: cdbr %f0, %f0 -; CHECK: bnor %r14 -; CHECK: ldr %f0, %f2 -; CHECK: jg sqrt@PLT +; CHECK: sqdbr %f1, %f0 +; CHECK: cdbr %f1, %f1 +; CHECK: jgo sqrt@PLT +; CHECK: ldr %f0, %f1 %res = tail call double @sqrt(double %val) ret double %res } Index: test/CodeGen/SystemZ/swift-return.ll =================================================================== --- test/CodeGen/SystemZ/swift-return.ll +++ test/CodeGen/SystemZ/swift-return.ll @@ -41,7 +41,6 @@ ; CHECK-LABEL: test2: ; CHECK: lr %[[REG1:r[0-9]+]], %r2 ; CHECK-DAG: la %r2, 160(%r15) -; CHECK-DAG: lr %r3, %[[REG1]] ; CHECK: brasl %r14, gen2 ; CHECK: l %r2, 160(%r15) ; CHECK: a %r2, 164(%r15) Index: test/CodeGen/SystemZ/swifterror.ll =================================================================== --- test/CodeGen/SystemZ/swifterror.ll +++ test/CodeGen/SystemZ/swifterror.ll @@ -34,11 +34,11 @@ ; CHECK: lgr %r[[REG1:[0-9]+]], %r2 ; CHECK: lghi %r9, 0 ; CHECK: brasl %r14, foo -; CHECK: cgijlh %r9, 0, +; CHECK: ltgr %r2, %r9 +; CHECK: jlh .LBB1_2 ; Access part of the error object and save it to error_ref -; CHECK: lb %r[[REG2:[0-9]+]], 8(%r9) +; CHECK: lb %r[[REG2:[0-9]+]], 8(%r2) ; CHECK: stc %r[[REG2]], 0(%r[[REG1]]) -; CHECK: lgr %r2, %r9 ; CHECK: brasl %r14, free ; CHECK-O0-LABEL: caller: ; CHECK-O0: lghi %r9, 0 @@ -70,13 +70,13 @@ ; CHECK: lgr %r[[REG1:[0-9]+]], %r2 ; CHECK: lghi %r9, 0 ; CHECK: brasl %r14, foo -; CHECK: cgijlh %r9, 0, +; CHECK: ltgr %r2, %r9 +; CHECK: jlh .LBB2_4 ; CHECK: ceb %f0, ; CHECK: jnh ; Access part of the error object and save it to error_ref -; CHECK: lb %r[[REG2:[0-9]+]], 8(%r9) +; CHECK: lb %r[[REG2:[0-9]+]], 8(%r2) ; CHECK: stc %r[[REG2]], 0(%r[[REG1]]) -; CHECK: lgr %r2, %r9 ; CHECK: brasl %r14, free ; CHECK-O0-LABEL: caller2: ; CHECK-O0: lghi %r9, 0 @@ -246,11 +246,11 @@ ; CHECK: lhi %r3, 1 ; CHECK: lghi %r9, 0 ; CHECK: brasl %r14, foo_sret -; CHECK: cgijlh %r9, 0, +; CHECK: ltgr %r2, %r9 +; CHECK: jlh .LBB6_2 ; Access part of the error object and save it to error_ref -; CHECK: lb %r0, 8(%r9) +; CHECK: lb %r0, 8(%r2) ; CHECK: stc %r0, 0(%r[[REG1]]) -; CHECK: lgr %r2, %r9 ; CHECK: brasl %r14, free ; CHECK-O0-LABEL: caller3: @@ -296,21 +296,21 @@ ; The first swifterror value: ; CHECK: lghi %r9, 0 ; CHECK: brasl %r14, foo -; CHECK: cgijlh %r9, 0, +; CHECK: ltgr %r2, %r9 +; CHECK: jlh .LBB7_2 ; Access part of the error object and save it to error_ref -; CHECK: lb %r0, 8(%r9) +; CHECK: lb %r0, 8(%r2) ; CHECK: stc %r0, 0(%r[[REG1]]) -; CHECK: lgr %r2, %r9 ; CHECK: brasl %r14, free ; The second swifterror value: ; CHECK: lghi %r9, 0 ; CHECK: brasl %r14, foo -; CHECK: cgijlh %r9, 0, +; CHECK: ltgr %r2, %r9 +; CHECK: jlh .LBB7_4 ; Access part of the error object and save it to error_ref -; CHECK: lb %r0, 8(%r9) +; CHECK: lb %r0, 8(%r2) ; CHECK: stc %r0, 0(%r[[REG2]]) -; CHECK: lgr %r2, %r9 ; CHECK: brasl %r14, free ; CHECK-O0-LABEL: caller_with_multiple_swifterror_values: