Skip to content

Commit f582206

Browse files
committed
Merging r353304:
------------------------------------------------------------------------ r353304 | uweigand | 2019-02-06 16:10:13 +0100 (Wed, 06 Feb 2019) | 18 lines [SystemZ] Do not return INT_MIN from strcmp/memcmp The IPM sequence currently generated to compute the strcmp/memcmp result will return INT_MIN for the "less than zero" case. While this is in compliance with the standard, strictly speaking, it turns out that common applications cannot handle this, e.g. because they negate a comparison result in order to implement reverse compares. This patch changes code to use a different sequence that will result in -2 for the "less than zero" case (same as GCC). However, this requires that the two source operands of the compare instructions are inverted, which breaks the optimization in removeIPMBasedCompare. Therefore, I've removed this (and all of optimizeCompareInstr), and replaced it with a mostly equivalent optimization in combineCCMask at the DAGcombine level. ------------------------------------------------------------------------ llvm-svn: 353379
1 parent 7ec84db commit f582206

File tree

6 files changed

+129
-163
lines changed

6 files changed

+129
-163
lines changed

llvm/lib/Target/SystemZ/SystemZISelLowering.cpp

Lines changed: 81 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -5618,55 +5618,96 @@ SDValue SystemZTargetLowering::combineBSWAP(
56185618
static bool combineCCMask(SDValue &CCReg, int &CCValid, int &CCMask) {
56195619
// We have a SELECT_CCMASK or BR_CCMASK comparing the condition code
56205620
// set by the CCReg instruction using the CCValid / CCMask masks,
5621-
// If the CCReg instruction is itself a (ICMP (SELECT_CCMASK)) testing
5622-
// the condition code set by some other instruction, see whether we
5623-
// can directly use that condition code.
5624-
bool Invert = false;
5621+
// If the CCReg instruction is itself a ICMP testing the condition
5622+
// code set by some other instruction, see whether we can directly
5623+
// use that condition code.
56255624

5626-
// Verify that we have an appropriate mask for a EQ or NE comparison.
5625+
// Verify that we have an ICMP against some constant.
56275626
if (CCValid != SystemZ::CCMASK_ICMP)
56285627
return false;
5629-
if (CCMask == SystemZ::CCMASK_CMP_NE)
5630-
Invert = !Invert;
5631-
else if (CCMask != SystemZ::CCMASK_CMP_EQ)
5632-
return false;
5633-
5634-
// Verify that we have an ICMP that is the user of a SELECT_CCMASK.
5635-
SDNode *ICmp = CCReg.getNode();
5628+
auto *ICmp = CCReg.getNode();
56365629
if (ICmp->getOpcode() != SystemZISD::ICMP)
56375630
return false;
5638-
SDNode *Select = ICmp->getOperand(0).getNode();
5639-
if (Select->getOpcode() != SystemZISD::SELECT_CCMASK)
5631+
auto *CompareLHS = ICmp->getOperand(0).getNode();
5632+
auto *CompareRHS = dyn_cast<ConstantSDNode>(ICmp->getOperand(1));
5633+
if (!CompareRHS)
56405634
return false;
56415635

5642-
// Verify that the ICMP compares against one of select values.
5643-
auto *CompareVal = dyn_cast<ConstantSDNode>(ICmp->getOperand(1));
5644-
if (!CompareVal)
5645-
return false;
5646-
auto *TrueVal = dyn_cast<ConstantSDNode>(Select->getOperand(0));
5647-
if (!TrueVal)
5648-
return false;
5649-
auto *FalseVal = dyn_cast<ConstantSDNode>(Select->getOperand(1));
5650-
if (!FalseVal)
5651-
return false;
5652-
if (CompareVal->getZExtValue() == FalseVal->getZExtValue())
5653-
Invert = !Invert;
5654-
else if (CompareVal->getZExtValue() != TrueVal->getZExtValue())
5655-
return false;
5636+
// Optimize the case where CompareLHS is a SELECT_CCMASK.
5637+
if (CompareLHS->getOpcode() == SystemZISD::SELECT_CCMASK) {
5638+
// Verify that we have an appropriate mask for a EQ or NE comparison.
5639+
bool Invert = false;
5640+
if (CCMask == SystemZ::CCMASK_CMP_NE)
5641+
Invert = !Invert;
5642+
else if (CCMask != SystemZ::CCMASK_CMP_EQ)
5643+
return false;
56565644

5657-
// Compute the effective CC mask for the new branch or select.
5658-
auto *NewCCValid = dyn_cast<ConstantSDNode>(Select->getOperand(2));
5659-
auto *NewCCMask = dyn_cast<ConstantSDNode>(Select->getOperand(3));
5660-
if (!NewCCValid || !NewCCMask)
5661-
return false;
5662-
CCValid = NewCCValid->getZExtValue();
5663-
CCMask = NewCCMask->getZExtValue();
5664-
if (Invert)
5665-
CCMask ^= CCValid;
5645+
// Verify that the ICMP compares against one of select values.
5646+
auto *TrueVal = dyn_cast<ConstantSDNode>(CompareLHS->getOperand(0));
5647+
if (!TrueVal)
5648+
return false;
5649+
auto *FalseVal = dyn_cast<ConstantSDNode>(CompareLHS->getOperand(1));
5650+
if (!FalseVal)
5651+
return false;
5652+
if (CompareRHS->getZExtValue() == FalseVal->getZExtValue())
5653+
Invert = !Invert;
5654+
else if (CompareRHS->getZExtValue() != TrueVal->getZExtValue())
5655+
return false;
56665656

5667-
// Return the updated CCReg link.
5668-
CCReg = Select->getOperand(4);
5669-
return true;
5657+
// Compute the effective CC mask for the new branch or select.
5658+
auto *NewCCValid = dyn_cast<ConstantSDNode>(CompareLHS->getOperand(2));
5659+
auto *NewCCMask = dyn_cast<ConstantSDNode>(CompareLHS->getOperand(3));
5660+
if (!NewCCValid || !NewCCMask)
5661+
return false;
5662+
CCValid = NewCCValid->getZExtValue();
5663+
CCMask = NewCCMask->getZExtValue();
5664+
if (Invert)
5665+
CCMask ^= CCValid;
5666+
5667+
// Return the updated CCReg link.
5668+
CCReg = CompareLHS->getOperand(4);
5669+
return true;
5670+
}
5671+
5672+
// Optimize the case where CompareRHS is (SRA (SHL (IPM))).
5673+
if (CompareLHS->getOpcode() == ISD::SRA) {
5674+
auto *SRACount = dyn_cast<ConstantSDNode>(CompareLHS->getOperand(1));
5675+
if (!SRACount || SRACount->getZExtValue() != 30)
5676+
return false;
5677+
auto *SHL = CompareLHS->getOperand(0).getNode();
5678+
if (SHL->getOpcode() != ISD::SHL)
5679+
return false;
5680+
auto *SHLCount = dyn_cast<ConstantSDNode>(SHL->getOperand(1));
5681+
if (!SHLCount || SHLCount->getZExtValue() != 30 - SystemZ::IPM_CC)
5682+
return false;
5683+
auto *IPM = SHL->getOperand(0).getNode();
5684+
if (IPM->getOpcode() != SystemZISD::IPM)
5685+
return false;
5686+
5687+
// Avoid introducing CC spills (because SRA would clobber CC).
5688+
if (!CompareLHS->hasOneUse())
5689+
return false;
5690+
// Verify that the ICMP compares against zero.
5691+
if (CompareRHS->getZExtValue() != 0)
5692+
return false;
5693+
5694+
// Compute the effective CC mask for the new branch or select.
5695+
switch (CCMask) {
5696+
case SystemZ::CCMASK_CMP_EQ: break;
5697+
case SystemZ::CCMASK_CMP_NE: break;
5698+
case SystemZ::CCMASK_CMP_LT: CCMask = SystemZ::CCMASK_CMP_GT; break;
5699+
case SystemZ::CCMASK_CMP_GT: CCMask = SystemZ::CCMASK_CMP_LT; break;
5700+
case SystemZ::CCMASK_CMP_LE: CCMask = SystemZ::CCMASK_CMP_GE; break;
5701+
case SystemZ::CCMASK_CMP_GE: CCMask = SystemZ::CCMASK_CMP_LE; break;
5702+
default: return false;
5703+
}
5704+
5705+
// Return the updated CCReg link.
5706+
CCReg = IPM->getOperand(0);
5707+
return true;
5708+
}
5709+
5710+
return false;
56705711
}
56715712

56725713
SDValue SystemZTargetLowering::combineBR_CCMASK(

llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp

Lines changed: 0 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -557,80 +557,6 @@ bool SystemZInstrInfo::analyzeCompare(const MachineInstr &MI, unsigned &SrcReg,
557557
return false;
558558
}
559559

560-
// If Reg is a virtual register, return its definition, otherwise return null.
561-
static MachineInstr *getDef(unsigned Reg,
562-
const MachineRegisterInfo *MRI) {
563-
if (TargetRegisterInfo::isPhysicalRegister(Reg))
564-
return nullptr;
565-
return MRI->getUniqueVRegDef(Reg);
566-
}
567-
568-
// Return true if MI is a shift of type Opcode by Imm bits.
569-
static bool isShift(MachineInstr *MI, unsigned Opcode, int64_t Imm) {
570-
return (MI->getOpcode() == Opcode &&
571-
!MI->getOperand(2).getReg() &&
572-
MI->getOperand(3).getImm() == Imm);
573-
}
574-
575-
// If the destination of MI has no uses, delete it as dead.
576-
static void eraseIfDead(MachineInstr *MI, const MachineRegisterInfo *MRI) {
577-
if (MRI->use_nodbg_empty(MI->getOperand(0).getReg()))
578-
MI->eraseFromParent();
579-
}
580-
581-
// Compare compares SrcReg against zero. Check whether SrcReg contains
582-
// the result of an IPM sequence whose input CC survives until Compare,
583-
// and whether Compare is therefore redundant. Delete it and return
584-
// true if so.
585-
static bool removeIPMBasedCompare(MachineInstr &Compare, unsigned SrcReg,
586-
const MachineRegisterInfo *MRI,
587-
const TargetRegisterInfo *TRI) {
588-
MachineInstr *LGFR = nullptr;
589-
MachineInstr *RLL = getDef(SrcReg, MRI);
590-
if (RLL && RLL->getOpcode() == SystemZ::LGFR) {
591-
LGFR = RLL;
592-
RLL = getDef(LGFR->getOperand(1).getReg(), MRI);
593-
}
594-
if (!RLL || !isShift(RLL, SystemZ::RLL, 31))
595-
return false;
596-
597-
MachineInstr *SRL = getDef(RLL->getOperand(1).getReg(), MRI);
598-
if (!SRL || !isShift(SRL, SystemZ::SRL, SystemZ::IPM_CC))
599-
return false;
600-
601-
MachineInstr *IPM = getDef(SRL->getOperand(1).getReg(), MRI);
602-
if (!IPM || IPM->getOpcode() != SystemZ::IPM)
603-
return false;
604-
605-
// Check that there are no assignments to CC between the IPM and Compare,
606-
if (IPM->getParent() != Compare.getParent())
607-
return false;
608-
MachineBasicBlock::iterator MBBI = IPM, MBBE = Compare.getIterator();
609-
for (++MBBI; MBBI != MBBE; ++MBBI) {
610-
MachineInstr &MI = *MBBI;
611-
if (MI.modifiesRegister(SystemZ::CC, TRI))
612-
return false;
613-
}
614-
615-
Compare.eraseFromParent();
616-
if (LGFR)
617-
eraseIfDead(LGFR, MRI);
618-
eraseIfDead(RLL, MRI);
619-
eraseIfDead(SRL, MRI);
620-
eraseIfDead(IPM, MRI);
621-
622-
return true;
623-
}
624-
625-
bool SystemZInstrInfo::optimizeCompareInstr(
626-
MachineInstr &Compare, unsigned SrcReg, unsigned SrcReg2, int Mask,
627-
int Value, const MachineRegisterInfo *MRI) const {
628-
assert(!SrcReg2 && "Only optimizing constant comparisons so far");
629-
bool IsLogical = (Compare.getDesc().TSFlags & SystemZII::IsLogical) != 0;
630-
return Value == 0 && !IsLogical &&
631-
removeIPMBasedCompare(Compare, SrcReg, MRI, &RI);
632-
}
633-
634560
bool SystemZInstrInfo::canInsertSelect(const MachineBasicBlock &MBB,
635561
ArrayRef<MachineOperand> Pred,
636562
unsigned TrueReg, unsigned FalseReg,

llvm/lib/Target/SystemZ/SystemZInstrInfo.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -208,9 +208,6 @@ class SystemZInstrInfo : public SystemZGenInstrInfo {
208208
int *BytesAdded = nullptr) const override;
209209
bool analyzeCompare(const MachineInstr &MI, unsigned &SrcReg,
210210
unsigned &SrcReg2, int &Mask, int &Value) const override;
211-
bool optimizeCompareInstr(MachineInstr &CmpInstr, unsigned SrcReg,
212-
unsigned SrcReg2, int Mask, int Value,
213-
const MachineRegisterInfo *MRI) const override;
214211
bool canInsertSelect(const MachineBasicBlock&, ArrayRef<MachineOperand> Cond,
215212
unsigned, unsigned, int&, int&, int&) const override;
216213
void insertSelect(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,

llvm/lib/Target/SystemZ/SystemZSelectionDAGInfo.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -164,17 +164,17 @@ static SDValue emitCLC(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain,
164164
}
165165

166166
// Convert the current CC value into an integer that is 0 if CC == 0,
167-
// less than zero if CC == 1 and greater than zero if CC >= 2.
167+
// greater than zero if CC == 1 and less than zero if CC >= 2.
168168
// The sequence starts with IPM, which puts CC into bits 29 and 28
169169
// of an integer and clears bits 30 and 31.
170170
static SDValue addIPMSequence(const SDLoc &DL, SDValue CCReg,
171171
SelectionDAG &DAG) {
172172
SDValue IPM = DAG.getNode(SystemZISD::IPM, DL, MVT::i32, CCReg);
173-
SDValue SRL = DAG.getNode(ISD::SRL, DL, MVT::i32, IPM,
174-
DAG.getConstant(SystemZ::IPM_CC, DL, MVT::i32));
175-
SDValue ROTL = DAG.getNode(ISD::ROTL, DL, MVT::i32, SRL,
176-
DAG.getConstant(31, DL, MVT::i32));
177-
return ROTL;
173+
SDValue SHL = DAG.getNode(ISD::SHL, DL, MVT::i32, IPM,
174+
DAG.getConstant(30 - SystemZ::IPM_CC, DL, MVT::i32));
175+
SDValue SRA = DAG.getNode(ISD::SRA, DL, MVT::i32, SHL,
176+
DAG.getConstant(30, DL, MVT::i32));
177+
return SRA;
178178
}
179179

180180
std::pair<SDValue, SDValue> SystemZSelectionDAGInfo::EmitTargetCodeForMemcmp(
@@ -184,7 +184,8 @@ std::pair<SDValue, SDValue> SystemZSelectionDAGInfo::EmitTargetCodeForMemcmp(
184184
if (auto *CSize = dyn_cast<ConstantSDNode>(Size)) {
185185
uint64_t Bytes = CSize->getZExtValue();
186186
assert(Bytes > 0 && "Caller should have handled 0-size case");
187-
SDValue CCReg = emitCLC(DAG, DL, Chain, Src1, Src2, Bytes);
187+
// Swap operands to invert CC == 1 vs. CC == 2 cases.
188+
SDValue CCReg = emitCLC(DAG, DL, Chain, Src2, Src1, Bytes);
188189
Chain = CCReg.getValue(1);
189190
return std::make_pair(addIPMSequence(DL, CCReg, DAG), Chain);
190191
}
@@ -232,7 +233,8 @@ std::pair<SDValue, SDValue> SystemZSelectionDAGInfo::EmitTargetCodeForStrcmp(
232233
SDValue Src2, MachinePointerInfo Op1PtrInfo,
233234
MachinePointerInfo Op2PtrInfo) const {
234235
SDVTList VTs = DAG.getVTList(Src1.getValueType(), MVT::i32, MVT::Other);
235-
SDValue Unused = DAG.getNode(SystemZISD::STRCMP, DL, VTs, Chain, Src1, Src2,
236+
// Swap operands to invert CC == 1 vs. CC == 2 cases.
237+
SDValue Unused = DAG.getNode(SystemZISD::STRCMP, DL, VTs, Chain, Src2, Src1,
236238
DAG.getConstant(0, DL, MVT::i32));
237239
SDValue CCReg = Unused.getValue(1);
238240
Chain = Unused.getValue(2);

0 commit comments

Comments
 (0)