Skip to content

Commit 586d5f9

Browse files
koachanbrad0
authored andcommitted
[SPARC] Improve integer branch handling for v9 targets
Do not emit deprecated v8-style branches when targeting a v9 processor. As a side effect, this also fixes the emission of useless ba's when doing conditional branches on 64-bit integer values. Reviewed By: arsenm Differential Revision: https://reviews.llvm.org/D130006
1 parent c3082e2 commit 586d5f9

File tree

9 files changed

+490
-218
lines changed

9 files changed

+490
-218
lines changed

llvm/lib/Target/Sparc/SparcISelLowering.cpp

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1928,7 +1928,10 @@ const char *SparcTargetLowering::getTargetNodeName(unsigned Opcode) const {
19281928
case SPISD::CMPICC: return "SPISD::CMPICC";
19291929
case SPISD::CMPFCC: return "SPISD::CMPFCC";
19301930
case SPISD::BRICC: return "SPISD::BRICC";
1931-
case SPISD::BRXCC: return "SPISD::BRXCC";
1931+
case SPISD::BPICC:
1932+
return "SPISD::BPICC";
1933+
case SPISD::BPXCC:
1934+
return "SPISD::BPXCC";
19321935
case SPISD::BRFCC: return "SPISD::BRFCC";
19331936
case SPISD::SELECT_ICC: return "SPISD::SELECT_ICC";
19341937
case SPISD::SELECT_XCC: return "SPISD::SELECT_XCC";
@@ -2533,8 +2536,8 @@ static SDValue LowerUINT_TO_FP(SDValue Op, SelectionDAG &DAG,
25332536
}
25342537

25352538
static SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG,
2536-
const SparcTargetLowering &TLI,
2537-
bool hasHardQuad) {
2539+
const SparcTargetLowering &TLI, bool hasHardQuad,
2540+
bool isV9) {
25382541
SDValue Chain = Op.getOperand(0);
25392542
ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get();
25402543
SDValue LHS = Op.getOperand(2);
@@ -2552,13 +2555,17 @@ static SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG,
25522555
if (LHS.getValueType().isInteger()) {
25532556
CompareFlag = DAG.getNode(SPISD::CMPICC, dl, MVT::Glue, LHS, RHS);
25542557
if (SPCC == ~0U) SPCC = IntCondCCodeToICC(CC);
2555-
// 32-bit compares use the icc flags, 64-bit uses the xcc flags.
2556-
Opc = LHS.getValueType() == MVT::i32 ? SPISD::BRICC : SPISD::BRXCC;
2558+
if (isV9)
2559+
// 32-bit compares use the icc flags, 64-bit uses the xcc flags.
2560+
Opc = LHS.getValueType() == MVT::i32 ? SPISD::BPICC : SPISD::BPXCC;
2561+
else
2562+
// Non-v9 targets don't have xcc.
2563+
Opc = SPISD::BRICC;
25572564
} else {
25582565
if (!hasHardQuad && LHS.getValueType() == MVT::f128) {
25592566
if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC);
25602567
CompareFlag = TLI.LowerF128Compare(LHS, RHS, SPCC, dl, DAG);
2561-
Opc = SPISD::BRICC;
2568+
Opc = isV9 ? SPISD::BPICC : SPISD::BRICC;
25622569
} else {
25632570
CompareFlag = DAG.getNode(SPISD::CMPFCC, dl, MVT::Glue, LHS, RHS);
25642571
if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC);
@@ -3141,8 +3148,8 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const {
31413148
hasHardQuad);
31423149
case ISD::UINT_TO_FP: return LowerUINT_TO_FP(Op, DAG, *this,
31433150
hasHardQuad);
3144-
case ISD::BR_CC: return LowerBR_CC(Op, DAG, *this,
3145-
hasHardQuad);
3151+
case ISD::BR_CC:
3152+
return LowerBR_CC(Op, DAG, *this, hasHardQuad, isV9);
31463153
case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG, *this,
31473154
hasHardQuad);
31483155
case ISD::VASTART: return LowerVASTART(Op, DAG, *this);
@@ -3221,6 +3228,8 @@ SparcTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
32213228
case SP::SELECT_CC_FP_ICC:
32223229
case SP::SELECT_CC_DFP_ICC:
32233230
case SP::SELECT_CC_QFP_ICC:
3231+
if (Subtarget->isV9())
3232+
return expandSelectCC(MI, BB, SP::BPICC);
32243233
return expandSelectCC(MI, BB, SP::BCOND);
32253234
case SP::SELECT_CC_Int_XCC:
32263235
case SP::SELECT_CC_FP_XCC:

llvm/lib/Target/Sparc/SparcISelLowering.h

Lines changed: 33 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -21,37 +21,39 @@ namespace llvm {
2121
class SparcSubtarget;
2222

2323
namespace SPISD {
24-
enum NodeType : unsigned {
25-
FIRST_NUMBER = ISD::BUILTIN_OP_END,
26-
CMPICC, // Compare two GPR operands, set icc+xcc.
27-
CMPFCC, // Compare two FP operands, set fcc.
28-
BRICC, // Branch to dest on icc condition
29-
BRXCC, // Branch to dest on xcc condition (64-bit only).
30-
BRFCC, // Branch to dest on fcc condition
31-
SELECT_ICC, // Select between two values using the current ICC flags.
32-
SELECT_XCC, // Select between two values using the current XCC flags.
33-
SELECT_FCC, // Select between two values using the current FCC flags.
34-
35-
Hi, Lo, // Hi/Lo operations, typically on a global address.
36-
37-
FTOI, // FP to Int within a FP register.
38-
ITOF, // Int to FP within a FP register.
39-
FTOX, // FP to Int64 within a FP register.
40-
XTOF, // Int64 to FP within a FP register.
41-
42-
CALL, // A call instruction.
43-
RET_FLAG, // Return with a flag operand.
44-
GLOBAL_BASE_REG, // Global base reg for PIC.
45-
FLUSHW, // FLUSH register windows to stack.
46-
47-
TAIL_CALL, // Tail call
48-
49-
TLS_ADD, // For Thread Local Storage (TLS).
50-
TLS_LD,
51-
TLS_CALL,
52-
53-
LOAD_GDOP, // Load operation w/ gdop relocation.
54-
};
24+
enum NodeType : unsigned {
25+
FIRST_NUMBER = ISD::BUILTIN_OP_END,
26+
CMPICC, // Compare two GPR operands, set icc+xcc.
27+
CMPFCC, // Compare two FP operands, set fcc.
28+
BRICC, // Branch to dest on icc condition
29+
BPICC, // Branch to dest on icc condition, with prediction (64-bit only).
30+
BPXCC, // Branch to dest on xcc condition, with prediction (64-bit only).
31+
BRFCC, // Branch to dest on fcc condition
32+
SELECT_ICC, // Select between two values using the current ICC flags.
33+
SELECT_XCC, // Select between two values using the current XCC flags.
34+
SELECT_FCC, // Select between two values using the current FCC flags.
35+
36+
Hi,
37+
Lo, // Hi/Lo operations, typically on a global address.
38+
39+
FTOI, // FP to Int within a FP register.
40+
ITOF, // Int to FP within a FP register.
41+
FTOX, // FP to Int64 within a FP register.
42+
XTOF, // Int64 to FP within a FP register.
43+
44+
CALL, // A call instruction.
45+
RET_FLAG, // Return with a flag operand.
46+
GLOBAL_BASE_REG, // Global base reg for PIC.
47+
FLUSHW, // FLUSH register windows to stack.
48+
49+
TAIL_CALL, // Tail call
50+
51+
TLS_ADD, // For Thread Local Storage (TLS).
52+
TLS_LD,
53+
TLS_CALL,
54+
55+
LOAD_GDOP, // Load operation w/ gdop relocation.
56+
};
5557
}
5658

5759
class SparcTargetLowering : public TargetLowering {

llvm/lib/Target/Sparc/SparcInstr64Bit.td

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -310,13 +310,13 @@ def : Pat<(store (i64 0), ADDRri:$dst), (STXri ADDRri:$dst, (i64 G0))>;
310310
// The icc flags correspond to the 32-bit result, and the xcc are for the
311311
// full 64-bit result.
312312
//
313-
// We reuse CMPICC SDNodes for compares, but use new BRXCC branch nodes for
313+
// We reuse CMPICC SDNodes for compares, but use new BPXCC branch nodes for
314314
// 64-bit compares. See LowerBR_CC.
315315

316316
let Predicates = [Is64Bit] in {
317317

318318
let Uses = [ICC], cc = 0b10 in
319-
defm BPX : IPredBranch<"%xcc", [(SPbrxcc bb:$imm19, imm:$cond)]>;
319+
defm BPX : IPredBranch<"%xcc", [(SPbpxcc bb:$imm19, imm:$cond)]>;
320320

321321
// Conditional moves on %xcc.
322322
let Uses = [ICC], Constraints = "$f = $rd" in {

llvm/lib/Target/Sparc/SparcInstrInfo.cpp

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -140,10 +140,25 @@ static SPCC::CondCodes GetOppositeBranchCondition(SPCC::CondCodes CC)
140140
llvm_unreachable("Invalid cond code");
141141
}
142142

143-
static bool isUncondBranchOpcode(int Opc) { return Opc == SP::BA; }
143+
static bool isUncondBranchOpcode(int Opc) {
144+
return Opc == SP::BA || Opc == SP::BPA;
145+
}
146+
147+
static bool isI32CondBranchOpcode(int Opc) {
148+
return Opc == SP::BCOND || Opc == SP::BPICC || Opc == SP::BPICCA ||
149+
Opc == SP::BPICCNT || Opc == SP::BPICCANT;
150+
}
151+
152+
static bool isI64CondBranchOpcode(int Opc) {
153+
return Opc == SP::BPXCC || Opc == SP::BPXCCA || Opc == SP::BPXCCNT ||
154+
Opc == SP::BPXCCANT;
155+
}
156+
157+
static bool isFCondBranchOpcode(int Opc) { return Opc == SP::FBCOND; }
144158

145159
static bool isCondBranchOpcode(int Opc) {
146-
return Opc == SP::FBCOND || Opc == SP::BCOND;
160+
return isI32CondBranchOpcode(Opc) || isI64CondBranchOpcode(Opc) ||
161+
isFCondBranchOpcode(Opc);
147162
}
148163

149164
static bool isIndirectBranchOpcode(int Opc) {
@@ -152,7 +167,14 @@ static bool isIndirectBranchOpcode(int Opc) {
152167

153168
static void parseCondBranch(MachineInstr *LastInst, MachineBasicBlock *&Target,
154169
SmallVectorImpl<MachineOperand> &Cond) {
155-
Cond.push_back(MachineOperand::CreateImm(LastInst->getOperand(1).getImm()));
170+
unsigned Opc = LastInst->getOpcode();
171+
int64_t CC = LastInst->getOperand(1).getImm();
172+
173+
// Push the branch opcode into Cond too so later in insertBranch
174+
// it can use the information to emit the correct SPARC branch opcode.
175+
Cond.push_back(MachineOperand::CreateImm(Opc));
176+
Cond.push_back(MachineOperand::CreateImm(CC));
177+
156178
Target = LastInst->getOperand(0).getMBB();
157179
}
158180

@@ -246,27 +268,29 @@ unsigned SparcInstrInfo::insertBranch(MachineBasicBlock &MBB,
246268
const DebugLoc &DL,
247269
int *BytesAdded) const {
248270
assert(TBB && "insertBranch must not be told to insert a fallthrough");
249-
assert((Cond.size() == 1 || Cond.size() == 0) &&
250-
"Sparc branch conditions should have one component!");
271+
assert((Cond.size() <= 2) &&
272+
"Sparc branch conditions should have at most two components!");
251273
assert(!BytesAdded && "code size not handled");
252274

253275
if (Cond.empty()) {
254276
assert(!FBB && "Unconditional branch with multiple successors!");
255-
BuildMI(&MBB, DL, get(SP::BA)).addMBB(TBB);
277+
BuildMI(&MBB, DL, get(Subtarget.isV9() ? SP::BPA : SP::BA)).addMBB(TBB);
256278
return 1;
257279
}
258280

259281
// Conditional branch
260-
unsigned CC = Cond[0].getImm();
282+
unsigned Opc = Cond[0].getImm();
283+
unsigned CC = Cond[1].getImm();
261284

262-
if (IsIntegerCC(CC))
263-
BuildMI(&MBB, DL, get(SP::BCOND)).addMBB(TBB).addImm(CC);
264-
else
285+
if (IsIntegerCC(CC)) {
286+
BuildMI(&MBB, DL, get(Opc)).addMBB(TBB).addImm(CC);
287+
} else {
265288
BuildMI(&MBB, DL, get(SP::FBCOND)).addMBB(TBB).addImm(CC);
289+
}
266290
if (!FBB)
267291
return 1;
268292

269-
BuildMI(&MBB, DL, get(SP::BA)).addMBB(FBB);
293+
BuildMI(&MBB, DL, get(Subtarget.isV9() ? SP::BPA : SP::BA)).addMBB(FBB);
270294
return 2;
271295
}
272296

@@ -282,9 +306,8 @@ unsigned SparcInstrInfo::removeBranch(MachineBasicBlock &MBB,
282306
if (I->isDebugInstr())
283307
continue;
284308

285-
if (I->getOpcode() != SP::BA
286-
&& I->getOpcode() != SP::BCOND
287-
&& I->getOpcode() != SP::FBCOND)
309+
if (!isCondBranchOpcode(I->getOpcode()) &&
310+
!isUncondBranchOpcode(I->getOpcode()))
288311
break; // Not a branch
289312

290313
I->eraseFromParent();
@@ -296,9 +319,9 @@ unsigned SparcInstrInfo::removeBranch(MachineBasicBlock &MBB,
296319

297320
bool SparcInstrInfo::reverseBranchCondition(
298321
SmallVectorImpl<MachineOperand> &Cond) const {
299-
assert(Cond.size() == 1);
300-
SPCC::CondCodes CC = static_cast<SPCC::CondCodes>(Cond[0].getImm());
301-
Cond[0].setImm(GetOppositeBranchCondition(CC));
322+
assert(Cond.size() <= 2);
323+
SPCC::CondCodes CC = static_cast<SPCC::CondCodes>(Cond[1].getImm());
324+
Cond[1].setImm(GetOppositeBranchCondition(CC));
302325
return false;
303326
}
304327

llvm/lib/Target/Sparc/SparcInstrInfo.td

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,8 @@ SDTypeProfile<1, 2, [SDTCisPtrTy<0>, SDTCisPtrTy<1>]>;
242242
def SPcmpicc : SDNode<"SPISD::CMPICC", SDTSPcmpicc, [SDNPOutGlue]>;
243243
def SPcmpfcc : SDNode<"SPISD::CMPFCC", SDTSPcmpfcc, [SDNPOutGlue]>;
244244
def SPbricc : SDNode<"SPISD::BRICC", SDTSPbrcc, [SDNPHasChain, SDNPInGlue]>;
245-
def SPbrxcc : SDNode<"SPISD::BRXCC", SDTSPbrcc, [SDNPHasChain, SDNPInGlue]>;
245+
def SPbpicc : SDNode<"SPISD::BPICC", SDTSPbrcc, [SDNPHasChain, SDNPInGlue]>;
246+
def SPbpxcc : SDNode<"SPISD::BPXCC", SDTSPbrcc, [SDNPHasChain, SDNPInGlue]>;
246247
def SPbrfcc : SDNode<"SPISD::BRFCC", SDTSPbrcc, [SDNPHasChain, SDNPInGlue]>;
247248

248249
def SPhi : SDNode<"SPISD::Hi", SDTIntUnaryOp>;
@@ -845,19 +846,27 @@ defm SAVE : F3_12np<"save" , 0b111100>;
845846
defm RESTORE : F3_12np<"restore", 0b111101>;
846847

847848
// Section B.21 - Branch on Integer Condition Codes Instructions, p. 119
849+
// Section A.7 - Branch on Integer Condition Codes with Prediction (SPARC v9)
848850

851+
let isBranch = 1, isTerminator = 1, hasDelaySlot = 1, isBarrier = 1 in {
849852
// unconditional branch class.
850853
class BranchAlways<dag ins, string asmstr, list<dag> pattern>
851-
: F2_2<0b010, 0, (outs), ins, asmstr, pattern> {
852-
let isBranch = 1;
853-
let isTerminator = 1;
854-
let hasDelaySlot = 1;
855-
let isBarrier = 1;
854+
: F2_2<0b010, 0, (outs), ins, asmstr, pattern>;
855+
856+
// Same as BranchAlways but uses the new v9 encoding
857+
class BranchPredictAlways<dag ins, string asmstr, list<dag> pattern>
858+
: F2_3<0b001, 0, 1, (outs), ins, asmstr, pattern>;
856859
}
857860

858-
let cond = 8 in
859-
def BA : BranchAlways<(ins brtarget:$imm22), "ba $imm22", [(br bb:$imm22)]>;
861+
let cond = 8 in {
862+
// If we're compiling for v9, prefer BPA rather than BA
863+
// TODO: Disallow BA emission when FeatureV8Deprecated isn't enabled
864+
let Predicates = [HasV9], cc = 0b00 in
865+
def BPA : BranchPredictAlways<(ins bprtarget:$imm19),
866+
"ba %icc, $imm19", [(br bb:$imm19)]>;
860867

868+
def BA : BranchAlways<(ins brtarget:$imm22), "ba $imm22", [(br bb:$imm22)]>;
869+
}
861870

862871
let isBranch = 1, isTerminator = 1, hasDelaySlot = 1 in {
863872

@@ -913,7 +922,7 @@ let Uses = [ICC] in {
913922
"b$cond,a $imm22", []>;
914923

915924
let Predicates = [HasV9], cc = 0b00 in
916-
defm BPI : IPredBranch<"%icc", []>;
925+
defm BPI : IPredBranch<"%icc", [(SPbpicc bb:$imm19, imm:$cond)]>;
917926
}
918927

919928
// Section B.22 - Branch on Floating-point Condition Codes Instructions, p. 121

0 commit comments

Comments
 (0)