Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 36 additions & 25 deletions llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2677,23 +2677,32 @@ AArch64AsmPrinter::lowerBlockAddressConstant(const BlockAddress &BA) {

void AArch64AsmPrinter::emitCBPseudoExpansion(const MachineInstr *MI) {
bool IsImm = false;
bool Is32Bit = false;
unsigned Width = 0;

switch (MI->getOpcode()) {
default:
llvm_unreachable("This is not a CB pseudo instruction");
case AArch64::CBBAssertExt:
IsImm = false;
Width = 8;
break;
case AArch64::CBHAssertExt:
IsImm = false;
Width = 16;
break;
case AArch64::CBWPrr:
Is32Bit = true;
Width = 32;
break;
case AArch64::CBXPrr:
Is32Bit = false;
Width = 64;
break;
case AArch64::CBWPri:
IsImm = true;
Is32Bit = true;
Width = 32;
break;
case AArch64::CBXPri:
IsImm = true;
Width = 64;
break;
}

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

#define GET_CB_OPC(IsImm, Width, ImmCond, RegCond) \
(IsImm \
? (Width == 32 ? AArch64::CB##ImmCond##Wri : AArch64::CB##ImmCond##Xri) \
: (Width == 8 \
? AArch64::CBB##RegCond##Wrr \
: (Width == 16 ? AArch64::CBH##RegCond##Wrr \
: (Width == 32 ? AArch64::CB##RegCond##Wrr \
: AArch64::CB##RegCond##Xrr))))
unsigned MCOpC;

// Decide if we need to either swap register operands or increment/decrement
// immediate operands
unsigned MCOpC;
switch (CC) {
default:
llvm_unreachable("Invalid CB condition code");
case AArch64CC::EQ:
MCOpC = IsImm ? (Is32Bit ? AArch64::CBEQWri : AArch64::CBEQXri)
: (Is32Bit ? AArch64::CBEQWrr : AArch64::CBEQXrr);
MCOpC = GET_CB_OPC(IsImm, Width, /* Reg-Imm */ EQ, /* Reg-Reg */ EQ);
break;
case AArch64CC::NE:
MCOpC = IsImm ? (Is32Bit ? AArch64::CBNEWri : AArch64::CBNEXri)
: (Is32Bit ? AArch64::CBNEWrr : AArch64::CBNEXrr);
MCOpC = GET_CB_OPC(IsImm, Width, /* Reg-Imm */ NE, /* Reg-Reg */ NE);
break;
case AArch64CC::HS:
MCOpC = IsImm ? (Is32Bit ? AArch64::CBHIWri : AArch64::CBHIXri)
: (Is32Bit ? AArch64::CBHSWrr : AArch64::CBHSXrr);
MCOpC = GET_CB_OPC(IsImm, Width, /* Reg-Imm */ HI, /* Reg-Reg */ HS);
NeedsImmDec = IsImm;
break;
case AArch64CC::LO:
MCOpC = IsImm ? (Is32Bit ? AArch64::CBLOWri : AArch64::CBLOXri)
: (Is32Bit ? AArch64::CBHIWrr : AArch64::CBHIXrr);
MCOpC = GET_CB_OPC(IsImm, Width, /* Reg-Imm */ LO, /* Reg-Reg */ HI);
NeedsRegSwap = !IsImm;
break;
case AArch64CC::HI:
MCOpC = IsImm ? (Is32Bit ? AArch64::CBHIWri : AArch64::CBHIXri)
: (Is32Bit ? AArch64::CBHIWrr : AArch64::CBHIXrr);
MCOpC = GET_CB_OPC(IsImm, Width, /* Reg-Imm */ HI, /* Reg-Reg */ HI);
break;
case AArch64CC::LS:
MCOpC = IsImm ? (Is32Bit ? AArch64::CBLOWri : AArch64::CBLOXri)
: (Is32Bit ? AArch64::CBHSWrr : AArch64::CBHSXrr);
MCOpC = GET_CB_OPC(IsImm, Width, /* Reg-Imm */ LO, /* Reg-Reg */ HS);
NeedsRegSwap = !IsImm;
NeedsImmInc = IsImm;
break;
case AArch64CC::GE:
MCOpC = IsImm ? (Is32Bit ? AArch64::CBGTWri : AArch64::CBGTXri)
: (Is32Bit ? AArch64::CBGEWrr : AArch64::CBGEXrr);
MCOpC = GET_CB_OPC(IsImm, Width, /* Reg-Imm */ GT, /* Reg-Reg */ GE);
NeedsImmDec = IsImm;
break;
case AArch64CC::LT:
MCOpC = IsImm ? (Is32Bit ? AArch64::CBLTWri : AArch64::CBLTXri)
: (Is32Bit ? AArch64::CBGTWrr : AArch64::CBGTXrr);
MCOpC = GET_CB_OPC(IsImm, Width, /* Reg-Imm */ LT, /* Reg-Reg */ GT);
NeedsRegSwap = !IsImm;
break;
case AArch64CC::GT:
MCOpC = IsImm ? (Is32Bit ? AArch64::CBGTWri : AArch64::CBGTXri)
: (Is32Bit ? AArch64::CBGTWrr : AArch64::CBGTXrr);
MCOpC = GET_CB_OPC(IsImm, Width, /* Reg-Imm */ GT, /* Reg-Reg */ GT);
break;
case AArch64CC::LE:
MCOpC = IsImm ? (Is32Bit ? AArch64::CBLTWri : AArch64::CBLTXri)
: (Is32Bit ? AArch64::CBGEWrr : AArch64::CBGEXrr);
MCOpC = GET_CB_OPC(IsImm, Width, /* Reg-Imm */ LT, /* Reg-Reg */ GE);
NeedsRegSwap = !IsImm;
NeedsImmInc = IsImm;
break;
}
#undef GET_CB_OPC

MCInst Inst;
Inst.setOpcode(MCOpC);
Expand Down Expand Up @@ -3422,6 +3431,8 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
}
case AArch64::CBWPri:
case AArch64::CBXPri:
case AArch64::CBBAssertExt:
case AArch64::CBHAssertExt:
case AArch64::CBWPrr:
case AArch64::CBXPrr:
emitCBPseudoExpansion(MI);
Expand Down
31 changes: 31 additions & 0 deletions llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,9 @@ class AArch64DAGToDAGISel : public SelectionDAGISel {
bool SelectAnyPredicate(SDValue N);

bool SelectCmpBranchUImm6Operand(SDNode *P, SDValue N, SDValue &Imm);

template <bool MatchCBB>
bool SelectCmpBranchExtOperand(SDValue N, SDValue &Reg, SDValue &ExtType);
};

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

return false;
}

template <bool MatchCBB>
bool AArch64DAGToDAGISel::SelectCmpBranchExtOperand(SDValue N, SDValue &Reg,
SDValue &ExtType) {

// Use an invalid shift-extend value to indicate we don't need to extend later
if (N.getOpcode() == ISD::AssertZext || N.getOpcode() == ISD::AssertSext) {
EVT Ty = cast<VTSDNode>(N.getOperand(1))->getVT();
if ((MatchCBB && Ty != MVT::i8) || (!MatchCBB && Ty != MVT::i16))
return false;
Reg = N.getOperand(0);
ExtType = CurDAG->getSignedTargetConstant(AArch64_AM::InvalidShiftExtend,
SDLoc(N), MVT::i32);
return true;
}

AArch64_AM::ShiftExtendType ET = getExtendTypeForNode(N);

if ((MatchCBB && (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB)) ||
(!MatchCBB && (ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH))) {
Reg = N.getOperand(0);
ExtType =
CurDAG->getTargetConstant(getExtendEncoding(ET), SDLoc(N), MVT::i32);
return true;
}

return false;
}
24 changes: 22 additions & 2 deletions llvm/lib/Target/AArch64/AArch64InstrFormats.td
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,12 @@ def CmpBranchUImm6Operand_64b
let WantsParent = true;
}

def CmpBranchBExtOperand
: ComplexPattern<i32, 2, "SelectCmpBranchExtOperand<true>", []> {}

def CmpBranchHExtOperand
: ComplexPattern<i32, 2, "SelectCmpBranchExtOperand<false>", []> {}

def UImm6Plus1Operand : AsmOperandClass {
let Name = "UImm6P1";
let DiagnosticType = "InvalidImm1_64";
Expand Down Expand Up @@ -13198,8 +13204,22 @@ multiclass CmpBranchRegisterAlias<string mnemonic, string insn> {
}

class CmpBranchRegisterPseudo<RegisterClass regtype>
: Pseudo<(outs), (ins ccode:$Cond, regtype:$Rt, regtype:$Rm, am_brcmpcond:$Target), []>,
Sched<[WriteBr]> {
: Pseudo<(outs),
(ins ccode:$Cond, regtype:$Rt, regtype:$Rm, am_brcmpcond:$Target),
[]>,
Sched<[WriteBr]> {
let isBranch = 1;
let isTerminator = 1;
}

// Cmpbr pseudo instruction, encoding potentially folded zero-, sign-extension,
// assertzext and/or assersext.
class CmpBranchExtRegisterPseudo
: Pseudo<(outs),
(ins ccode:$Cond, GPR32:$Rt, GPR32:$Rm, am_brcmpcond:$Target,
simm8_32b:$ExtRt, simm8_32b:$ExtRm),
[]>,
Sched<[WriteBr]> {
let isBranch = 1;
let isTerminator = 1;
}
Expand Down
Loading