Skip to content

Commit 1d18930

Browse files
authored
[SystemZ] Don't use FP Load and Test as comparisons to same reg (llvm#78074)
The usage of FP Load and Test instructions as a comparison against zero with the assumption that the dest reg will always reflect the source reg is actually incorrect: Unfortunately, a SNaN will be converted to a QNaN, so the instruction may actually change the value as opposed to being a pure register move with a test. This patch - changes instruction selection to always emit FP LT with a scratch def reg, which will typically be allocated to the same reg if dead. - Removes the conversions into FP LT in SystemZElimcompare.
1 parent 82e1e41 commit 1d18930

19 files changed

+168
-159
lines changed

llvm/lib/Target/SystemZ/SystemZElimCompare.cpp

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -115,12 +115,6 @@ static bool preservesValueOf(MachineInstr &MI, unsigned Reg) {
115115
case SystemZ::LTR:
116116
case SystemZ::LTGR:
117117
case SystemZ::LTGFR:
118-
case SystemZ::LER:
119-
case SystemZ::LDR:
120-
case SystemZ::LXR:
121-
case SystemZ::LTEBR:
122-
case SystemZ::LTDBR:
123-
case SystemZ::LTXBR:
124118
if (MI.getOperand(1).getReg() == Reg)
125119
return true;
126120
}
@@ -498,18 +492,10 @@ bool SystemZElimCompare::adjustCCMasksForInstr(
498492

499493
// Return true if Compare is a comparison against zero.
500494
static bool isCompareZero(MachineInstr &Compare) {
501-
switch (Compare.getOpcode()) {
502-
case SystemZ::LTEBRCompare:
503-
case SystemZ::LTDBRCompare:
504-
case SystemZ::LTXBRCompare:
495+
if (isLoadAndTestAsCmp(Compare))
505496
return true;
506-
507-
default:
508-
if (isLoadAndTestAsCmp(Compare))
509-
return true;
510-
return Compare.getNumExplicitOperands() == 2 &&
511-
Compare.getOperand(1).isImm() && Compare.getOperand(1).getImm() == 0;
512-
}
497+
return Compare.getNumExplicitOperands() == 2 &&
498+
Compare.getOperand(1).isImm() && Compare.getOperand(1).getImm() == 0;
513499
}
514500

515501
// Try to optimize cases where comparison instruction Compare is testing
@@ -569,7 +555,7 @@ bool SystemZElimCompare::optimizeCompareZero(
569555

570556
// Also do a forward search to handle cases where an instruction after the
571557
// compare can be converted, like
572-
// LTEBRCompare %f0s, %f0s; %f2s = LER %f0s => LTEBRCompare %f2s, %f0s
558+
// CGHI %r0d, 0; %r1d = LGR %r0d => LTGR %r1d, %r0d
573559
auto MIRange = llvm::make_range(
574560
std::next(MachineBasicBlock::iterator(&Compare)), MBB.end());
575561
for (MachineInstr &MI : llvm::make_early_inc_range(MIRange)) {

llvm/lib/Target/SystemZ/SystemZISelLowering.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9437,11 +9437,11 @@ MachineBasicBlock *SystemZTargetLowering::EmitInstrWithCustomInserter(
94379437
return emitTransactionBegin(MI, MBB, SystemZ::TBEGIN, true);
94389438
case SystemZ::TBEGINC:
94399439
return emitTransactionBegin(MI, MBB, SystemZ::TBEGINC, true);
9440-
case SystemZ::LTEBRCompare_VecPseudo:
9440+
case SystemZ::LTEBRCompare_Pseudo:
94419441
return emitLoadAndTestCmp0(MI, MBB, SystemZ::LTEBR);
9442-
case SystemZ::LTDBRCompare_VecPseudo:
9442+
case SystemZ::LTDBRCompare_Pseudo:
94439443
return emitLoadAndTestCmp0(MI, MBB, SystemZ::LTDBR);
9444-
case SystemZ::LTXBRCompare_VecPseudo:
9444+
case SystemZ::LTXBRCompare_Pseudo:
94459445
return emitLoadAndTestCmp0(MI, MBB, SystemZ::LTXBR);
94469446

94479447
case SystemZ::PROBED_ALLOCA:

llvm/lib/Target/SystemZ/SystemZInstrFP.td

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -51,36 +51,27 @@ let isCodeGenOnly = 1 in
5151
def LDR32 : UnaryRR<"ldr", 0x28, null_frag, FP32, FP32>;
5252

5353
// Moves between two floating-point registers that also set the condition
54-
// codes.
54+
// codes. Note that these instructions will turn SNaNs into QNaNs and should
55+
// not be used for comparison if the result will be used afterwards.
5556
let Uses = [FPC], mayRaiseFPException = 1,
5657
Defs = [CC], CCValues = 0xF, CompareZeroCCMask = 0xF in {
57-
defm LTEBR : LoadAndTestRRE<"ltebr", 0xB302, FP32>;
58-
defm LTDBR : LoadAndTestRRE<"ltdbr", 0xB312, FP64>;
59-
defm LTXBR : LoadAndTestRRE<"ltxbr", 0xB342, FP128>;
60-
}
61-
// Note that LTxBRCompare is not available if we have vector support,
62-
// since load-and-test instructions will partially clobber the target
63-
// (vector) register.
64-
let Predicates = [FeatureNoVector] in {
65-
defm : CompareZeroFP<LTEBRCompare, FP32>;
66-
defm : CompareZeroFP<LTDBRCompare, FP64>;
67-
defm : CompareZeroFP<LTXBRCompare, FP128>;
58+
def LTEBR : UnaryRRE<"ltebr", 0xB302, null_frag, FP32, FP32>;
59+
def LTDBR : UnaryRRE<"ltdbr", 0xB312, null_frag, FP64, FP64>;
60+
def LTXBR : UnaryRRE<"ltxbr", 0xB342, null_frag, FP128, FP128>;
6861
}
6962

70-
// Use a normal load-and-test for compare against zero in case of
71-
// vector support (via a pseudo to simplify instruction selection).
63+
// Use a load-and-test for compare against zero (via a pseudo to simplify
64+
// instruction selection).
7265
let Uses = [FPC], mayRaiseFPException = 1,
7366
Defs = [CC], usesCustomInserter = 1, hasNoSchedulingInfo = 1 in {
74-
def LTEBRCompare_VecPseudo : Pseudo<(outs), (ins FP32:$R1, FP32:$R2), []>;
75-
def LTDBRCompare_VecPseudo : Pseudo<(outs), (ins FP64:$R1, FP64:$R2), []>;
76-
def LTXBRCompare_VecPseudo : Pseudo<(outs), (ins FP128:$R1, FP128:$R2), []>;
77-
}
78-
let Predicates = [FeatureVector] in {
79-
defm : CompareZeroFP<LTEBRCompare_VecPseudo, FP32>;
80-
defm : CompareZeroFP<LTDBRCompare_VecPseudo, FP64>;
67+
def LTEBRCompare_Pseudo : Pseudo<(outs), (ins FP32:$R1), []>;
68+
def LTDBRCompare_Pseudo : Pseudo<(outs), (ins FP64:$R1), []>;
69+
def LTXBRCompare_Pseudo : Pseudo<(outs), (ins FP128:$R1), []>;
8170
}
82-
let Predicates = [FeatureVector, FeatureNoVectorEnhancements1] in
83-
defm : CompareZeroFP<LTXBRCompare_VecPseudo, FP128>;
71+
defm : CompareZeroFP<LTEBRCompare_Pseudo, FP32>;
72+
defm : CompareZeroFP<LTDBRCompare_Pseudo, FP64>;
73+
let Predicates = [FeatureNoVectorEnhancements1] in
74+
defm : CompareZeroFP<LTXBRCompare_Pseudo, FP128>;
8475

8576
// Moves between 64-bit integer and floating-point registers.
8677
def LGDR : UnaryRRE<"lgdr", 0xB3CD, bitconvert, GR64, FP64>;

llvm/lib/Target/SystemZ/SystemZInstrFormats.td

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5036,18 +5036,6 @@ class BranchPreloadMII<string mnemonic, bits<8> opcode>
50365036
(ins imm32zx4:$M1, brtarget12bpp:$RI2, brtarget24bpp:$RI3),
50375037
mnemonic#"\t$M1, $RI2, $RI3", []>;
50385038

5039-
// A floating-point load-and test operation. Create both a normal unary
5040-
// operation and one that acts as a comparison against zero.
5041-
// Note that the comparison against zero operation is not available if we
5042-
// have vector support, since load-and-test instructions will partially
5043-
// clobber the target (vector) register.
5044-
multiclass LoadAndTestRRE<string mnemonic, bits<16> opcode,
5045-
RegisterOperand cls> {
5046-
def "" : UnaryRRE<mnemonic, opcode, null_frag, cls, cls>;
5047-
let isCodeGenOnly = 1, Predicates = [FeatureNoVector] in
5048-
def Compare : CompareRRE<mnemonic, opcode, null_frag, cls, cls>;
5049-
}
5050-
50515039
//===----------------------------------------------------------------------===//
50525040
// Pseudo instructions
50535041
//===----------------------------------------------------------------------===//

llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1692,9 +1692,6 @@ unsigned SystemZInstrInfo::getLoadAndTest(unsigned Opcode) const {
16921692
case SystemZ::LR: return SystemZ::LTR;
16931693
case SystemZ::LGFR: return SystemZ::LTGFR;
16941694
case SystemZ::LGR: return SystemZ::LTGR;
1695-
case SystemZ::LER: return SystemZ::LTEBR;
1696-
case SystemZ::LDR: return SystemZ::LTDBR;
1697-
case SystemZ::LXR: return SystemZ::LTXBR;
16981695
case SystemZ::LCDFR: return SystemZ::LCDBR;
16991696
case SystemZ::LPDFR: return SystemZ::LPDBR;
17001697
case SystemZ::LNDFR: return SystemZ::LNDBR;

llvm/lib/Target/SystemZ/SystemZPatterns.td

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -145,12 +145,11 @@ multiclass BlockLoadStore<SDPatternOperator load, ValueType vt,
145145
}
146146

147147
// Record that INSN is a LOAD AND TEST that can be used to compare
148-
// registers in CLS against zero. The instruction has separate R1 and R2
149-
// operands, but they must be the same when the instruction is used like this.
148+
// registers in CLS against zero.
150149
multiclass CompareZeroFP<Instruction insn, RegisterOperand cls> {
151-
def : Pat<(z_any_fcmp cls:$reg, (fpimm0)), (insn cls:$reg, cls:$reg)>;
150+
def : Pat<(z_any_fcmp cls:$reg, (fpimm0)), (insn cls:$reg)>;
152151
// The sign of the zero makes no difference.
153-
def : Pat<(z_any_fcmp cls:$reg, (fpimmneg0)), (insn cls:$reg, cls:$reg)>;
152+
def : Pat<(z_any_fcmp cls:$reg, (fpimmneg0)), (insn cls:$reg)>;
154153
}
155154

156155
// Use INSN for performing binary operation OPERATION of type VT

llvm/lib/Target/SystemZ/SystemZScheduleZ13.td

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -784,9 +784,7 @@ def : InstRW<[WLat2, FXb2, GroupAlone], (instregex "LXR$")>;
784784

785785
// Load and Test
786786
def : InstRW<[WLat3, WLat3, VecXsPm, NormalGr], (instregex "LT(E|D)BR$")>;
787-
def : InstRW<[WLat3, VecXsPm, NormalGr], (instregex "LT(E|D)BRCompare$")>;
788-
def : InstRW<[WLat10, WLat10, VecDF4, GroupAlone],
789-
(instregex "LTXBR(Compare)?$")>;
787+
def : InstRW<[WLat10, WLat10, VecDF4, GroupAlone], (instregex "LTXBR$")>;
790788

791789
// Copy sign
792790
def : InstRW<[WLat2, VecXsPm, NormalGr], (instregex "CPSDR(d|s)(d|s)$")>;

llvm/lib/Target/SystemZ/SystemZScheduleZ14.td

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -804,9 +804,7 @@ def : InstRW<[WLat2, FXb2, GroupAlone], (instregex "LXR$")>;
804804

805805
// Load and Test
806806
def : InstRW<[WLat3, WLat3, VecXsPm, NormalGr], (instregex "LT(E|D)BR$")>;
807-
def : InstRW<[WLat3, VecXsPm, NormalGr], (instregex "LT(E|D)BRCompare$")>;
808-
def : InstRW<[WLat10, WLat10, VecDF4, GroupAlone],
809-
(instregex "LTXBR(Compare)?$")>;
807+
def : InstRW<[WLat10, WLat10, VecDF4, GroupAlone], (instregex "LTXBR$")>;
810808

811809
// Copy sign
812810
def : InstRW<[WLat2, VecXsPm, NormalGr], (instregex "CPSDR(d|s)(d|s)$")>;

llvm/lib/Target/SystemZ/SystemZScheduleZ15.td

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -821,9 +821,7 @@ def : InstRW<[WLat2, FXb2, GroupAlone], (instregex "LXR$")>;
821821

822822
// Load and Test
823823
def : InstRW<[WLat3, WLat3, VecXsPm, NormalGr], (instregex "LT(E|D)BR$")>;
824-
def : InstRW<[WLat3, VecXsPm, NormalGr], (instregex "LT(E|D)BRCompare$")>;
825-
def : InstRW<[WLat10, WLat10, VecDF4, GroupAlone],
826-
(instregex "LTXBR(Compare)?$")>;
824+
def : InstRW<[WLat10, WLat10, VecDF4, GroupAlone], (instregex "LTXBR$")>;
827825

828826
// Copy sign
829827
def : InstRW<[WLat2, VecXsPm, NormalGr], (instregex "CPSDR(d|s)(d|s)$")>;

llvm/lib/Target/SystemZ/SystemZScheduleZ16.td

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -822,9 +822,7 @@ def : InstRW<[WLat2, FXb2, GroupAlone], (instregex "LXR$")>;
822822

823823
// Load and Test
824824
def : InstRW<[WLat3, WLat3, VecXsPm, NormalGr], (instregex "LT(E|D)BR$")>;
825-
def : InstRW<[WLat3, VecXsPm, NormalGr], (instregex "LT(E|D)BRCompare$")>;
826-
def : InstRW<[WLat10, WLat10, VecDF4, GroupAlone],
827-
(instregex "LTXBR(Compare)?$")>;
825+
def : InstRW<[WLat10, WLat10, VecDF4, GroupAlone], (instregex "LTXBR$")>;
828826

829827
// Copy sign
830828
def : InstRW<[WLat2, VecXsPm, NormalGr], (instregex "CPSDR(d|s)(d|s)$")>;

0 commit comments

Comments
 (0)