Lower BR_JT on the XCore to a jump into a series of jump instructions.

llvm-svn: 96942
This commit is contained in:
Richard Osborne 2010-02-23 13:25:07 +00:00
parent 64810b7bc6
commit 7387249531
7 changed files with 259 additions and 5 deletions

View File

@ -27,6 +27,7 @@
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Target/TargetData.h"
@ -62,6 +63,11 @@ namespace {
}
void printMemOperand(const MachineInstr *MI, int opNum);
void printInlineJT(const MachineInstr *MI, int opNum,
const std::string &directive = ".jmptable");
void printInlineJT32(const MachineInstr *MI, int opNum) {
printInlineJT(MI, opNum, ".jmptable32");
}
void printOperand(const MachineInstr *MI, int opNum);
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
unsigned AsmVariant, const char *ExtraCode);
@ -257,6 +263,23 @@ void XCoreAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum)
printOperand(MI, opNum+1);
}
void XCoreAsmPrinter::
printInlineJT(const MachineInstr *MI, int opNum, const std::string &directive)
{
unsigned JTI = MI->getOperand(opNum).getIndex();
const MachineFunction *MF = MI->getParent()->getParent();
const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
O << "\t" << directive << " ";
for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
MachineBasicBlock *MBB = JTBBs[i];
if (i > 0)
O << ",";
O << *MBB->getSymbol(OutContext);
}
}
void XCoreAsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
const MachineOperand &MO = MI->getOperand(opNum);
switch (MO.getType()) {

View File

@ -29,6 +29,7 @@
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/CodeGen/ValueTypes.h"
@ -53,6 +54,8 @@ getTargetNodeName(unsigned Opcode) const
case XCoreISD::RETSP : return "XCoreISD::RETSP";
case XCoreISD::LADD : return "XCoreISD::LADD";
case XCoreISD::LSUB : return "XCoreISD::LSUB";
case XCoreISD::BR_JT : return "XCoreISD::BR_JT";
case XCoreISD::BR_JT32 : return "XCoreISD::BR_JT32";
default : return NULL;
}
}
@ -106,9 +109,8 @@ XCoreTargetLowering::XCoreTargetLowering(XCoreTargetMachine &XTM)
setOperationAction(ISD::TRAP, MVT::Other, Legal);
// Expand jump tables for now
setOperationAction(ISD::BR_JT, MVT::Other, Expand);
setOperationAction(ISD::JumpTable, MVT::i32, Custom);
// Jump tables.
setOperationAction(ISD::BR_JT, MVT::Other, Custom);
setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
setOperationAction(ISD::BlockAddress, MVT::i32 , Custom);
@ -158,6 +160,7 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) {
case ISD::BlockAddress: return LowerBlockAddress(Op, DAG);
case ISD::ConstantPool: return LowerConstantPool(Op, DAG);
case ISD::JumpTable: return LowerJumpTable(Op, DAG);
case ISD::BR_JT: return LowerBR_JT(Op, DAG);
case ISD::LOAD: return LowerLOAD(Op, DAG);
case ISD::STORE: return LowerSTORE(Op, DAG);
case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG);
@ -325,6 +328,30 @@ LowerJumpTable(SDValue Op, SelectionDAG &DAG)
return DAG.getNode(XCoreISD::DPRelativeWrapper, dl, MVT::i32, JTI);
}
SDValue XCoreTargetLowering::
LowerBR_JT(SDValue Op, SelectionDAG &DAG)
{
SDValue Chain = Op.getOperand(0);
SDValue Table = Op.getOperand(1);
SDValue Index = Op.getOperand(2);
DebugLoc dl = Op.getDebugLoc();
JumpTableSDNode *JT = cast<JumpTableSDNode>(Table);
unsigned JTI = JT->getIndex();
MachineFunction &MF = DAG.getMachineFunction();
const MachineJumpTableInfo *MJTI = MF.getJumpTableInfo();
SDValue TargetJT = DAG.getTargetJumpTable(JT->getIndex(), MVT::i32);
unsigned NumEntries = MJTI->getJumpTables()[JTI].MBBs.size();
if (NumEntries <= 32) {
return DAG.getNode(XCoreISD::BR_JT, dl, MVT::Other, Chain, TargetJT, Index);
}
assert((NumEntries >> 31) == 0);
SDValue ScaledIndex = DAG.getNode(ISD::SHL, dl, MVT::i32, Index,
DAG.getConstant(1, MVT::i32));
return DAG.getNode(XCoreISD::BR_JT32, dl, MVT::Other, Chain, TargetJT,
ScaledIndex);
}
static bool
IsWordAlignedBasePlusConstantOffset(SDValue Addr, SDValue &AlignedBase,
int64_t &Offset)

View File

@ -52,7 +52,13 @@ namespace llvm {
LADD,
// Corresponds to LSUB instruction
LSUB
LSUB,
// Jumptable branch.
BR_JT,
// Jumptable branch using long branches for each entry.
BR_JT32
};
}
@ -123,6 +129,7 @@ namespace llvm {
SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG);
SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG);
SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG);
SDValue LowerBR_JT(SDValue Op, SelectionDAG &DAG);
SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG);
SDValue LowerVAARG(SDValue Op, SelectionDAG &DAG);
SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG);

View File

@ -145,6 +145,11 @@ static inline bool IsCondBranch(unsigned BrOpc) {
return IsBRF(BrOpc) || IsBRT(BrOpc);
}
static inline bool IsBR_JT(unsigned BrOpc) {
return BrOpc == XCore::BR_JT
|| BrOpc == XCore::BR_JT32;
}
/// GetCondFromBranchOpc - Return the XCore CC that matches
/// the correspondent Branch instruction opcode.
static XCore::CondCode GetCondFromBranchOpc(unsigned BrOpc)
@ -271,6 +276,14 @@ XCoreInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
return false;
}
// Likewise if it ends with a branch table followed by an unconditional branch.
if (IsBR_JT(SecondLastInst->getOpcode()) && IsBRU(LastInst->getOpcode())) {
I = LastInst;
if (AllowModify)
I->eraseFromParent();
return true;
}
// Otherwise, can't handle this.
return true;
}

View File

@ -34,6 +34,15 @@ def XCoreBranchLink : SDNode<"XCoreISD::BL",SDT_XCoreBranchLink,
def XCoreRetsp : SDNode<"XCoreISD::RETSP", SDTNone,
[SDNPHasChain, SDNPOptInFlag]>;
def SDT_XCoreBR_JT : SDTypeProfile<0, 2,
[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
def XCoreBR_JT : SDNode<"XCoreISD::BR_JT", SDT_XCoreBR_JT,
[SDNPHasChain]>;
def XCoreBR_JT32 : SDNode<"XCoreISD::BR_JT32", SDT_XCoreBR_JT,
[SDNPHasChain]>;
def SDT_XCoreAddress : SDTypeProfile<1, 1,
[SDTCisSameAs<0, 1>, SDTCisPtrTy<0>]>;
@ -185,6 +194,15 @@ def MEMii : Operand<i32> {
let MIOperandInfo = (ops i32imm, i32imm);
}
// Jump tables.
def InlineJT : Operand<i32> {
let PrintMethod = "printInlineJT";
}
def InlineJT32 : Operand<i32> {
let PrintMethod = "printInlineJT32";
}
//===----------------------------------------------------------------------===//
// Instruction Class Templates
//===----------------------------------------------------------------------===//
@ -756,13 +774,23 @@ def CLZ_l2r : _FL2R<(outs GRRegs:$dst), (ins GRRegs:$src),
// One operand short
// TODO edu, eeu, waitet, waitef, freer, tstart, msync, mjoin, syncr, clrtp
// bru, setdp, setcp, setv, setev, kcall
// setdp, setcp, setv, setev, kcall
// dgetreg
let isBranch=1, isIndirectBranch=1, isTerminator=1 in
def BAU_1r : _F1R<(outs), (ins GRRegs:$addr),
"bau $addr",
[(brind GRRegs:$addr)]>;
let isBranch=1, isIndirectBranch=1, isTerminator=1, isBarrier = 1 in
def BR_JT : PseudoInstXCore<(outs), (ins InlineJT:$t, GRRegs:$i),
"bru $i\n$t",
[(XCoreBR_JT tjumptable:$t, GRRegs:$i)]>;
let isBranch=1, isIndirectBranch=1, isTerminator=1, isBarrier = 1 in
def BR_JT32 : PseudoInstXCore<(outs), (ins InlineJT32:$t, GRRegs:$i),
"bru $i\n$t",
[(XCoreBR_JT32 tjumptable:$t, GRRegs:$i)]>;
let Defs=[SP], neverHasSideEffects=1 in
def SETSP_1r : _F1R<(outs), (ins GRRegs:$src),
"set sp, $src",

View File

@ -0,0 +1,24 @@
; RUN: llc -march=xcore < %s | FileCheck %s
define i32 @switch(i32 %i) {
entry:
switch i32 %i, label %default [
i32 0, label %bb0
i32 1, label %bb1
i32 2, label %bb2
i32 3, label %bb3
]
; CHECK-NOT: shl
; CHECK: bru
; CHECK: .jmptable
bb0:
ret i32 0
bb1:
ret i32 1
bb2:
ret i32 2
bb3:
ret i32 3
default:
ret i32 4
}

View File

@ -0,0 +1,132 @@
; RUN: llc -march=xcore < %s | FileCheck %s
define i32 @switch(i32 %i) {
entry:
switch i32 %i, label %default [
i32 0, label %bb0
i32 1, label %bb1
i32 2, label %bb2
i32 3, label %bb3
i32 4, label %bb4
i32 5, label %bb5
i32 6, label %bb6
i32 7, label %bb7
i32 8, label %bb8
i32 9, label %bb9
i32 10, label %bb10
i32 11, label %bb11
i32 12, label %bb12
i32 13, label %bb13
i32 14, label %bb14
i32 15, label %bb15
i32 16, label %bb16
i32 17, label %bb17
i32 18, label %bb18
i32 19, label %bb19
i32 20, label %bb20
i32 21, label %bb21
i32 22, label %bb22
i32 23, label %bb23
i32 24, label %bb24
i32 25, label %bb25
i32 26, label %bb26
i32 27, label %bb27
i32 28, label %bb28
i32 29, label %bb29
i32 30, label %bb30
i32 31, label %bb31
i32 32, label %bb32
i32 33, label %bb33
i32 34, label %bb34
i32 35, label %bb35
i32 36, label %bb36
i32 37, label %bb37
i32 38, label %bb38
i32 39, label %bb39
]
; CHECK: shl
; CHECK: bru
; CHECK: .jmptable
bb0:
ret i32 0
bb1:
ret i32 1
bb2:
ret i32 2
bb3:
ret i32 3
bb4:
ret i32 4
bb5:
ret i32 5
bb6:
ret i32 6
bb7:
ret i32 7
bb8:
ret i32 8
bb9:
ret i32 9
bb10:
ret i32 0
bb11:
ret i32 1
bb12:
ret i32 2
bb13:
ret i32 3
bb14:
ret i32 4
bb15:
ret i32 5
bb16:
ret i32 6
bb17:
ret i32 7
bb18:
ret i32 8
bb19:
ret i32 9
bb20:
ret i32 0
bb21:
ret i32 1
bb22:
ret i32 2
bb23:
ret i32 3
bb24:
ret i32 4
bb25:
ret i32 5
bb26:
ret i32 6
bb27:
ret i32 7
bb28:
ret i32 8
bb29:
ret i32 9
bb30:
ret i32 0
bb31:
ret i32 1
bb32:
ret i32 2
bb33:
ret i32 3
bb34:
ret i32 4
bb35:
ret i32 5
bb36:
ret i32 6
bb37:
ret i32 7
bb38:
ret i32 8
bb39:
ret i32 9
default:
ret i32 0
}