mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 11:13:28 +01:00
SELECT_CC lowering
llvm-svn: 75948
This commit is contained in:
parent
769a8c2312
commit
e26fb377c5
@ -61,6 +61,14 @@ SystemZTargetLowering::SystemZTargetLowering(SystemZTargetMachine &tm) :
|
||||
setOperationAction(ISD::BRCOND, MVT::Other, Expand);
|
||||
setOperationAction(ISD::BR_CC, MVT::i32, Custom);
|
||||
setOperationAction(ISD::BR_CC, MVT::i64, Custom);
|
||||
|
||||
// FIXME: Can we lower these 2 efficiently?
|
||||
setOperationAction(ISD::SETCC, MVT::i32, Expand);
|
||||
setOperationAction(ISD::SETCC, MVT::i64, Expand);
|
||||
setOperationAction(ISD::SELECT, MVT::i32, Expand);
|
||||
setOperationAction(ISD::SELECT, MVT::i64, Expand);
|
||||
setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
|
||||
setOperationAction(ISD::SELECT_CC, MVT::i64, Custom);
|
||||
}
|
||||
|
||||
SDValue SystemZTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
|
||||
@ -69,6 +77,7 @@ SDValue SystemZTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
|
||||
case ISD::RET: return LowerRET(Op, DAG);
|
||||
case ISD::CALL: return LowerCALL(Op, DAG);
|
||||
case ISD::BR_CC: return LowerBR_CC(Op, DAG);
|
||||
case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG);
|
||||
default:
|
||||
assert(0 && "unimplemented operand");
|
||||
return SDValue();
|
||||
@ -472,6 +481,27 @@ SDValue SystemZTargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) {
|
||||
Chain, Dest, SystemZCC, Flag);
|
||||
}
|
||||
|
||||
SDValue SystemZTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) {
|
||||
SDValue LHS = Op.getOperand(0);
|
||||
SDValue RHS = Op.getOperand(1);
|
||||
SDValue TrueV = Op.getOperand(2);
|
||||
SDValue FalseV = Op.getOperand(3);
|
||||
ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get();
|
||||
DebugLoc dl = Op.getDebugLoc();
|
||||
|
||||
SDValue SystemZCC;
|
||||
SDValue Flag = EmitCmp(LHS, RHS, CC, SystemZCC, DAG);
|
||||
|
||||
SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Flag);
|
||||
SmallVector<SDValue, 4> Ops;
|
||||
Ops.push_back(TrueV);
|
||||
Ops.push_back(FalseV);
|
||||
Ops.push_back(SystemZCC);
|
||||
Ops.push_back(Flag);
|
||||
|
||||
return DAG.getNode(SystemZISD::SELECT, dl, VTs, &Ops[0], Ops.size());
|
||||
}
|
||||
|
||||
|
||||
const char *SystemZTargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||
switch (Opcode) {
|
||||
@ -480,7 +510,70 @@ const char *SystemZTargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||
case SystemZISD::BRCOND: return "SystemZISD::BRCOND";
|
||||
case SystemZISD::CMP: return "SystemZISD::CMP";
|
||||
case SystemZISD::UCMP: return "SystemZISD::UCMP";
|
||||
case SystemZISD::SELECT: return "SystemZISD::SELECT";
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Other Lowering Code
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
MachineBasicBlock*
|
||||
SystemZTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
|
||||
MachineBasicBlock *BB) const {
|
||||
const SystemZInstrInfo &TII = *TM.getInstrInfo();
|
||||
DebugLoc dl = MI->getDebugLoc();
|
||||
assert((MI->getOpcode() == SystemZ::Select32 ||
|
||||
MI->getOpcode() == SystemZ::Select64) &&
|
||||
"Unexpected instr type to insert");
|
||||
|
||||
// To "insert" a SELECT 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();
|
||||
MachineFunction::iterator I = BB;
|
||||
++I;
|
||||
|
||||
// thisMBB:
|
||||
// ...
|
||||
// TrueVal = ...
|
||||
// cmpTY ccX, r1, r2
|
||||
// jCC copy1MBB
|
||||
// fallthrough --> copy0MBB
|
||||
MachineBasicBlock *thisMBB = BB;
|
||||
MachineFunction *F = BB->getParent();
|
||||
MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);
|
||||
MachineBasicBlock *copy1MBB = F->CreateMachineBasicBlock(LLVM_BB);
|
||||
SystemZCC::CondCodes CC = (SystemZCC::CondCodes)MI->getOperand(3).getImm();
|
||||
BuildMI(BB, dl, TII.getBrCond(CC)).addMBB(copy1MBB);
|
||||
F->insert(I, copy0MBB);
|
||||
F->insert(I, copy1MBB);
|
||||
// Update machine-CFG edges by transferring all successors of the current
|
||||
// block to the new block which will contain the Phi node for the select.
|
||||
copy1MBB->transferSuccessors(BB);
|
||||
// Next, add the true and fallthrough blocks as its successors.
|
||||
BB->addSuccessor(copy0MBB);
|
||||
BB->addSuccessor(copy1MBB);
|
||||
|
||||
// copy0MBB:
|
||||
// %FalseValue = ...
|
||||
// # fallthrough to copy1MBB
|
||||
BB = copy0MBB;
|
||||
|
||||
// Update machine-CFG edges
|
||||
BB->addSuccessor(copy1MBB);
|
||||
|
||||
// copy1MBB:
|
||||
// %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ]
|
||||
// ...
|
||||
BB = copy1MBB;
|
||||
BuildMI(BB, dl, TII.get(SystemZ::PHI),
|
||||
MI->getOperand(0).getReg())
|
||||
.addReg(MI->getOperand(2).getReg()).addMBB(copy0MBB)
|
||||
.addReg(MI->getOperand(1).getReg()).addMBB(thisMBB);
|
||||
|
||||
F->DeleteMachineInstr(MI); // The pseudo instruction is gone now.
|
||||
return BB;
|
||||
}
|
||||
|
@ -32,9 +32,18 @@ namespace llvm {
|
||||
/// instruction, which includes a bunch of information.
|
||||
CALL,
|
||||
|
||||
/// CMP, UCMP - Compare instruction
|
||||
CMP,
|
||||
UCMP,
|
||||
BRCOND
|
||||
|
||||
/// BRCOND - Conditional branch. Operand 0 is chain operand, operand 1 is
|
||||
/// the block to branch if condition is true, operand 2 is condition code
|
||||
/// and operand 3 is the flag operand produced by a CMP instruction.
|
||||
BRCOND,
|
||||
|
||||
/// SELECT - Operands 0 and 1 are selection variables, operand 2 is
|
||||
/// condition code and operand 3 is the flag operand.
|
||||
SELECT
|
||||
};
|
||||
}
|
||||
|
||||
@ -56,6 +65,7 @@ namespace llvm {
|
||||
SDValue LowerRET(SDValue Op, SelectionDAG &DAG);
|
||||
SDValue LowerCALL(SDValue Op, SelectionDAG &DAG);
|
||||
SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG);
|
||||
SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG);
|
||||
|
||||
SDValue LowerCCCArguments(SDValue Op, SelectionDAG &DAG);
|
||||
SDValue LowerCCCCallTo(SDValue Op, SelectionDAG &DAG, unsigned CC);
|
||||
@ -67,6 +77,10 @@ namespace llvm {
|
||||
ISD::CondCode CC, SDValue &SystemZCC,
|
||||
SelectionDAG &DAG);
|
||||
|
||||
|
||||
MachineBasicBlock* EmitInstrWithCustomInserter(MachineInstr *MI,
|
||||
MachineBasicBlock *BB) const;
|
||||
|
||||
private:
|
||||
const SystemZSubtarget &Subtarget;
|
||||
const SystemZTargetMachine &TM;
|
||||
|
@ -239,3 +239,32 @@ SystemZInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const TargetInstrDesc&
|
||||
SystemZInstrInfo::getBrCond(SystemZCC::CondCodes CC) const {
|
||||
unsigned Opc;
|
||||
switch (CC) {
|
||||
default:
|
||||
assert(0 && "Unknown condition code!");
|
||||
case SystemZCC::E:
|
||||
Opc = SystemZ::JE;
|
||||
break;
|
||||
case SystemZCC::NE:
|
||||
Opc = SystemZ::JNE;
|
||||
break;
|
||||
case SystemZCC::H:
|
||||
Opc = SystemZ::JH;
|
||||
break;
|
||||
case SystemZCC::L:
|
||||
Opc = SystemZ::JL;
|
||||
break;
|
||||
case SystemZCC::HE:
|
||||
Opc = SystemZ::JHE;
|
||||
break;
|
||||
case SystemZCC::LE:
|
||||
Opc = SystemZ::JLE;
|
||||
break;
|
||||
}
|
||||
|
||||
return get(Opc);
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
#ifndef LLVM_TARGET_SYSTEMZINSTRINFO_H
|
||||
#define LLVM_TARGET_SYSTEMZINSTRINFO_H
|
||||
|
||||
#include "SystemZ.h"
|
||||
#include "SystemZRegisterInfo.h"
|
||||
#include "llvm/ADT/IndexedMap.h"
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
@ -65,6 +66,7 @@ public:
|
||||
MachineBasicBlock *FBB,
|
||||
const SmallVectorImpl<MachineOperand> &Cond) const;
|
||||
|
||||
const TargetInstrDesc& getBrCond(SystemZCC::CondCodes CC) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -31,6 +31,10 @@ def SDT_CmpTest : SDTypeProfile<0, 2, [SDTCisSameAs<0, 1>]>;
|
||||
def SDT_BrCond : SDTypeProfile<0, 2,
|
||||
[SDTCisVT<0, OtherVT>,
|
||||
SDTCisI8<1>]>;
|
||||
def SDT_SelectCC : SDTypeProfile<1, 3,
|
||||
[SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>,
|
||||
SDTCisI8<3>]>;
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// SystemZ Specific Node Definitions.
|
||||
@ -49,6 +53,7 @@ def SystemZcmp : SDNode<"SystemZISD::CMP", SDT_CmpTest, [SDNPOutFlag]>;
|
||||
def SystemZucmp : SDNode<"SystemZISD::UCMP", SDT_CmpTest, [SDNPOutFlag]>;
|
||||
def SystemZbrcond : SDNode<"SystemZISD::BRCOND", SDT_BrCond,
|
||||
[SDNPHasChain, SDNPInFlag]>;
|
||||
def SystemZselect : SDNode<"SystemZISD::SELECT", SDT_SelectCC, [SDNPInFlag]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Instruction Pattern Stuff.
|
||||
@ -236,6 +241,17 @@ def ADJCALLSTACKUP : Pseudo<(outs), (ins i64imm:$amt1, i64imm:$amt2),
|
||||
"#ADJCALLSTACKUP",
|
||||
[(SystemZcallseq_end timm:$amt1, timm:$amt2)]>;
|
||||
|
||||
let usesCustomDAGSchedInserter = 1 in {
|
||||
def Select32 : Pseudo<(outs GR32:$dst), (ins GR32:$src1, GR32:$src2, i8imm:$cc),
|
||||
"# Select32 PSEUDO",
|
||||
[(set GR32:$dst,
|
||||
(SystemZselect GR32:$src1, GR32:$src2, imm:$cc))]>;
|
||||
def Select64 : Pseudo<(outs GR64:$dst), (ins GR64:$src1, GR64:$src2, i8imm:$cc),
|
||||
"# Select64 PSEUDO",
|
||||
[(set GR64:$dst,
|
||||
(SystemZselect GR64:$src1, GR64:$src2, imm:$cc))]>;
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Control Flow Instructions...
|
||||
|
Loading…
Reference in New Issue
Block a user