Skip to content

Commit 77caeda

Browse files
committed
[AArch64][FEAT_CMPBR] Codegen for Armv9.6-a CBB and CBH
This patch adds codegen for CBB and CBH, CB variants operating on bytes and half-words, allowing to fold sign- and zero-extensions. Since if-conversion needs to be able to undo conditional branches, we remember possibly folded zero- and sign-extensions, as well as potentially folded assertzext and assertsext as additional arguments of the CBBAssertExt and CBHAssertExt pseudos during codegen.
1 parent a2977de commit 77caeda

File tree

9 files changed

+1582
-139
lines changed

9 files changed

+1582
-139
lines changed

llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp

Lines changed: 36 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2677,23 +2677,32 @@ AArch64AsmPrinter::lowerBlockAddressConstant(const BlockAddress &BA) {
26772677

26782678
void AArch64AsmPrinter::emitCBPseudoExpansion(const MachineInstr *MI) {
26792679
bool IsImm = false;
2680-
bool Is32Bit = false;
2680+
unsigned Width = 0;
26812681

26822682
switch (MI->getOpcode()) {
26832683
default:
26842684
llvm_unreachable("This is not a CB pseudo instruction");
2685+
case AArch64::CBBAssertExt:
2686+
IsImm = false;
2687+
Width = 8;
2688+
break;
2689+
case AArch64::CBHAssertExt:
2690+
IsImm = false;
2691+
Width = 16;
2692+
break;
26852693
case AArch64::CBWPrr:
2686-
Is32Bit = true;
2694+
Width = 32;
26872695
break;
26882696
case AArch64::CBXPrr:
2689-
Is32Bit = false;
2697+
Width = 64;
26902698
break;
26912699
case AArch64::CBWPri:
26922700
IsImm = true;
2693-
Is32Bit = true;
2701+
Width = 32;
26942702
break;
26952703
case AArch64::CBXPri:
26962704
IsImm = true;
2705+
Width = 64;
26972706
break;
26982707
}
26992708

@@ -2703,61 +2712,61 @@ void AArch64AsmPrinter::emitCBPseudoExpansion(const MachineInstr *MI) {
27032712
bool NeedsImmDec = false;
27042713
bool NeedsImmInc = false;
27052714

2715+
#define GET_CB_OPC(IsImm, Width, ImmCond, RegCond) \
2716+
(IsImm \
2717+
? (Width == 32 ? AArch64::CB##ImmCond##Wri : AArch64::CB##ImmCond##Xri) \
2718+
: (Width == 8 \
2719+
? AArch64::CBB##RegCond##Wrr \
2720+
: (Width == 16 ? AArch64::CBH##RegCond##Wrr \
2721+
: (Width == 32 ? AArch64::CB##RegCond##Wrr \
2722+
: AArch64::CB##RegCond##Xrr))))
2723+
unsigned MCOpC;
2724+
27062725
// Decide if we need to either swap register operands or increment/decrement
27072726
// immediate operands
2708-
unsigned MCOpC;
27092727
switch (CC) {
27102728
default:
27112729
llvm_unreachable("Invalid CB condition code");
27122730
case AArch64CC::EQ:
2713-
MCOpC = IsImm ? (Is32Bit ? AArch64::CBEQWri : AArch64::CBEQXri)
2714-
: (Is32Bit ? AArch64::CBEQWrr : AArch64::CBEQXrr);
2731+
MCOpC = GET_CB_OPC(IsImm, Width, /* Reg-Imm */ EQ, /* Reg-Reg */ EQ);
27152732
break;
27162733
case AArch64CC::NE:
2717-
MCOpC = IsImm ? (Is32Bit ? AArch64::CBNEWri : AArch64::CBNEXri)
2718-
: (Is32Bit ? AArch64::CBNEWrr : AArch64::CBNEXrr);
2734+
MCOpC = GET_CB_OPC(IsImm, Width, /* Reg-Imm */ NE, /* Reg-Reg */ NE);
27192735
break;
27202736
case AArch64CC::HS:
2721-
MCOpC = IsImm ? (Is32Bit ? AArch64::CBHIWri : AArch64::CBHIXri)
2722-
: (Is32Bit ? AArch64::CBHSWrr : AArch64::CBHSXrr);
2737+
MCOpC = GET_CB_OPC(IsImm, Width, /* Reg-Imm */ HI, /* Reg-Reg */ HS);
27232738
NeedsImmDec = IsImm;
27242739
break;
27252740
case AArch64CC::LO:
2726-
MCOpC = IsImm ? (Is32Bit ? AArch64::CBLOWri : AArch64::CBLOXri)
2727-
: (Is32Bit ? AArch64::CBHIWrr : AArch64::CBHIXrr);
2741+
MCOpC = GET_CB_OPC(IsImm, Width, /* Reg-Imm */ LO, /* Reg-Reg */ HI);
27282742
NeedsRegSwap = !IsImm;
27292743
break;
27302744
case AArch64CC::HI:
2731-
MCOpC = IsImm ? (Is32Bit ? AArch64::CBHIWri : AArch64::CBHIXri)
2732-
: (Is32Bit ? AArch64::CBHIWrr : AArch64::CBHIXrr);
2745+
MCOpC = GET_CB_OPC(IsImm, Width, /* Reg-Imm */ HI, /* Reg-Reg */ HI);
27332746
break;
27342747
case AArch64CC::LS:
2735-
MCOpC = IsImm ? (Is32Bit ? AArch64::CBLOWri : AArch64::CBLOXri)
2736-
: (Is32Bit ? AArch64::CBHSWrr : AArch64::CBHSXrr);
2748+
MCOpC = GET_CB_OPC(IsImm, Width, /* Reg-Imm */ LO, /* Reg-Reg */ HS);
27372749
NeedsRegSwap = !IsImm;
27382750
NeedsImmInc = IsImm;
27392751
break;
27402752
case AArch64CC::GE:
2741-
MCOpC = IsImm ? (Is32Bit ? AArch64::CBGTWri : AArch64::CBGTXri)
2742-
: (Is32Bit ? AArch64::CBGEWrr : AArch64::CBGEXrr);
2753+
MCOpC = GET_CB_OPC(IsImm, Width, /* Reg-Imm */ GT, /* Reg-Reg */ GE);
27432754
NeedsImmDec = IsImm;
27442755
break;
27452756
case AArch64CC::LT:
2746-
MCOpC = IsImm ? (Is32Bit ? AArch64::CBLTWri : AArch64::CBLTXri)
2747-
: (Is32Bit ? AArch64::CBGTWrr : AArch64::CBGTXrr);
2757+
MCOpC = GET_CB_OPC(IsImm, Width, /* Reg-Imm */ LT, /* Reg-Reg */ GT);
27482758
NeedsRegSwap = !IsImm;
27492759
break;
27502760
case AArch64CC::GT:
2751-
MCOpC = IsImm ? (Is32Bit ? AArch64::CBGTWri : AArch64::CBGTXri)
2752-
: (Is32Bit ? AArch64::CBGTWrr : AArch64::CBGTXrr);
2761+
MCOpC = GET_CB_OPC(IsImm, Width, /* Reg-Imm */ GT, /* Reg-Reg */ GT);
27532762
break;
27542763
case AArch64CC::LE:
2755-
MCOpC = IsImm ? (Is32Bit ? AArch64::CBLTWri : AArch64::CBLTXri)
2756-
: (Is32Bit ? AArch64::CBGEWrr : AArch64::CBGEXrr);
2764+
MCOpC = GET_CB_OPC(IsImm, Width, /* Reg-Imm */ LT, /* Reg-Reg */ GE);
27572765
NeedsRegSwap = !IsImm;
27582766
NeedsImmInc = IsImm;
27592767
break;
27602768
}
2769+
#undef GET_CB_OPC
27612770

27622771
MCInst Inst;
27632772
Inst.setOpcode(MCOpC);
@@ -3422,6 +3431,8 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
34223431
}
34233432
case AArch64::CBWPri:
34243433
case AArch64::CBXPri:
3434+
case AArch64::CBBAssertExt:
3435+
case AArch64::CBHAssertExt:
34253436
case AArch64::CBWPrr:
34263437
case AArch64::CBXPrr:
34273438
emitCBPseudoExpansion(MI);

llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,9 @@ class AArch64DAGToDAGISel : public SelectionDAGISel {
513513
bool SelectAnyPredicate(SDValue N);
514514

515515
bool SelectCmpBranchUImm6Operand(SDNode *P, SDValue N, SDValue &Imm);
516+
517+
template <bool MatchCBB>
518+
bool SelectCmpBranchExtOperand(SDValue N, SDValue &Reg, SDValue &ExtType);
516519
};
517520

518521
class AArch64DAGToDAGISelLegacy : public SelectionDAGISelLegacy {
@@ -7697,3 +7700,31 @@ bool AArch64DAGToDAGISel::SelectCmpBranchUImm6Operand(SDNode *P, SDValue N,
76977700

76987701
return false;
76997702
}
7703+
7704+
template <bool MatchCBB>
7705+
bool AArch64DAGToDAGISel::SelectCmpBranchExtOperand(SDValue N, SDValue &Reg,
7706+
SDValue &ExtType) {
7707+
7708+
// Use an invalid shift-extend value to indicate we don't need to extend later
7709+
if (N.getOpcode() == ISD::AssertZext || N.getOpcode() == ISD::AssertSext) {
7710+
EVT Ty = cast<VTSDNode>(N.getOperand(1))->getVT();
7711+
if ((MatchCBB && Ty != MVT::i8) || (!MatchCBB && Ty != MVT::i16))
7712+
return false;
7713+
Reg = N.getOperand(0);
7714+
ExtType = CurDAG->getSignedTargetConstant(AArch64_AM::InvalidShiftExtend,
7715+
SDLoc(N), MVT::i32);
7716+
return true;
7717+
}
7718+
7719+
AArch64_AM::ShiftExtendType ET = getExtendTypeForNode(N);
7720+
7721+
if ((MatchCBB && (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB)) ||
7722+
(!MatchCBB && (ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH))) {
7723+
Reg = N.getOperand(0);
7724+
ExtType =
7725+
CurDAG->getTargetConstant(getExtendEncoding(ET), SDLoc(N), MVT::i32);
7726+
return true;
7727+
}
7728+
7729+
return false;
7730+
}

llvm/lib/Target/AArch64/AArch64InstrFormats.td

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,12 @@ def CmpBranchUImm6Operand_64b
415415
let WantsParent = true;
416416
}
417417

418+
def CmpBranchBExtOperand
419+
: ComplexPattern<i32, 2, "SelectCmpBranchExtOperand<true>", []> {}
420+
421+
def CmpBranchHExtOperand
422+
: ComplexPattern<i32, 2, "SelectCmpBranchExtOperand<false>", []> {}
423+
418424
def UImm6Plus1Operand : AsmOperandClass {
419425
let Name = "UImm6P1";
420426
let DiagnosticType = "InvalidImm1_64";
@@ -13198,8 +13204,22 @@ multiclass CmpBranchRegisterAlias<string mnemonic, string insn> {
1319813204
}
1319913205

1320013206
class CmpBranchRegisterPseudo<RegisterClass regtype>
13201-
: Pseudo<(outs), (ins ccode:$Cond, regtype:$Rt, regtype:$Rm, am_brcmpcond:$Target), []>,
13202-
Sched<[WriteBr]> {
13207+
: Pseudo<(outs),
13208+
(ins ccode:$Cond, regtype:$Rt, regtype:$Rm, am_brcmpcond:$Target),
13209+
[]>,
13210+
Sched<[WriteBr]> {
13211+
let isBranch = 1;
13212+
let isTerminator = 1;
13213+
}
13214+
13215+
// Cmpbr pseudo instruction, encoding potentially folded zero-, sign-extension,
13216+
// assertzext and/or assersext.
13217+
class CmpBranchExtRegisterPseudo
13218+
: Pseudo<(outs),
13219+
(ins ccode:$Cond, GPR32:$Rt, GPR32:$Rm, am_brcmpcond:$Target,
13220+
simm8_32b:$ExtRt, simm8_32b:$ExtRm),
13221+
[]>,
13222+
Sched<[WriteBr]> {
1320313223
let isBranch = 1;
1320413224
let isTerminator = 1;
1320513225
}

0 commit comments

Comments
 (0)