#include "X86TargetMachine.h"
#include "llvm/CallingConv.h"
#include "llvm/Function.h"
-#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/CodeGen/SSARegMap.h"
#include "llvm/Target/TargetOptions.h"
return std::make_pair(Result, Chain);
}
-//===----------------------------------------------------------------------===//
-// X86 Custom Lowering Hooks
-//===----------------------------------------------------------------------===//
+/// getCondBrOpcodeForX86CC - Returns the X86 conditional branch opcode
+/// which corresponds to the condition code.
+static unsigned getCondBrOpcodeForX86CC(unsigned X86CC) {
+ switch (X86CC) {
+ default: assert(0 && "Unknown X86 conditional code!");
+ case X86ISD::COND_A: return X86::JA;
+ case X86ISD::COND_AE: return X86::JAE;
+ case X86ISD::COND_B: return X86::JB;
+ case X86ISD::COND_BE: return X86::JBE;
+ case X86ISD::COND_E: return X86::JE;
+ case X86ISD::COND_G: return X86::JG;
+ case X86ISD::COND_GE: return X86::JGE;
+ case X86ISD::COND_L: return X86::JL;
+ case X86ISD::COND_LE: return X86::JLE;
+ case X86ISD::COND_NE: return X86::JNE;
+ case X86ISD::COND_NO: return X86::JNO;
+ case X86ISD::COND_NP: return X86::JNP;
+ case X86ISD::COND_NS: return X86::JNS;
+ case X86ISD::COND_O: return X86::JO;
+ case X86ISD::COND_P: return X86::JP;
+ case X86ISD::COND_S: return X86::JS;
+ }
+}
-/// SetCCToX86CondCode - do a one to one translation of a ISD::CondCode to
-/// X86 specific CondCode. It returns a X86ISD::COND_INVALID if it cannot
+/// getX86CC - do a one to one translation of a ISD::CondCode to the X86
+/// specific condition code. It returns a X86ISD::COND_INVALID if it cannot
/// do a direct translation.
-static unsigned CCToX86CondCode(SDOperand CC, bool isFP) {
+static unsigned getX86CC(SDOperand CC, bool isFP) {
ISD::CondCode SetCCOpcode = cast<CondCodeSDNode>(CC)->get();
unsigned X86CC = X86ISD::COND_INVALID;
if (!isFP) {
return X86CC;
}
-/// SupportedByFPCMOV - is there a floating point cmov for the specific
-/// X86 condition code.
-/// Current x86 isa includes the following FP cmov instructions:
+/// hasFPCMov - is there a floating point cmov for the specific X86 condition
+/// code. Current x86 isa includes the following FP cmov instructions:
/// fcmovb, fcomvbe, fcomve, fcmovu, fcmovae, fcmova, fcmovne, fcmovnu.
-static bool SupportedByFPCMOV(unsigned X86CC) {
+static bool hasFPCMov(unsigned X86CC) {
switch (X86CC) {
default:
return false;
}
}
+MachineBasicBlock *
+X86TargetLowering::InsertAtEndOfBasicBlock(MachineInstr *MI,
+ MachineBasicBlock *BB) {
+ assert((MI->getOpcode() == X86::CMOV_FR32 ||
+ MI->getOpcode() == X86::CMOV_FR64) &&
+ "Unexpected instr type to insert");
+
+ // To "insert" a SELECT_CC instruction, we actually have to insert the diamond
+ // control-flow pattern. The incoming instruction knows the destination vreg
+ // to set, the condition code register to branch on, the true/false values to
+ // select between, and a branch opcode to use.
+ const BasicBlock *LLVM_BB = BB->getBasicBlock();
+ ilist<MachineBasicBlock>::iterator It = BB;
+ ++It;
+
+ // thisMBB:
+ // ...
+ // TrueVal = ...
+ // cmpTY ccX, r1, r2
+ // bCC copy1MBB
+ // fallthrough --> copy0MBB
+ MachineBasicBlock *thisMBB = BB;
+ MachineBasicBlock *copy0MBB = new MachineBasicBlock(LLVM_BB);
+ MachineBasicBlock *sinkMBB = new MachineBasicBlock(LLVM_BB);
+ unsigned Opc = getCondBrOpcodeForX86CC(MI->getOperand(3).getImmedValue());
+ BuildMI(BB, Opc, 1).addMBB(sinkMBB);
+ MachineFunction *F = BB->getParent();
+ F->getBasicBlockList().insert(It, copy0MBB);
+ F->getBasicBlockList().insert(It, sinkMBB);
+ // Update machine-CFG edges
+ BB->addSuccessor(copy0MBB);
+ BB->addSuccessor(sinkMBB);
+
+ // copy0MBB:
+ // %FalseValue = ...
+ // # fallthrough to sinkMBB
+ BB = copy0MBB;
+
+ // Update machine-CFG edges
+ BB->addSuccessor(sinkMBB);
+
+ // sinkMBB:
+ // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ]
+ // ...
+ BB = sinkMBB;
+ BuildMI(BB, X86::PHI, 4, MI->getOperand(0).getReg())
+ .addReg(MI->getOperand(1).getReg()).addMBB(copy0MBB)
+ .addReg(MI->getOperand(2).getReg()).addMBB(thisMBB);
+
+ delete MI; // The pseudo instruction is gone now.
+ return BB;
+}
+
+
+//===----------------------------------------------------------------------===//
+// X86 Custom Lowering Hooks
+//===----------------------------------------------------------------------===//
+
/// LowerOperation - Provide custom lowering hooks for some operations.
///
SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
Op.getOperand(0), Op.getOperand(1));
ISD::CondCode SetCCOpcode = cast<CondCodeSDNode>(CC)->get();
bool isFP = MVT::isFloatingPoint(Op.getOperand(1).getValueType());
- unsigned X86CC = CCToX86CondCode(CC, isFP);
+ unsigned X86CC = getX86CC(CC, isFP);
if (X86CC != X86ISD::COND_INVALID) {
return DAG.getNode(X86ISD::SETCC, MVT::i8,
DAG.getConstant(X86CC, MVT::i8), Cond);
CC = Op0.getOperand(0);
Cond = Op0.getOperand(1);
isValid =
- !(isFPStack &&
- !SupportedByFPCMOV(cast<ConstantSDNode>(CC)->getSignExtended()));
+ !(isFPStack && !hasFPCMov(cast<ConstantSDNode>(CC)->getSignExtended()));
} else if (Op0.getOpcode() == ISD::SETCC) {
CC = Op0.getOperand(2);
bool isFP = MVT::isFloatingPoint(Op0.getOperand(1).getValueType());
- unsigned X86CC = CCToX86CondCode(CC, isFP);
+ unsigned X86CC = getX86CC(CC, isFP);
CC = DAG.getConstant(X86CC, MVT::i8);
Cond = DAG.getNode(X86ISD::CMP, MVT::Flag,
Op0.getOperand(0), Op0.getOperand(1));
} else if (Cond.getOpcode() == ISD::SETCC) {
CC = Cond.getOperand(2);
bool isFP = MVT::isFloatingPoint(Cond.getOperand(1).getValueType());
- unsigned X86CC = CCToX86CondCode(CC, isFP);
+ unsigned X86CC = getX86CC(CC, isFP);
CC = DAG.getConstant(X86CC, MVT::i8);
Cond = DAG.getNode(X86ISD::CMP, MVT::Flag,
Cond.getOperand(0), Cond.getOperand(1));
// Instruction list...
//
+// Pseudo-instructions:
def PHI : I<0, Pseudo, (ops variable_ops), "PHINODE", []>; // PHI node.
-def NOOP : I<0x90, RawFrm, (ops), "nop", []>; // nop
def ADJCALLSTACKDOWN : I<0, Pseudo, (ops i32imm:$amt), "#ADJCALLSTACKDOWN",
[(X86callseq_start imm:$amt)]>;
[(set FR64:$dst, (undef))]>, Requires<[HasSSE2]>;
+// CMOV* - Used to implement the SSE SELECT DAG operation. Expanded by the
+// scheduler into a branch sequence.
+let usesCustomDAGSchedInserter = 1 in { // Expanded by the scheduler.
+ def CMOV_FR32 : I<0, Pseudo,
+ (ops FR32:$dst, FR32:$t, FR32:$f, i8imm:$cond),
+ "#CMOV PSEUDO!",
+ [(set FR32:$dst, (X86cmov FR32:$t, FR32:$f, imm:$cond,
+ STATUS))]>;
+ def CMOV_FR64 : I<0, Pseudo,
+ (ops FR64:$dst, FR64:$t, FR64:$f, i8imm:$cond),
+ "#CMOV PSEUDO!",
+ [(set FR64:$dst, (X86cmov FR64:$t, FR64:$f, imm:$cond,
+ STATUS))]>;
+}
+
let isTerminator = 1 in
let Defs = [FP0, FP1, FP2, FP3, FP4, FP5, FP6] in
def FP_REG_KILL : I<0, Pseudo, (ops), "#FP_REG_KILL", []>;
+
+// Nop
+def NOOP : I<0x90, RawFrm, (ops), "nop", []>;
+
//===----------------------------------------------------------------------===//
// Control Flow Instructions...
//
class IBr<bits<8> opcode, dag ops, string asm, list<dag> pattern> :
I<opcode, RawFrm, ops, asm, pattern>;
+// Conditional branches
let isBarrier = 1 in
def JMP : IBr<0xE9, (ops brtarget:$dst), "jmp $dst", [(br bb:$dst)]>;
[(X86brcond bb:$dst, X86_COND_P, STATUS)]>, Imp<[STATUS],[]>, TB;
def JNP : IBr<0x8B, (ops brtarget:$dst), "jnp $dst",
[(X86brcond bb:$dst, X86_COND_NP, STATUS)]>, Imp<[STATUS],[]>, TB;
+def JO : IBr<0x80, (ops brtarget:$dst), "jo $dst",
+ [(X86brcond bb:$dst, X86_COND_O, STATUS)]>, Imp<[STATUS],[]>, TB;
+def JNO : IBr<0x81, (ops brtarget:$dst), "jno $dst",
+ [(X86brcond bb:$dst, X86_COND_NO, STATUS)]>, Imp<[STATUS],[]>, TB;
//===----------------------------------------------------------------------===//
// Call Instructions...