return false;
}
-bool PPCInstrInfo::combineRLWINM(MachineInstr &MI,
- MachineInstr **ToErase) const {
+// This function tries to combine two RLWINMs. We not only perform such
+// optimization in SSA, but also after RA, since some RLWINM is generated after
+// RA.
+bool PPCInstrInfo::simplifyRotateAndMaskInstr(MachineInstr &MI,
+ MachineInstr *&ToErase) const {
+ bool Is64Bit = false;
+ switch (MI.getOpcode()) {
+ case PPC::RLWINM:
+ case PPC::RLWINM_rec:
+ break;
+ case PPC::RLWINM8:
+ case PPC::RLWINM8_rec:
+ Is64Bit = true;
+ break;
+ default:
+ return false;
+ }
MachineRegisterInfo *MRI = &MI.getParent()->getParent()->getRegInfo();
- unsigned FoldingReg = MI.getOperand(1).getReg();
- if (!Register::isVirtualRegister(FoldingReg))
+ Register FoldingReg = MI.getOperand(1).getReg();
+ MachineInstr *SrcMI = nullptr;
+ bool NoUse = false;
+ if (MRI->isSSA()) {
+ if (!Register::isVirtualRegister(FoldingReg))
+ return false;
+ SrcMI = MRI->getVRegDef(FoldingReg);
+ } else {
+ bool OtherIntermediateUse = false;
+ SrcMI = getDefMIPostRA(FoldingReg, MI, OtherIntermediateUse);
+ NoUse = !OtherIntermediateUse && MI.getOperand(1).isKill();
+ }
+ if (!SrcMI)
return false;
- MachineInstr *SrcMI = MRI->getVRegDef(FoldingReg);
- if (SrcMI->getOpcode() != PPC::RLWINM &&
- SrcMI->getOpcode() != PPC::RLWINM_rec &&
- SrcMI->getOpcode() != PPC::RLWINM8 &&
- SrcMI->getOpcode() != PPC::RLWINM8_rec)
+ // TODO: The pairs of RLWINM8(RLWINM) or RLWINM(RLWINM8) never occur before
+ // RA, but after RA. And We can fold RLWINM8(RLWINM) -> RLWINM8, or
+ // RLWINM(RLWINM8) -> RLWINM.
+ switch (SrcMI->getOpcode()) {
+ case PPC::RLWINM:
+ case PPC::RLWINM_rec:
+ if (Is64Bit)
+ return false;
+ break;
+ case PPC::RLWINM8:
+ case PPC::RLWINM8_rec:
+ if (!Is64Bit)
+ return false;
+ break;
+ default:
return false;
+ }
assert((MI.getOperand(2).isImm() && MI.getOperand(3).isImm() &&
MI.getOperand(4).isImm() && SrcMI->getOperand(2).isImm() &&
SrcMI->getOperand(3).isImm() && SrcMI->getOperand(4).isImm()) &&
// If final mask is 0, MI result should be 0 too.
if (FinalMask.isNullValue()) {
- bool Is64Bit =
- (MI.getOpcode() == PPC::RLWINM8 || MI.getOpcode() == PPC::RLWINM8_rec);
Simplified = true;
LLVM_DEBUG(dbgs() << "Replace Instr: ");
LLVM_DEBUG(MI.dump());
LLVM_DEBUG(dbgs() << "To: ");
LLVM_DEBUG(MI.dump());
}
- if (Simplified & MRI->use_nodbg_empty(FoldingReg) &&
- !SrcMI->hasImplicitDef()) {
- // If FoldingReg has no non-debug use and it has no implicit def (it
- // is not RLWINMO or RLWINM8o), it's safe to delete its def SrcMI.
- // Otherwise keep it.
- *ToErase = SrcMI;
- LLVM_DEBUG(dbgs() << "Delete dead instruction: ");
- LLVM_DEBUG(SrcMI->dump());
+ if (Simplified && !SrcMI->hasImplicitDef()) {
+ // If SrcMI has no implicit def, and FoldingReg has no non-debug use or
+ // its flag is "killed", it's safe to delete SrcMI. Otherwise keep it.
+ if ((!MRI->isSSA() && NoUse) ||
+ (MRI->isSSA() && MRI->use_nodbg_empty(FoldingReg))) {
+ ToErase = SrcMI;
+ LLVM_DEBUG(dbgs() << "Delete dead instruction: ");
+ LLVM_DEBUG(SrcMI->dump());
+ }
}
return Simplified;
}
--- /dev/null
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mcpu=pwr9 -mtriple=powerpc64le-unknown-unknown -stop-after \
+# RUN: ppc-pre-emit-peephole %s -o - | FileCheck %s
+
+---
+name: testFoldRLWINM
+tracksRegLiveness: true
+body: |
+ bb.0.entry:
+ liveins: $r3
+ ; CHECK-LABEL: name: testFoldRLWINM
+ ; CHECK: liveins: $r3
+ ; CHECK: renamable $r3 = RLWINM killed renamable $r3, 14, 0, 12, implicit-def $x3
+ ; CHECK: BLR8 implicit $lr8, implicit $rm, implicit killed $x3
+ $r3 = RLWINM killed $r3, 27, 5, 31
+ dead renamable $r3 = RLWINM killed renamable $r3, 19, 0, 12, implicit-def $x3
+ BLR8 implicit $lr8, implicit $rm, implicit killed $x3
+...
+---
+name: testFoldRLWINMSrcFullMask
+tracksRegLiveness: true
+body: |
+ bb.0.entry:
+ liveins: $r3
+ ; CHECK-LABEL: name: testFoldRLWINMSrcFullMask
+ ; CHECK: liveins: $r3
+ ; CHECK: renamable $r3 = RLWINM killed renamable $r3, 14, 0, 12, implicit-def $x3
+ ; CHECK: BLR8 implicit $lr8, implicit $rm, implicit killed $x3
+ $r3 = RLWINM killed $r3, 27, 0, 31
+ dead renamable $r3 = RLWINM killed renamable $r3, 19, 0, 12, implicit-def $x3
+ BLR8 implicit $lr8, implicit $rm, implicit killed $x3
+...
+---
+name: testFoldRLWINMSrcWrapped
+tracksRegLiveness: true
+body: |
+ bb.0.entry:
+ liveins: $r3
+ ; CHECK-LABEL: name: testFoldRLWINMSrcWrapped
+ ; CHECK: liveins: $r3
+ ; CHECK: renamable $r3 = RLWINM killed renamable $r3, 14, 11, 12, implicit-def $x3
+ ; CHECK: BLR8 implicit $lr8, implicit $rm, implicit killed $x3
+ $r3 = RLWINM killed $r3, 27, 30, 10
+ dead renamable $r3 = RLWINM killed renamable $r3, 19, 0, 12, implicit-def $x3
+ BLR8 implicit $lr8, implicit $rm, implicit killed $x3
+...
+---
+name: testFoldRLWINMToZero
+tracksRegLiveness: true
+body: |
+ bb.0.entry:
+ liveins: $r3
+ ; CHECK-LABEL: name: testFoldRLWINMToZero
+ ; CHECK: liveins: $r3
+ ; CHECK: renamable $r3 = LI 0, implicit-def $x3
+ ; CHECK: BLR8 implicit $lr8, implicit $rm, implicit killed $x3
+ $r3 = RLWINM killed $r3, 27, 5, 10
+ dead renamable $r3 = RLWINM killed renamable $r3, 8, 5, 10, implicit-def $x3
+ BLR8 implicit $lr8, implicit $rm, implicit killed $x3
+...
+---
+name: testFoldRLWINM_recToZero
+tracksRegLiveness: true
+body: |
+ bb.0.entry:
+ liveins: $r3
+ ; CHECK-LABEL: name: testFoldRLWINM_recToZero
+ ; CHECK: liveins: $r3
+ ; CHECK: dead renamable $r3 = ANDI_rec killed renamable $r3, 0, implicit-def $cr0
+ ; CHECK: BLR8 implicit $lr8, implicit $rm, implicit killed $cr0
+ $r3 = RLWINM killed $r3, 27, 5, 10
+ dead renamable $r3 = RLWINM_rec killed renamable $r3, 8, 5, 10, implicit-def $cr0
+ BLR8 implicit $lr8, implicit $rm, implicit killed $cr0
+...
+---
+name: testFoldRLWINMoToZeroSrcCanNotBeDeleted
+tracksRegLiveness: true
+body: |
+ bb.0.entry:
+ liveins: $r3
+ ; CHECK-LABEL: name: testFoldRLWINMoToZeroSrcCanNotBeDeleted
+ ; CHECK: liveins: $r3
+ ; CHECK: $r3 = RLWINM_rec $r3, 27, 5, 10, implicit-def dead $cr0
+ ; CHECK: dead renamable $r3 = ANDI_rec killed renamable $r3, 0, implicit-def $cr0
+ ; CHECK: BLR8 implicit $lr8, implicit $rm, implicit killed $cr0
+ $r3 = RLWINM_rec $r3, 27, 5, 10, implicit-def $cr0
+ dead renamable $r3 = RLWINM_rec killed renamable $r3, 8, 5, 10, implicit-def $cr0
+ BLR8 implicit $lr8, implicit $rm, implicit killed $cr0
+...
+---
+name: testFoldRLWINMInvalidMask
+tracksRegLiveness: true
+body: |
+ bb.0.entry:
+ liveins: $r3
+ ; CHECK-LABEL: name: testFoldRLWINMInvalidMask
+ ; CHECK: liveins: $r3
+ ; CHECK: $r3 = RLWINM killed $r3, 20, 5, 31
+ ; CHECK: renamable $r3 = RLWINM killed renamable $r3, 19, 10, 20, implicit-def $x3
+ ; CHECK: BLR8 implicit $lr8, implicit $rm, implicit killed $x3
+ $r3 = RLWINM killed $r3, 20, 5, 31
+ dead renamable $r3 = RLWINM killed renamable $r3, 19, 10, 20, implicit-def $x3
+ BLR8 implicit $lr8, implicit $rm, implicit killed $x3
+...