unsigned EmitComparison(unsigned OpNum, Value *Op0, Value *Op1,
MachineBasicBlock *MBB,
MachineBasicBlock::iterator MBBI);
+ void visitSelectInst(SelectInst &SI);
+
// Memory Instructions
void visitLoadInst(LoadInst &I);
Value *Op, Value *ShiftAmount, bool isLeftShift,
const Type *ResultTy, unsigned DestReg);
+ /// emitSelectOperation - Common code shared between visitSelectInst and the
+ /// constant expression support.
+ void emitSelectOperation(MachineBasicBlock *MBB,
+ MachineBasicBlock::iterator IP,
+ Value *Cond, Value *TrueVal, Value *FalseVal,
+ unsigned DestReg);
/// copyConstantToRegister - Output the instructions required to put the
/// specified constant into the specified register.
CE->getOpcode() == Instruction::Shl, CE->getType(), R);
return;
+ case Instruction::Select:
+ emitSelectOperation(MBB, IP, CE->getOperand(0), CE->getOperand(1),
+ CE->getOperand(2), R);
+ return;
+
default:
std::cerr << "Offending expr: " << C << "\n";
assert(0 && "Constant expression not yet handled!\n");
// If this is a constant or GlobalValue, we may have to insert code
// into the basic block to compute it into a virtual register.
if (isa<Constant>(Val) || isa<GlobalValue>(Val)) {
- // Because we don't want to clobber any values which might be in
- // physical registers with the computation of this constant (which
- // might be arbitrarily complex if it is a constant expression),
- // just insert the computation at the top of the basic block.
- MachineBasicBlock::iterator PI = PredMBB->begin();
-
- // Skip over any PHI nodes though!
- while (PI != PredMBB->end() && PI->getOpcode() == X86::PHI)
- ++PI;
-
- ValReg = getReg(Val, PredMBB, PI);
+ if (isa<ConstantExpr>(Val)) {
+ // Because we don't want to clobber any values which might be in
+ // physical registers with the computation of this constant (which
+ // might be arbitrarily complex if it is a constant expression),
+ // just insert the computation at the top of the basic block.
+ MachineBasicBlock::iterator PI = PredMBB->begin();
+
+ // Skip over any PHI nodes though!
+ while (PI != PredMBB->end() && PI->getOpcode() == X86::PHI)
+ ++PI;
+
+ ValReg = getReg(Val, PredMBB, PI);
+ } else {
+ // Simple constants get emitted at the end of the basic block,
+ // before any terminator instructions. We "know" that the code to
+ // move a constant into a register will never clobber any flags.
+ ValReg = getReg(Val, PredMBB, PredMBB->getFirstTerminator());
+ }
} else {
ValReg = getReg(Val);
}
}
-// 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;
return OpNum;
}
-
/// SetCC instructions - Here we just emit boilerplate code to set a byte-sized
/// 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();
}
}
+void ISel::visitSelectInst(SelectInst &SI) {
+ unsigned DestReg = getReg(SI);
+ MachineBasicBlock::iterator MII = BB->end();
+ emitSelectOperation(BB, MII, SI.getCondition(), SI.getTrueValue(),
+ SI.getFalseValue(), DestReg);
+}
+
+/// emitSelect - Common code shared between visitSelectInst and the constant
+/// expression support.
+void ISel::emitSelectOperation(MachineBasicBlock *MBB,
+ MachineBasicBlock::iterator IP,
+ Value *Cond, Value *TrueVal, Value *FalseVal,
+ unsigned DestReg) {
+ unsigned SelectClass = getClassB(TrueVal->getType());
+
+ // We don't support 8-bit conditional moves. If we have incoming constants,
+ // transform them into 16-bit constants to avoid having a run-time conversion.
+ if (SelectClass == cByte) {
+ if (Constant *T = dyn_cast<Constant>(TrueVal))
+ TrueVal = ConstantExpr::getCast(T, Type::ShortTy);
+ if (Constant *F = dyn_cast<Constant>(FalseVal))
+ 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: assert(0 && "Unknown value class!");
+ case cFP: {
+ // Annoyingly, we don't have a full set of floating point conditional
+ // moves. :(
+ static const unsigned OpcodeTab[2][8] = {
+ { X86::FCMOVNE, X86::FCMOVE, X86::FCMOVAE, X86::FCMOVB,
+ X86::FCMOVBE, X86::FCMOVA, 0, 0 },
+ { X86::FCMOVNE, X86::FCMOVE, 0, 0, 0, 0, 0, 0 },
+ };
+ Opcode = OpcodeTab[isSigned][OpNum];
+
+ // If opcode == 0, we hit a case that we don't support. Output a setcc
+ // and compare the result against zero.
+ if (Opcode == 0) {
+ unsigned CompClass = getClassB(CompTy);
+ unsigned CondReg;
+ if (CompClass != cLong || OpNum < 2) {
+ CondReg = makeAnotherReg(Type::BoolTy);
+ // Handle normal comparisons with a setcc instruction...
+ BuildMI(*MBB, IP, SetCCOpcodeTab[isSigned][OpNum], 0, CondReg);
+ } else {
+ // Long comparisons end up in the BL register.
+ CondReg = X86::BL;
+ }
+
+ BuildMI(*MBB, IP, X86::TEST8rr, 2).addReg(CondReg).addReg(CondReg);
+ Opcode = X86::FCMOVE;
+ }
+ break;
+ }
+ 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::TEST8rr, 2).addReg(CondReg).addReg(CondReg);
+ switch (SelectClass) {
+ default: assert(0 && "Unknown value class!");
+ case cFP: Opcode = X86::FCMOVE; break;
+ case cByte:
+ case cShort: Opcode = X86::CMOVE16rr; break;
+ case cInt:
+ case cLong: 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
+ // cmove, then truncate the result.
+ if (SelectClass == cByte) {
+ DestReg = makeAnotherReg(Type::ShortTy);
+ if (getClassB(TrueVal->getType()) == cByte) {
+ // Promote the true value, by storing it into AL, and reading from AX.
+ BuildMI(*MBB, IP, X86::MOV8rr, 1, X86::AL).addReg(TrueReg);
+ BuildMI(*MBB, IP, X86::MOV8ri, 1, X86::AH).addImm(0);
+ TrueReg = makeAnotherReg(Type::ShortTy);
+ BuildMI(*MBB, IP, X86::MOV16rr, 1, TrueReg).addReg(X86::AX);
+ }
+ if (getClassB(FalseVal->getType()) == cByte) {
+ // Promote the true value, by storing it into CL, and reading from CX.
+ BuildMI(*MBB, IP, X86::MOV8rr, 1, X86::CL).addReg(FalseReg);
+ BuildMI(*MBB, IP, X86::MOV8ri, 1, X86::CH).addImm(0);
+ FalseReg = makeAnotherReg(Type::ShortTy);
+ BuildMI(*MBB, IP, X86::MOV16rr, 1, FalseReg).addReg(X86::CX);
+ }
+ }
+
+ BuildMI(*MBB, IP, Opcode, 2, DestReg).addReg(TrueReg).addReg(FalseReg);
+
+ switch (SelectClass) {
+ case cByte:
+ // We did the computation with 16-bit registers. Truncate back to our
+ // result by copying into AX then copying out AL.
+ BuildMI(*MBB, IP, X86::MOV16rr, 1, X86::AX).addReg(DestReg);
+ BuildMI(*MBB, IP, X86::MOV8rr, 1, RealDestReg).addReg(X86::AL);
+ break;
+ case cLong:
+ // Move the upper half of the value as well.
+ BuildMI(*MBB, IP, Opcode, 2,DestReg+1).addReg(TrueReg+1).addReg(FalseReg+1);
+ break;
+ }
+}
}
// 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...
unsigned condReg = getReg(BI.getCondition());
- BuildMI(BB, X86::CMP8ri, 2).addReg(condReg).addImm(0);
+ BuildMI(BB, X86::TEST8rr, 2).addReg(condReg).addReg(condReg);
if (BI.getSuccessor(1) == NextBB) {
if (BI.getSuccessor(0) != NextBB)
BuildMI(BB, X86::JNE, 1).addPCDisp(BI.getSuccessor(0));
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op0)) {
if (CI->isNullValue()) {
unsigned op1Reg = getReg(Op1, MBB, IP);
- switch (Class) {
- default: assert(0 && "Unknown class for this function!");
- case cByte:
- BuildMI(*MBB, IP, X86::NEG8r, 1, DestReg).addReg(op1Reg);
- return;
- case cShort:
- BuildMI(*MBB, IP, X86::NEG16r, 1, DestReg).addReg(op1Reg);
- return;
- case cInt:
- BuildMI(*MBB, IP, X86::NEG32r, 1, DestReg).addReg(op1Reg);
- return;
- }
+ static unsigned const NEGTab[] = {
+ X86::NEG8r, X86::NEG16r, X86::NEG32r
+ };
+ BuildMI(*MBB, IP, NEGTab[Class], 1, DestReg).addReg(op1Reg);
+ return;
}
} else if (ConstantFP *CFP = dyn_cast<ConstantFP>(Op0))
if (CFP->isExactlyValue(-0.0)) {
// add X, 1 -> inc X
if (OperatorClass == 0 && Op1C->equalsInt(1)) {
- static unsigned const DECTab[] = { X86::INC8r, X86::INC16r, X86::INC32r };
- BuildMI(*MBB, IP, DECTab[Class], 1, DestReg).addReg(Op0r);
+ static unsigned const INCTab[] = { X86::INC8r, X86::INC16r, X86::INC32r };
+ BuildMI(*MBB, IP, INCTab[Class], 1, DestReg).addReg(Op0r);
return;
}
uint64_t Op1v = cast<ConstantInt>(Op1C)->getRawValue();
- BuildMI(*MBB, IP, Opcode, 5, DestReg).addReg(Op0r).addImm(Op1v);
+ BuildMI(*MBB, IP, Opcode, 2, DestReg).addReg(Op0r).addImm(Op1v);
return;
}