Skip to content

Commit

Permalink
[X86] Merge the different SETcc instructions for each condition code …
Browse files Browse the repository at this point in the history
…into single instructions that store the condition code as an operand.

Summary:
This avoids needing an isel pattern for each condition code. And it removes translation switches for converting between SETcc instructions and condition codes.

Now the printer, encoder and disassembler take care of converting the immediate. We use InstAliases to handle the assembly matching. But we print using the asm string in the instruction definition. The instruction itself is marked IsCodeGenOnly=1 to hide it from the assembly parser.

Reviewers: andreadb, courbet, RKSimon, spatel, lebedev.ri

Reviewed By: andreadb

Subscribers: hiraditya, lebedev.ri, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D60138

llvm-svn: 357801
  • Loading branch information
topperc committed Apr 5, 2019
1 parent e0bfeb5 commit 7323c2b
Show file tree
Hide file tree
Showing 29 changed files with 467 additions and 416 deletions.
18 changes: 16 additions & 2 deletions llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -351,10 +351,16 @@ namespace X86II {
///
MRMSrcMemCC = 36,

/// MRMXm - This form is used for instructions that use the Mod/RM byte
/// to specify a memory source, but doesn't use the middle field. And has
/// a condition code.
///
MRMXmCC = 38,

/// MRMXm - This form is used for instructions that use the Mod/RM byte
/// to specify a memory source, but doesn't use the middle field.
///
MRMXm = 39, // Instruction that uses Mod/RM but not the middle field.
MRMXm = 39,

// Next, instructions that operate on a memory r/m operand...
MRM0m = 40, MRM1m = 41, MRM2m = 42, MRM3m = 43, // Format /0 /1 /2 /3
Expand Down Expand Up @@ -385,10 +391,16 @@ namespace X86II {
///
MRMSrcRegCC = 52,

/// MRMXCCr - This form is used for instructions that use the Mod/RM byte
/// to specify a register source, but doesn't use the middle field. And has
/// a condition code.
///
MRMXrCC = 54,

/// MRMXr - This form is used for instructions that use the Mod/RM byte
/// to specify a register source, but doesn't use the middle field.
///
MRMXr = 55, // Instruction that uses Mod/RM but not the middle field.
MRMXr = 55,

// Instructions that operate on a register r/m operand...
MRM0r = 56, MRM1r = 57, MRM2r = 58, MRM3r = 59, // Format /0 /1 /2 /3
Expand Down Expand Up @@ -779,12 +791,14 @@ namespace X86II {
case X86II::MRMSrcReg4VOp3:
case X86II::MRMSrcRegOp4:
case X86II::MRMSrcRegCC:
case X86II::MRMXrCC:
case X86II::MRMXr:
case X86II::MRM0r: case X86II::MRM1r:
case X86II::MRM2r: case X86II::MRM3r:
case X86II::MRM4r: case X86II::MRM5r:
case X86II::MRM6r: case X86II::MRM7r:
return -1;
case X86II::MRMXmCC:
case X86II::MRMXm:
case X86II::MRM0m: case X86II::MRM1m:
case X86II::MRM2m: case X86II::MRM3m:
Expand Down
24 changes: 22 additions & 2 deletions llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1081,15 +1081,15 @@ uint8_t X86MCCodeEmitter::DetermineREXPrefix(const MCInst &MI, uint64_t TSFlags,
CurOp += X86::AddrNumOperands;
REX |= isREXExtendedReg(MI, CurOp++) << 2; // REX.R
break;
case X86II::MRMXm:
case X86II::MRMXmCC: case X86II::MRMXm:
case X86II::MRM0m: case X86II::MRM1m:
case X86II::MRM2m: case X86II::MRM3m:
case X86II::MRM4m: case X86II::MRM5m:
case X86II::MRM6m: case X86II::MRM7m:
REX |= isREXExtendedReg(MI, MemOperand+X86::AddrBaseReg) << 0; // REX.B
REX |= isREXExtendedReg(MI, MemOperand+X86::AddrIndexReg) << 1; // REX.X
break;
case X86II::MRMXr:
case X86II::MRMXrCC: case X86II::MRMXr:
case X86II::MRM0r: case X86II::MRM1r:
case X86II::MRM2r: case X86II::MRM3r:
case X86II::MRM4r: case X86II::MRM5r:
Expand Down Expand Up @@ -1506,6 +1506,15 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS,
break;
}

case X86II::MRMXrCC: {
unsigned RegOp = CurOp++;

unsigned CC = MI.getOperand(CurOp++).getImm();
EmitByte(BaseOpcode + CC, CurByte, OS);
EmitRegModRMByte(MI.getOperand(RegOp), 0, CurByte, OS);
break;
}

case X86II::MRMXr:
case X86II::MRM0r: case X86II::MRM1r:
case X86II::MRM2r: case X86II::MRM3r:
Expand All @@ -1521,6 +1530,17 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS,
CurByte, OS);
break;

case X86II::MRMXmCC: {
unsigned FirstMemOp = CurOp;
CurOp = FirstMemOp + X86::AddrNumOperands;

unsigned CC = MI.getOperand(CurOp++).getImm();
EmitByte(BaseOpcode + CC, CurByte, OS);

emitMemModRMByte(MI, FirstMemOp, 0, TSFlags, Rex, CurByte, OS, Fixups, STI);
break;
}

case X86II::MRMXm:
case X86II::MRM0m: case X86II::MRM1m:
case X86II::MRM2m: case X86II::MRM3m:
Expand Down
48 changes: 24 additions & 24 deletions llvm/lib/Target/X86/X86FastISel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1480,8 +1480,8 @@ bool X86FastISel::X86SelectCmp(const Instruction *I) {

// FCMP_OEQ and FCMP_UNE cannot be checked with a single instruction.
static const uint16_t SETFOpcTable[2][3] = {
{ X86::SETEr, X86::SETNPr, X86::AND8rr },
{ X86::SETNEr, X86::SETPr, X86::OR8rr }
{ X86::COND_E, X86::COND_NP, X86::AND8rr },
{ X86::COND_NE, X86::COND_P, X86::OR8rr }
};
const uint16_t *SETFOpc = nullptr;
switch (Predicate) {
Expand All @@ -1497,10 +1497,10 @@ bool X86FastISel::X86SelectCmp(const Instruction *I) {

unsigned FlagReg1 = createResultReg(&X86::GR8RegClass);
unsigned FlagReg2 = createResultReg(&X86::GR8RegClass);
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(SETFOpc[0]),
FlagReg1);
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(SETFOpc[1]),
FlagReg2);
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(X86::SETCCr),
FlagReg1).addImm(SETFOpc[0]);
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(X86::SETCCr),
FlagReg2).addImm(SETFOpc[1]);
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(SETFOpc[2]),
ResultReg).addReg(FlagReg1).addReg(FlagReg2);
updateValueMap(I, ResultReg);
Expand All @@ -1511,7 +1511,6 @@ bool X86FastISel::X86SelectCmp(const Instruction *I) {
bool SwapArgs;
std::tie(CC, SwapArgs) = X86::getX86ConditionCode(Predicate);
assert(CC <= X86::LAST_VALID_COND && "Unexpected condition code.");
unsigned Opc = X86::getSETFromCond(CC);

if (SwapArgs)
std::swap(LHS, RHS);
Expand All @@ -1520,7 +1519,8 @@ bool X86FastISel::X86SelectCmp(const Instruction *I) {
if (!X86FastEmitCompare(LHS, RHS, VT, I->getDebugLoc()))
return false;

BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg);
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(X86::SETCCr),
ResultReg).addImm(CC);
updateValueMap(I, ResultReg);
return true;
}
Expand Down Expand Up @@ -2047,8 +2047,8 @@ bool X86FastISel::X86FastEmitCMoveSelect(MVT RetVT, const Instruction *I) {

// FCMP_OEQ and FCMP_UNE cannot be checked with a single instruction.
static const uint16_t SETFOpcTable[2][3] = {
{ X86::SETNPr, X86::SETEr , X86::TEST8rr },
{ X86::SETPr, X86::SETNEr, X86::OR8rr }
{ X86::COND_NP, X86::COND_E, X86::TEST8rr },
{ X86::COND_P, X86::COND_NE, X86::OR8rr }
};
const uint16_t *SETFOpc = nullptr;
switch (Predicate) {
Expand Down Expand Up @@ -2080,10 +2080,10 @@ bool X86FastISel::X86FastEmitCMoveSelect(MVT RetVT, const Instruction *I) {
if (SETFOpc) {
unsigned FlagReg1 = createResultReg(&X86::GR8RegClass);
unsigned FlagReg2 = createResultReg(&X86::GR8RegClass);
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(SETFOpc[0]),
FlagReg1);
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(SETFOpc[1]),
FlagReg2);
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(X86::SETCCr),
FlagReg1).addImm(SETFOpc[0]);
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(X86::SETCCr),
FlagReg2).addImm(SETFOpc[1]);
auto const &II = TII.get(SETFOpc[2]);
if (II.getNumDefs()) {
unsigned TmpReg = createResultReg(&X86::GR8RegClass);
Expand Down Expand Up @@ -2897,21 +2897,21 @@ bool X86FastISel::fastLowerIntrinsicCall(const IntrinsicInst *II) {
isCommutativeIntrinsic(II))
std::swap(LHS, RHS);

unsigned BaseOpc, CondOpc;
unsigned BaseOpc, CondCode;
switch (II->getIntrinsicID()) {
default: llvm_unreachable("Unexpected intrinsic!");
case Intrinsic::sadd_with_overflow:
BaseOpc = ISD::ADD; CondOpc = X86::SETOr; break;
BaseOpc = ISD::ADD; CondCode = X86::COND_O; break;
case Intrinsic::uadd_with_overflow:
BaseOpc = ISD::ADD; CondOpc = X86::SETBr; break;
BaseOpc = ISD::ADD; CondCode = X86::COND_B; break;
case Intrinsic::ssub_with_overflow:
BaseOpc = ISD::SUB; CondOpc = X86::SETOr; break;
BaseOpc = ISD::SUB; CondCode = X86::COND_O; break;
case Intrinsic::usub_with_overflow:
BaseOpc = ISD::SUB; CondOpc = X86::SETBr; break;
BaseOpc = ISD::SUB; CondCode = X86::COND_B; break;
case Intrinsic::smul_with_overflow:
BaseOpc = X86ISD::SMUL; CondOpc = X86::SETOr; break;
BaseOpc = X86ISD::SMUL; CondCode = X86::COND_O; break;
case Intrinsic::umul_with_overflow:
BaseOpc = X86ISD::UMUL; CondOpc = X86::SETOr; break;
BaseOpc = X86ISD::UMUL; CondCode = X86::COND_O; break;
}

unsigned LHSReg = getRegForValue(LHS);
Expand All @@ -2928,7 +2928,7 @@ bool X86FastISel::fastLowerIntrinsicCall(const IntrinsicInst *II) {
};

if (CI->isOne() && (BaseOpc == ISD::ADD || BaseOpc == ISD::SUB) &&
CondOpc == X86::SETOr) {
CondCode == X86::COND_O) {
// We can use INC/DEC.
ResultReg = createResultReg(TLI.getRegClassFor(VT));
bool IsDec = BaseOpc == ISD::SUB;
Expand Down Expand Up @@ -2987,8 +2987,8 @@ bool X86FastISel::fastLowerIntrinsicCall(const IntrinsicInst *II) {
// Assign to a GPR since the overflow return value is lowered to a SETcc.
unsigned ResultReg2 = createResultReg(&X86::GR8RegClass);
assert((ResultReg+1) == ResultReg2 && "Nonconsecutive result registers.");
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(CondOpc),
ResultReg2);
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(X86::SETCCr),
ResultReg2).addImm(CondCode);

updateValueMap(II, ResultReg, 2);
return true;
Expand Down
26 changes: 1 addition & 25 deletions llvm/lib/Target/X86/X86FixupSetCC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,30 +67,6 @@ char X86FixupSetCCPass::ID = 0;

FunctionPass *llvm::createX86FixupSetCC() { return new X86FixupSetCCPass(); }

bool X86FixupSetCCPass::isSetCCr(unsigned Opcode) {
switch (Opcode) {
default:
return false;
case X86::SETOr:
case X86::SETNOr:
case X86::SETBr:
case X86::SETAEr:
case X86::SETEr:
case X86::SETNEr:
case X86::SETBEr:
case X86::SETAr:
case X86::SETSr:
case X86::SETNSr:
case X86::SETPr:
case X86::SETNPr:
case X86::SETLr:
case X86::SETGEr:
case X86::SETLEr:
case X86::SETGr:
return true;
}
}

// We expect the instruction *immediately* before the setcc to imp-def
// EFLAGS (because of scheduling glue). To make this less brittle w.r.t
// scheduling, look backwards until we hit the beginning of the
Expand Down Expand Up @@ -128,7 +104,7 @@ bool X86FixupSetCCPass::runOnMachineFunction(MachineFunction &MF) {
// Find a setcc that is used by a zext.
// This doesn't have to be the only use, the transformation is safe
// regardless.
if (!isSetCCr(MI.getOpcode()))
if (MI.getOpcode() != X86::SETCCr)
continue;

MachineInstr *ZExt = nullptr;
Expand Down
9 changes: 4 additions & 5 deletions llvm/lib/Target/X86/X86FlagsCopyLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -601,8 +601,7 @@ bool X86FlagsCopyLoweringPass::runOnMachineFunction(MachineFunction &MF) {
// Otherwise we can just rewrite in-place.
if (X86::getCondFromCMov(MI) != X86::COND_INVALID) {
rewriteCMov(*TestMBB, TestPos, TestLoc, MI, *FlagUse, CondRegs);
} else if (X86::getCondFromSETOpc(MI.getOpcode()) !=
X86::COND_INVALID) {
} else if (X86::getCondFromSETCC(MI) != X86::COND_INVALID) {
rewriteSetCC(*TestMBB, TestPos, TestLoc, MI, *FlagUse, CondRegs);
} else if (MI.getOpcode() == TargetOpcode::COPY) {
rewriteCopy(MI, *FlagUse, CopyDefI);
Expand Down Expand Up @@ -729,7 +728,7 @@ CondRegArray X86FlagsCopyLoweringPass::collectCondsInRegs(
// Scan backwards across the range of instructions with live EFLAGS.
for (MachineInstr &MI :
llvm::reverse(llvm::make_range(MBB.begin(), TestPos))) {
X86::CondCode Cond = X86::getCondFromSETOpc(MI.getOpcode());
X86::CondCode Cond = X86::getCondFromSETCC(MI);
if (Cond != X86::COND_INVALID && !MI.mayStore() && MI.getOperand(0).isReg() &&
TRI->isVirtualRegister(MI.getOperand(0).getReg())) {
assert(MI.getOperand(0).isDef() &&
Expand All @@ -750,7 +749,7 @@ unsigned X86FlagsCopyLoweringPass::promoteCondToReg(
DebugLoc TestLoc, X86::CondCode Cond) {
unsigned Reg = MRI->createVirtualRegister(PromoteRC);
auto SetI = BuildMI(TestMBB, TestPos, TestLoc,
TII->get(X86::getSETFromCond(Cond)), Reg);
TII->get(X86::SETCCr), Reg).addImm(Cond);
(void)SetI;
LLVM_DEBUG(dbgs() << " save cond: "; SetI->dump());
++NumSetCCsInserted;
Expand Down Expand Up @@ -1023,7 +1022,7 @@ void X86FlagsCopyLoweringPass::rewriteSetCC(MachineBasicBlock &TestMBB,
MachineInstr &SetCCI,
MachineOperand &FlagUse,
CondRegArray &CondRegs) {
X86::CondCode Cond = X86::getCondFromSETOpc(SetCCI.getOpcode());
X86::CondCode Cond = X86::getCondFromSETCC(SetCCI);
// Note that we can't usefully rewrite this to the inverse without complex
// analysis of the users of the setCC. Largely we rely on duplicates which
// could have been avoided already being avoided here.
Expand Down
9 changes: 6 additions & 3 deletions llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2326,11 +2326,14 @@ static X86::CondCode getCondFromNode(SDNode *N) {
X86::CondCode CC = X86::COND_INVALID;
if (CC == X86::COND_INVALID)
CC = X86::getCondFromBranchOpc(N->getMachineOpcode());
if (CC == X86::COND_INVALID)
CC = X86::getCondFromSETOpc(N->getMachineOpcode());
if (CC == X86::COND_INVALID) {
unsigned Opc = N->getMachineOpcode();
if (Opc == X86::CMOV16rr || Opc == X86::CMOV32rr || Opc == X86::CMOV64rr)
if (Opc == X86::SETCCr)
CC = static_cast<X86::CondCode>(N->getConstantOperandVal(0));
else if (Opc == X86::SETCCm)
CC = static_cast<X86::CondCode>(N->getConstantOperandVal(5));
else if (Opc == X86::CMOV16rr || Opc == X86::CMOV32rr ||
Opc == X86::CMOV64rr)
CC = static_cast<X86::CondCode>(N->getConstantOperandVal(2));
else if (Opc == X86::CMOV16rm || Opc == X86::CMOV32rm ||
Opc == X86::CMOV64rm)
Expand Down
Loading

0 comments on commit 7323c2b

Please sign in to comment.