mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-15 04:30:12 +00:00
Fold comparisons into select instructions, making much better code and
using our broad selection of movcc instructions. :) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@12560 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
dd285eab68
commit
307ecbaddb
@ -743,19 +743,20 @@ void ISel::InsertFPRegKills() {
|
||||
}
|
||||
|
||||
|
||||
// canFoldSetCCIntoBranch - Return the setcc instruction if we can fold it into
|
||||
// the conditional branch instruction which is the only user of the cc
|
||||
// instruction. This is the case if the conditional branch is the only user of
|
||||
// the setcc, and if the setcc is in the same basic block as the conditional
|
||||
// branch. We also don't handle long arguments below, so we reject them here as
|
||||
// well.
|
||||
// canFoldSetCCIntoBranchOrSelect - Return the setcc instruction if we can fold
|
||||
// it into the conditional branch or select instruction which is the only user
|
||||
// of the cc instruction. This is the case if the conditional branch is the
|
||||
// only user of the setcc, and if the setcc is in the same basic block as the
|
||||
// conditional branch. We also don't handle long arguments below, so we reject
|
||||
// them here as well.
|
||||
//
|
||||
static SetCondInst *canFoldSetCCIntoBranch(Value *V) {
|
||||
static SetCondInst *canFoldSetCCIntoBranchOrSelect(Value *V) {
|
||||
if (SetCondInst *SCI = dyn_cast<SetCondInst>(V))
|
||||
if (SCI->hasOneUse() && isa<BranchInst>(SCI->use_back()) &&
|
||||
SCI->getParent() == cast<BranchInst>(SCI->use_back())->getParent()) {
|
||||
const Type *Ty = SCI->getOperand(0)->getType();
|
||||
if (Ty != Type::LongTy && Ty != Type::ULongTy)
|
||||
if (SCI->hasOneUse()) {
|
||||
Instruction *User = cast<Instruction>(SCI->use_back());
|
||||
if ((isa<BranchInst>(User) || isa<SelectInst>(User)) &&
|
||||
SCI->getParent() == User->getParent() &&
|
||||
getClassB(SCI->getOperand(0)->getType()) != cLong)
|
||||
return SCI;
|
||||
}
|
||||
return 0;
|
||||
@ -907,7 +908,8 @@ unsigned ISel::EmitComparison(unsigned OpNum, Value *Op0, Value *Op1,
|
||||
/// register, then move it to wherever the result should be.
|
||||
///
|
||||
void ISel::visitSetCondInst(SetCondInst &I) {
|
||||
if (canFoldSetCCIntoBranch(&I)) return; // Fold this into a branch...
|
||||
if (canFoldSetCCIntoBranchOrSelect(&I))
|
||||
return; // Fold this into a branch or select.
|
||||
|
||||
unsigned DestReg = getReg(I);
|
||||
MachineBasicBlock::iterator MII = BB->end();
|
||||
@ -963,16 +965,64 @@ void ISel::emitSelectOperation(MachineBasicBlock *MBB,
|
||||
FalseVal = ConstantExpr::getCast(F, Type::ShortTy);
|
||||
}
|
||||
|
||||
|
||||
unsigned Opcode;
|
||||
if (SetCondInst *SCI = canFoldSetCCIntoBranchOrSelect(Cond)) {
|
||||
// We successfully folded the setcc into the select instruction.
|
||||
|
||||
unsigned OpNum = getSetCCNumber(SCI->getOpcode());
|
||||
OpNum = EmitComparison(OpNum, SCI->getOperand(0), SCI->getOperand(1), MBB,
|
||||
IP);
|
||||
|
||||
const Type *CompTy = SCI->getOperand(0)->getType();
|
||||
bool isSigned = CompTy->isSigned() && getClassB(CompTy) != cFP;
|
||||
|
||||
// LLVM -> X86 signed X86 unsigned
|
||||
// ----- ---------- ------------
|
||||
// seteq -> cmovNE cmovNE
|
||||
// setne -> cmovE cmovE
|
||||
// setlt -> cmovGE cmovAE
|
||||
// setge -> cmovL cmovB
|
||||
// setgt -> cmovLE cmovBE
|
||||
// setle -> cmovG cmovA
|
||||
// ----
|
||||
// cmovNS // Used by comparison with 0 optimization
|
||||
// cmovS
|
||||
|
||||
switch (SelectClass) {
|
||||
default:
|
||||
case cFP:
|
||||
assert(0 && "We don't support floating point selects yet, they should "
|
||||
"have been lowered!");
|
||||
case cByte:
|
||||
case cShort: {
|
||||
static const unsigned OpcodeTab[2][8] = {
|
||||
{ X86::CMOVNE16rr, X86::CMOVE16rr, X86::CMOVAE16rr, X86::CMOVB16rr,
|
||||
X86::CMOVBE16rr, X86::CMOVA16rr, 0, 0 },
|
||||
{ X86::CMOVNE16rr, X86::CMOVE16rr, X86::CMOVGE16rr, X86::CMOVL16rr,
|
||||
X86::CMOVLE16rr, X86::CMOVG16rr, X86::CMOVNS16rr, X86::CMOVS16rr },
|
||||
};
|
||||
Opcode = OpcodeTab[isSigned][OpNum];
|
||||
break;
|
||||
}
|
||||
case cInt:
|
||||
case cLong: {
|
||||
static const unsigned OpcodeTab[2][8] = {
|
||||
{ X86::CMOVNE32rr, X86::CMOVE32rr, X86::CMOVAE32rr, X86::CMOVB32rr,
|
||||
X86::CMOVBE32rr, X86::CMOVA32rr, 0, 0 },
|
||||
{ X86::CMOVNE32rr, X86::CMOVE32rr, X86::CMOVGE32rr, X86::CMOVL32rr,
|
||||
X86::CMOVLE32rr, X86::CMOVG32rr, X86::CMOVNS32rr, X86::CMOVS32rr },
|
||||
};
|
||||
Opcode = OpcodeTab[isSigned][OpNum];
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Get the value being branched on, and use it to set the condition codes.
|
||||
unsigned CondReg = getReg(Cond, MBB, IP);
|
||||
BuildMI(*MBB, IP, X86::CMP8ri, 2).addReg(CondReg).addImm(0);
|
||||
|
||||
unsigned TrueReg = getReg(TrueVal, MBB, IP);
|
||||
unsigned FalseReg = getReg(FalseVal, MBB, IP);
|
||||
unsigned RealDestReg = DestReg;
|
||||
unsigned Opcode;
|
||||
|
||||
switch (SelectClass) {
|
||||
default:
|
||||
case cFP:
|
||||
assert(0 && "We don't support floating point selects yet, they should "
|
||||
"have been lowered!");
|
||||
@ -985,6 +1035,12 @@ void ISel::emitSelectOperation(MachineBasicBlock *MBB,
|
||||
Opcode = X86::CMOVE32rr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned TrueReg = getReg(TrueVal, MBB, IP);
|
||||
unsigned FalseReg = getReg(FalseVal, MBB, IP);
|
||||
unsigned RealDestReg = DestReg;
|
||||
|
||||
|
||||
// Annoyingly enough, X86 doesn't HAVE 8-bit conditional moves. Because of
|
||||
// this, we have to promote the incoming values to 16 bits, perform a 16-bit
|
||||
@ -1126,7 +1182,7 @@ void ISel::visitBranchInst(BranchInst &BI) {
|
||||
}
|
||||
|
||||
// See if we can fold the setcc into the branch itself...
|
||||
SetCondInst *SCI = canFoldSetCCIntoBranch(BI.getCondition());
|
||||
SetCondInst *SCI = canFoldSetCCIntoBranchOrSelect(BI.getCondition());
|
||||
if (SCI == 0) {
|
||||
// Nope, cannot fold setcc into this branch. Emit a branch on a condition
|
||||
// computed some other way...
|
||||
|
@ -743,19 +743,20 @@ void ISel::InsertFPRegKills() {
|
||||
}
|
||||
|
||||
|
||||
// canFoldSetCCIntoBranch - Return the setcc instruction if we can fold it into
|
||||
// the conditional branch instruction which is the only user of the cc
|
||||
// instruction. This is the case if the conditional branch is the only user of
|
||||
// the setcc, and if the setcc is in the same basic block as the conditional
|
||||
// branch. We also don't handle long arguments below, so we reject them here as
|
||||
// well.
|
||||
// canFoldSetCCIntoBranchOrSelect - Return the setcc instruction if we can fold
|
||||
// it into the conditional branch or select instruction which is the only user
|
||||
// of the cc instruction. This is the case if the conditional branch is the
|
||||
// only user of the setcc, and if the setcc is in the same basic block as the
|
||||
// conditional branch. We also don't handle long arguments below, so we reject
|
||||
// them here as well.
|
||||
//
|
||||
static SetCondInst *canFoldSetCCIntoBranch(Value *V) {
|
||||
static SetCondInst *canFoldSetCCIntoBranchOrSelect(Value *V) {
|
||||
if (SetCondInst *SCI = dyn_cast<SetCondInst>(V))
|
||||
if (SCI->hasOneUse() && isa<BranchInst>(SCI->use_back()) &&
|
||||
SCI->getParent() == cast<BranchInst>(SCI->use_back())->getParent()) {
|
||||
const Type *Ty = SCI->getOperand(0)->getType();
|
||||
if (Ty != Type::LongTy && Ty != Type::ULongTy)
|
||||
if (SCI->hasOneUse()) {
|
||||
Instruction *User = cast<Instruction>(SCI->use_back());
|
||||
if ((isa<BranchInst>(User) || isa<SelectInst>(User)) &&
|
||||
SCI->getParent() == User->getParent() &&
|
||||
getClassB(SCI->getOperand(0)->getType()) != cLong)
|
||||
return SCI;
|
||||
}
|
||||
return 0;
|
||||
@ -907,7 +908,8 @@ unsigned ISel::EmitComparison(unsigned OpNum, Value *Op0, Value *Op1,
|
||||
/// register, then move it to wherever the result should be.
|
||||
///
|
||||
void ISel::visitSetCondInst(SetCondInst &I) {
|
||||
if (canFoldSetCCIntoBranch(&I)) return; // Fold this into a branch...
|
||||
if (canFoldSetCCIntoBranchOrSelect(&I))
|
||||
return; // Fold this into a branch or select.
|
||||
|
||||
unsigned DestReg = getReg(I);
|
||||
MachineBasicBlock::iterator MII = BB->end();
|
||||
@ -963,16 +965,64 @@ void ISel::emitSelectOperation(MachineBasicBlock *MBB,
|
||||
FalseVal = ConstantExpr::getCast(F, Type::ShortTy);
|
||||
}
|
||||
|
||||
|
||||
unsigned Opcode;
|
||||
if (SetCondInst *SCI = canFoldSetCCIntoBranchOrSelect(Cond)) {
|
||||
// We successfully folded the setcc into the select instruction.
|
||||
|
||||
unsigned OpNum = getSetCCNumber(SCI->getOpcode());
|
||||
OpNum = EmitComparison(OpNum, SCI->getOperand(0), SCI->getOperand(1), MBB,
|
||||
IP);
|
||||
|
||||
const Type *CompTy = SCI->getOperand(0)->getType();
|
||||
bool isSigned = CompTy->isSigned() && getClassB(CompTy) != cFP;
|
||||
|
||||
// LLVM -> X86 signed X86 unsigned
|
||||
// ----- ---------- ------------
|
||||
// seteq -> cmovNE cmovNE
|
||||
// setne -> cmovE cmovE
|
||||
// setlt -> cmovGE cmovAE
|
||||
// setge -> cmovL cmovB
|
||||
// setgt -> cmovLE cmovBE
|
||||
// setle -> cmovG cmovA
|
||||
// ----
|
||||
// cmovNS // Used by comparison with 0 optimization
|
||||
// cmovS
|
||||
|
||||
switch (SelectClass) {
|
||||
default:
|
||||
case cFP:
|
||||
assert(0 && "We don't support floating point selects yet, they should "
|
||||
"have been lowered!");
|
||||
case cByte:
|
||||
case cShort: {
|
||||
static const unsigned OpcodeTab[2][8] = {
|
||||
{ X86::CMOVNE16rr, X86::CMOVE16rr, X86::CMOVAE16rr, X86::CMOVB16rr,
|
||||
X86::CMOVBE16rr, X86::CMOVA16rr, 0, 0 },
|
||||
{ X86::CMOVNE16rr, X86::CMOVE16rr, X86::CMOVGE16rr, X86::CMOVL16rr,
|
||||
X86::CMOVLE16rr, X86::CMOVG16rr, X86::CMOVNS16rr, X86::CMOVS16rr },
|
||||
};
|
||||
Opcode = OpcodeTab[isSigned][OpNum];
|
||||
break;
|
||||
}
|
||||
case cInt:
|
||||
case cLong: {
|
||||
static const unsigned OpcodeTab[2][8] = {
|
||||
{ X86::CMOVNE32rr, X86::CMOVE32rr, X86::CMOVAE32rr, X86::CMOVB32rr,
|
||||
X86::CMOVBE32rr, X86::CMOVA32rr, 0, 0 },
|
||||
{ X86::CMOVNE32rr, X86::CMOVE32rr, X86::CMOVGE32rr, X86::CMOVL32rr,
|
||||
X86::CMOVLE32rr, X86::CMOVG32rr, X86::CMOVNS32rr, X86::CMOVS32rr },
|
||||
};
|
||||
Opcode = OpcodeTab[isSigned][OpNum];
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Get the value being branched on, and use it to set the condition codes.
|
||||
unsigned CondReg = getReg(Cond, MBB, IP);
|
||||
BuildMI(*MBB, IP, X86::CMP8ri, 2).addReg(CondReg).addImm(0);
|
||||
|
||||
unsigned TrueReg = getReg(TrueVal, MBB, IP);
|
||||
unsigned FalseReg = getReg(FalseVal, MBB, IP);
|
||||
unsigned RealDestReg = DestReg;
|
||||
unsigned Opcode;
|
||||
|
||||
switch (SelectClass) {
|
||||
default:
|
||||
case cFP:
|
||||
assert(0 && "We don't support floating point selects yet, they should "
|
||||
"have been lowered!");
|
||||
@ -985,6 +1035,12 @@ void ISel::emitSelectOperation(MachineBasicBlock *MBB,
|
||||
Opcode = X86::CMOVE32rr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned TrueReg = getReg(TrueVal, MBB, IP);
|
||||
unsigned FalseReg = getReg(FalseVal, MBB, IP);
|
||||
unsigned RealDestReg = DestReg;
|
||||
|
||||
|
||||
// Annoyingly enough, X86 doesn't HAVE 8-bit conditional moves. Because of
|
||||
// this, we have to promote the incoming values to 16 bits, perform a 16-bit
|
||||
@ -1126,7 +1182,7 @@ void ISel::visitBranchInst(BranchInst &BI) {
|
||||
}
|
||||
|
||||
// See if we can fold the setcc into the branch itself...
|
||||
SetCondInst *SCI = canFoldSetCCIntoBranch(BI.getCondition());
|
||||
SetCondInst *SCI = canFoldSetCCIntoBranchOrSelect(BI.getCondition());
|
||||
if (SCI == 0) {
|
||||
// Nope, cannot fold setcc into this branch. Emit a branch on a condition
|
||||
// computed some other way...
|
||||
|
Loading…
Reference in New Issue
Block a user