mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-15 20:29:48 +00:00
SSE cmov support.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@25190 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
f710062bfb
commit
4a46080fe0
@ -17,8 +17,9 @@
|
||||
#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"
|
||||
@ -1140,14 +1141,34 @@ LowerFrameReturnAddress(bool isFrameAddress, SDOperand Chain, unsigned Depth,
|
||||
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) {
|
||||
@ -1192,11 +1213,10 @@ static unsigned CCToX86CondCode(SDOperand CC, bool 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;
|
||||
@ -1212,6 +1232,64 @@ static bool SupportedByFPCMOV(unsigned X86CC) {
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
@ -1383,7 +1461,7 @@ 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);
|
||||
@ -1475,12 +1553,11 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
|
||||
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));
|
||||
@ -1513,7 +1590,7 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
|
||||
} 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));
|
||||
|
@ -199,6 +199,9 @@ namespace llvm {
|
||||
LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
|
||||
SelectionDAG &DAG);
|
||||
|
||||
virtual MachineBasicBlock *InsertAtEndOfBasicBlock(MachineInstr *MI,
|
||||
MachineBasicBlock *MBB);
|
||||
|
||||
/// getTargetNodeName - This method returns the name of a target specific
|
||||
/// DAG node.
|
||||
virtual const char *getTargetNodeName(unsigned Opcode) const;
|
||||
|
@ -361,8 +361,8 @@ class Ii32<bits<8> o, Format f, dag ops, string asm, list<dag> pattern>
|
||||
// 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)]>;
|
||||
@ -388,10 +388,29 @@ def IMPLICIT_DEF_FR64 : I<0, Pseudo, (ops FR64:$dst),
|
||||
[(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...
|
||||
//
|
||||
@ -409,6 +428,7 @@ let isBranch = 1, isTerminator = 1, noResults = 1 in
|
||||
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)]>;
|
||||
|
||||
@ -442,6 +462,10 @@ def JP : IBr<0x8A, (ops brtarget:$dst), "jp $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...
|
||||
|
Loading…
Reference in New Issue
Block a user