[llvm] r182872 - Teach ReMaterialization to be more cunning about subregisters

Evan Cheng evan.cheng at apple.com
Wed May 29 13:26:18 PDT 2013


Nice. Is there measurable benefit for any specific target / benchmark?

Evan

On May 29, 2013, at 12:32 PM, Tim Northover <tnorthover at apple.com> wrote:

> Author: tnorthover
> Date: Wed May 29 14:32:06 2013
> New Revision: 182872
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=182872&view=rev
> Log:
> Teach ReMaterialization to be more cunning about subregisters
> 
> This allows rematerialization during register coalescing to handle
> more cases involving operations like SUBREG_TO_REG which might need to
> be rematerialized using sub-register indices.
> 
> For example, code like:
>    v1(GPR64):sub_32 = MOVZ something
>    v2(GPR64) = COPY v1(GPR64)
> should be convertable to:
>    v2(GPR64):sub_32 = MOVZ something
> 
> but previously we just gave up in places like this
> 
> Modified:
>    llvm/trunk/lib/CodeGen/RegisterCoalescer.cpp
>    llvm/trunk/test/CodeGen/AArch64/sibling-call.ll
>    llvm/trunk/test/DebugInfo/AArch64/variable-loc.ll
> 
> Modified: llvm/trunk/lib/CodeGen/RegisterCoalescer.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegisterCoalescer.cpp?rev=182872&r1=182871&r2=182872&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/RegisterCoalescer.cpp (original)
> +++ llvm/trunk/lib/CodeGen/RegisterCoalescer.cpp Wed May 29 14:32:06 2013
> @@ -733,7 +733,9 @@ bool RegisterCoalescer::removeCopyByComm
> bool RegisterCoalescer::reMaterializeTrivialDef(CoalescerPair &CP,
>                                                 MachineInstr *CopyMI) {
>   unsigned SrcReg = CP.isFlipped() ? CP.getDstReg() : CP.getSrcReg();
> +  unsigned SrcIdx = CP.isFlipped() ? CP.getDstIdx() : CP.getSrcIdx();
>   unsigned DstReg = CP.isFlipped() ? CP.getSrcReg() : CP.getDstReg();
> +  unsigned DstIdx = CP.isFlipped() ? CP.getSrcIdx() : CP.getDstIdx();
>   if (TargetRegisterInfo::isPhysicalRegister(SrcReg))
>     return false;
> 
> @@ -762,29 +764,38 @@ bool RegisterCoalescer::reMaterializeTri
>   MachineOperand &DstOperand = CopyMI->getOperand(0);
>   if (DstOperand.getSubReg() && !DstOperand.isUndef())
>     return false;
> +
> +  const TargetRegisterClass *DefRC = TII->getRegClass(MCID, 0, TRI, *MF);
>   if (!DefMI->isImplicitDef()) {
> -    // Make sure the copy destination register class fits the instruction
> -    // definition register class. The mismatch can happen as a result of earlier
> -    // extract_subreg, insert_subreg, subreg_to_reg coalescing.
> -    const TargetRegisterClass *RC = TII->getRegClass(MCID, 0, TRI, *MF);
> -    if (TargetRegisterInfo::isVirtualRegister(DstReg)) {
> -      if (!MRI->constrainRegClass(DstReg, RC))
> +    if (TargetRegisterInfo::isPhysicalRegister(DstReg)) {
> +      unsigned NewDstReg = DstReg;
> +
> +      unsigned NewDstIdx = TRI->composeSubRegIndices(CP.getSrcIdx(),
> +                                              DefMI->getOperand(0).getSubReg());
> +      if (NewDstIdx)
> +        NewDstReg = TRI->getSubReg(DstReg, NewDstIdx);
> +
> +      // Finally, make sure that the physical subregister that will be
> +      // constructed later is permitted for the instruction.
> +      if (!DefRC->contains(NewDstReg))
>         return false;
> -    } else if (!RC->contains(DstReg))
> -      return false;
> +    } else {
> +      // Theoretically, some stack frame reference could exist. Just make sure
> +      // it hasn't actually happened.
> +      assert(TargetRegisterInfo::isVirtualRegister(DstReg) &&
> +             "Only expect to deal with virtual or physical registers");
> +    }
>   }
> 
>   MachineBasicBlock *MBB = CopyMI->getParent();
>   MachineBasicBlock::iterator MII =
>     llvm::next(MachineBasicBlock::iterator(CopyMI));
> -  TII->reMaterialize(*MBB, MII, DstReg, 0, DefMI, *TRI);
> +  TII->reMaterialize(*MBB, MII, DstReg, SrcIdx, DefMI, *TRI);
>   MachineInstr *NewMI = prior(MII);
> 
> -  // The original DefMI may have been a subregister def, but the full register
> -  // class of its destination matches the destination of CopyMI, and CopyMI is
> -  // either a full register def or is read-undef. Therefore we can clear the
> -  // subregister index on the rematerialized instruction.
> -  NewMI->getOperand(0).setSubReg(0);
> +  LIS->ReplaceMachineInstrInMaps(CopyMI, NewMI);
> +  CopyMI->eraseFromParent();
> +  ErasedInstrs.insert(CopyMI);
> 
>   // NewMI may have dead implicit defs (E.g. EFLAGS for MOV<bits>r0 on X86).
>   // We need to remember these so we can add intervals once we insert
> @@ -800,6 +811,46 @@ bool RegisterCoalescer::reMaterializeTri
>     }
>   }
> 
> +  if (TargetRegisterInfo::isVirtualRegister(DstReg)) {
> +    unsigned NewIdx = NewMI->getOperand(0).getSubReg();
> +    const TargetRegisterClass *RCForInst;
> +    if (NewIdx)
> +      RCForInst = TRI->getMatchingSuperRegClass(MRI->getRegClass(DstReg), DefRC,
> +                                                NewIdx);
> +
> +    if (MRI->constrainRegClass(DstReg, DefRC)) {
> +      // The materialized instruction is quite capable of setting DstReg
> +      // directly, but it may still have a now-trivial subregister index which
> +      // we should clear.
> +      NewMI->getOperand(0).setSubReg(0);
> +    } else if (NewIdx && RCForInst) {
> +      // The subreg index on NewMI is essential; we still have to make sure
> +      // DstReg:idx is in a class that NewMI can use.
> +      MRI->constrainRegClass(DstReg, RCForInst);
> +    } else {
> +      // DstReg is actually incompatible with NewMI, we have to move to a
> +      // super-reg's class. This could come from a sequence like:
> +      //     GR32 = MOV32r0
> +      //     GR8 = COPY GR32:sub_8
> +      MRI->setRegClass(DstReg, CP.getNewRC());
> +      updateRegDefsUses(DstReg, DstReg, DstIdx);
> +      NewMI->getOperand(0).setSubReg(
> +          TRI->composeSubRegIndices(SrcIdx, DefMI->getOperand(0).getSubReg()));
> +    }
> +  } else if (NewMI->getOperand(0).getReg() != DstReg) {
> +    // The New instruction may be defining a sub-register of what's actually
> +    // been asked for. If so it must implicitly define the whole thing.
> +    assert(TargetRegisterInfo::isPhysicalRegister(DstReg) &&
> +           "Only expect virtual or physical registers in remat");
> +    NewMI->addOperand(MachineOperand::CreateReg(DstReg,
> +                                                true  /*IsDef*/,
> +                                                true  /*IsImp*/,
> +                                                false /*IsKill*/));
> +  }
> +
> +  if (NewMI->getOperand(0).getSubReg())
> +    NewMI->getOperand(0).setIsUndef();
> +
>   // CopyMI may have implicit operands, transfer them over to the newly
>   // rematerialized instruction. And update implicit def interval valnos.
>   for (unsigned i = CopyMI->getDesc().getNumOperands(),
> @@ -814,8 +865,6 @@ bool RegisterCoalescer::reMaterializeTri
>     }
>   }
> 
> -  LIS->ReplaceMachineInstrInMaps(CopyMI, NewMI);
> -
>   SlotIndex NewMIIdx = LIS->getInstructionIndex(NewMI);
>   for (unsigned i = 0, e = NewMIImplDefs.size(); i != e; ++i) {
>     unsigned Reg = NewMIImplDefs[i];
> @@ -824,8 +873,6 @@ bool RegisterCoalescer::reMaterializeTri
>         LI->createDeadDef(NewMIIdx.getRegSlot(), LIS->getVNInfoAllocator());
>   }
> 
> -  CopyMI->eraseFromParent();
> -  ErasedInstrs.insert(CopyMI);
>   DEBUG(dbgs() << "Remat: " << *NewMI);
>   ++NumReMats;
> 
> 
> Modified: llvm/trunk/test/CodeGen/AArch64/sibling-call.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/sibling-call.ll?rev=182872&r1=182871&r2=182872&view=diff
> ==============================================================================
> --- llvm/trunk/test/CodeGen/AArch64/sibling-call.ll (original)
> +++ llvm/trunk/test/CodeGen/AArch64/sibling-call.ll Wed May 29 14:32:06 2013
> @@ -91,7 +91,7 @@ define void @indirect_tail() {
>   %fptr = load void(i32)** @func
>   tail call void %fptr(i32 42)
>   ret void
> -; CHECK: movz w0, #42
> ; CHECK: ldr [[FPTR:x[1-9]+]], [{{x[0-9]+}}, #:lo12:func]
> +; CHECK: movz w0, #42
> ; CHECK: br [[FPTR]]
> -}
> \ No newline at end of file
> +}
> 
> Modified: llvm/trunk/test/DebugInfo/AArch64/variable-loc.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/AArch64/variable-loc.ll?rev=182872&r1=182871&r2=182872&view=diff
> ==============================================================================
> --- llvm/trunk/test/DebugInfo/AArch64/variable-loc.ll (original)
> +++ llvm/trunk/test/DebugInfo/AArch64/variable-loc.ll Wed May 29 14:32:06 2013
> @@ -16,21 +16,21 @@
> ;     return 0;
> ; }
> 
> -  ; First make sure main_arr is where we expect it: sp + 12 == x29 - 420:
> +  ; First make sure main_arr is where we expect it: sp + 4 == x29 - 412:
> ; CHECK: main:
> -; CHECK: sub sp, sp, #448
> -; CHECK: stp x29, x30, [sp, #432]
> -; CHECK: add x29, sp, #432
> -; CHECK: add {{x[0-9]+}}, sp, #12
> +; CHECK: sub sp, sp, #432
> +; CHECK: stp x29, x30, [sp, #416]
> +; CHECK: add x29, sp, #416
> +; CHECK: add {{x[0-9]+}}, sp, #4
> 
>   ; Now check the debugging information reflects this:
> ; CHECK: DW_TAG_variable
> ; CHECK-NEXT: .word .Linfo_string7
> 
> -  ; Rather hard-coded, but 145 => DW_OP_fbreg and the .ascii is LEB128 encoded -420.
> +  ; Rather hard-coded, but 145 => DW_OP_fbreg and the .ascii is LEB128 encoded -412.
> ; CHECK: DW_AT_location
> ; CHECK-NEXT: .byte 145
> -; CHECK-NEXT: .ascii "\334|"
> +; CHECK-NEXT: .ascii "\344|"
> 
> ; CHECK: .Linfo_string7:
> ; CHECK-NEXT: main_arr
> 
> 
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits




More information about the llvm-commits mailing list