return false;
}
-// If Reg is a virtual register that is used by only a single non-debug
-// instruction, return the defining instruction, otherwise return null.
-static MachineInstr *getDefSingleUse(const MachineRegisterInfo *MRI,
- unsigned Reg) {
+// If Reg is a virtual register, return its definition, otherwise return null.
+static MachineInstr *getDef(unsigned Reg,
+ const MachineRegisterInfo *MRI) {
if (TargetRegisterInfo::isPhysicalRegister(Reg))
return 0;
-
- MachineRegisterInfo::use_nodbg_iterator I = MRI->use_nodbg_begin(Reg);
- MachineRegisterInfo::use_nodbg_iterator E = MRI->use_nodbg_end();
- if (I == E || llvm::next(I) != E)
- return 0;
-
return MRI->getUniqueVRegDef(Reg);
}
MI->getOperand(3).getImm() == Imm);
}
+// If the destination of MI has no uses, delete it as dead.
+static void eraseIfDead(MachineInstr *MI, const MachineRegisterInfo *MRI) {
+ if (MRI->use_nodbg_empty(MI->getOperand(0).getReg()))
+ MI->eraseFromParent();
+}
+
// Compare compares SrcReg against zero. Check whether SrcReg contains
-// the result of an IPM sequence that is only used by Compare. Try to
-// delete both of them if so and return true if a change was made.
-static bool removeIPM(MachineInstr *Compare, unsigned SrcReg,
- const MachineRegisterInfo *MRI,
- const TargetRegisterInfo *TRI) {
- MachineInstr *SRA = getDefSingleUse(MRI, SrcReg);
- if (!SRA || !isShift(SRA, SystemZ::SRA, 30))
+// the result of an IPM sequence whose input CC survives until Compare,
+// and whether Compare is therefore redundant. Delete it and return
+// true if so.
+static bool removeIPMBasedCompare(MachineInstr *Compare, unsigned SrcReg,
+ const MachineRegisterInfo *MRI,
+ const TargetRegisterInfo *TRI) {
+ MachineInstr *RLL = getDef(SrcReg, MRI);
+ if (!RLL || !isShift(RLL, SystemZ::RLL, 31))
return false;
- MachineInstr *SLL = getDefSingleUse(MRI, SRA->getOperand(1).getReg());
- if (!SLL || !isShift(SLL, SystemZ::SLL, 2))
+ MachineInstr *SRL = getDef(RLL->getOperand(1).getReg(), MRI);
+ if (!SRL || !isShift(SRL, SystemZ::SRL, 28))
return false;
- MachineInstr *IPM = getDefSingleUse(MRI, SLL->getOperand(1).getReg());
+ MachineInstr *IPM = getDef(SRL->getOperand(1).getReg(), MRI);
if (!IPM || IPM->getOpcode() != SystemZ::IPM)
return false;
// Check that there are no assignments to CC between the IPM and Compare,
- // except for the SRA that we'd like to delete. We can ignore SLL because
- // it does not assign to CC. We can also ignore uses of the SRA CC result,
- // since it is effectively restoring CC to the value it had before IPM
- // (for all current use cases).
if (IPM->getParent() != Compare->getParent())
return false;
MachineBasicBlock::iterator MBBI = IPM, MBBE = Compare;
for (++MBBI; MBBI != MBBE; ++MBBI) {
MachineInstr *MI = MBBI;
- if (MI != SRA && MI->modifiesRegister(SystemZ::CC, TRI))
+ if (MI->modifiesRegister(SystemZ::CC, TRI))
return false;
}
- IPM->eraseFromParent();
- SLL->eraseFromParent();
- SRA->eraseFromParent();
Compare->eraseFromParent();
+ eraseIfDead(RLL, MRI);
+ eraseIfDead(SRL, MRI);
+ eraseIfDead(IPM, MRI);
+
return true;
}
bool IsLogical = (Compare->getDesc().TSFlags & SystemZII::IsLogical) != 0;
if (Value == 0 &&
!IsLogical &&
- removeIPM(Compare, SrcReg, MRI, TM.getRegisterInfo()))
+ removeIPMBasedCompare(Compare, SrcReg, MRI, TM.getRegisterInfo()))
return true;
return false;
}
Src1, Src2, Size);
SDValue Glue = Chain.getValue(1);
// IPM inserts the CC value into bits 29 and 28, with 0 meaning "equal",
- // 1 meaning "greater" and 2 meaning "less". Convert them into an
- // integer that is respectively equal, greater or less than 0.
+ // 1 meaning "less" and 2 meaning "greater". Bits 30 and 31 are zero.
+ // Convert this into an integer that is respectively equal, less
+ // or greater than 0.
SDValue IPM = DAG.getNode(SystemZISD::IPM, DL, MVT::i32, Glue);
- SDValue SHL = DAG.getNode(ISD::SHL, DL, MVT::i32, IPM,
- DAG.getConstant(2, MVT::i32));
- SDValue SRA = DAG.getNode(ISD::SRA, DL, MVT::i32, SHL,
- DAG.getConstant(30, MVT::i32));
- return std::make_pair(SRA, Chain);
+ SDValue SRL = DAG.getNode(ISD::SRL, DL, MVT::i32, IPM,
+ DAG.getConstant(28, MVT::i32));
+ SDValue ROTL = DAG.getNode(ISD::ROTL, DL, MVT::i32, SRL,
+ DAG.getConstant(31, MVT::i32));
+ return std::make_pair(ROTL, Chain);
}
}
return std::make_pair(SDValue(), SDValue());
define i32 @f2(i8 *%src1, i8 *%src2) {
; CHECK-LABEL: f2:
; CHECK: clc 0(2,%r2), 0(%r3)
-; CHECK: ipm %r2
-; CHECK: sll %r2, 2
-; CHECK: sra %r2, 30
+; CHECK: ipm [[REG:%r[0-5]]]
+; CHECK: srl [[REG]], 28
+; CHECK: rll %r2, [[REG]], 31
; CHECK: br %r14
%res = call i32 @memcmp(i8 *%src1, i8 *%src2, i64 2)
ret i32 %res
}
; Check the upper end of the CLC range. Here the result is used both as
-; an integer and for branching, but it's better to branch on the result
-; of the SRA.
+; an integer and for branching.
define i32 @f7(i8 *%src1, i8 *%src2, i32 *%dest) {
; CHECK-LABEL: f7:
; CHECK: clc 0(256,%r2), 0(%r3)
-; CHECK: ipm %r2
-; CHECK: sll %r2, 2
-; CHECK: sra %r2, 30
+; CHECK: ipm [[REG:%r[0-5]]]
+; CHECK: srl [[REG]], 28
+; CHECK: rll %r2, [[REG]], 31
; CHECK: jl {{.L*}}
; CHECK: br %r14
entry: