mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-08 19:25:47 +00:00
ptx: add analyze/insert/remove branch
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@128084 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -11,11 +11,15 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#define DEBUG_TYPE "ptx-instrinfo"
|
||||||
|
|
||||||
#include "PTX.h"
|
#include "PTX.h"
|
||||||
#include "PTXInstrInfo.h"
|
#include "PTXInstrInfo.h"
|
||||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||||
#include "llvm/CodeGen/SelectionDAG.h"
|
#include "llvm/CodeGen/SelectionDAG.h"
|
||||||
#include "llvm/CodeGen/SelectionDAGNodes.h"
|
#include "llvm/CodeGen/SelectionDAGNodes.h"
|
||||||
|
#include "llvm/Support/Debug.h"
|
||||||
|
#include "llvm/Support/raw_ostream.h"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
@@ -132,7 +136,6 @@ SubsumesPredicate(const SmallVectorImpl<MachineOperand> &Pred1,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool PTXInstrInfo::
|
bool PTXInstrInfo::
|
||||||
DefinesPredicate(MachineInstr *MI,
|
DefinesPredicate(MachineInstr *MI,
|
||||||
std::vector<MachineOperand> &Pred) const {
|
std::vector<MachineOperand> &Pred) const {
|
||||||
@@ -165,6 +168,127 @@ DefinesPredicate(MachineInstr *MI,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// branch support
|
||||||
|
|
||||||
|
bool PTXInstrInfo::
|
||||||
|
AnalyzeBranch(MachineBasicBlock &MBB,
|
||||||
|
MachineBasicBlock *&TBB,
|
||||||
|
MachineBasicBlock *&FBB,
|
||||||
|
SmallVectorImpl<MachineOperand> &Cond,
|
||||||
|
bool AllowModify) const {
|
||||||
|
// TODO implement cases when AllowModify is true
|
||||||
|
|
||||||
|
if (MBB.empty())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
MachineBasicBlock::const_iterator iter = MBB.end();
|
||||||
|
const MachineInstr& instLast1 = *--iter;
|
||||||
|
const TargetInstrDesc &desc1 = instLast1.getDesc();
|
||||||
|
// for special case that MBB has only 1 instruction
|
||||||
|
const bool IsSizeOne = MBB.size() == 1;
|
||||||
|
// if IsSizeOne is true, *--iter and instLast2 are invalid
|
||||||
|
// we put a dummy value in instLast2 and desc2 since they are used
|
||||||
|
const MachineInstr& instLast2 = IsSizeOne ? instLast1 : *--iter;
|
||||||
|
const TargetInstrDesc &desc2 = IsSizeOne ? desc1 : instLast2.getDesc();
|
||||||
|
|
||||||
|
DEBUG(dbgs() << "\n");
|
||||||
|
DEBUG(dbgs() << "AnalyzeBranch: opcode: " << instLast1.getOpcode() << "\n");
|
||||||
|
DEBUG(dbgs() << "AnalyzeBranch: MBB: " << MBB.getName().str() << "\n");
|
||||||
|
DEBUG(dbgs() << "AnalyzeBranch: TBB: " << TBB << "\n");
|
||||||
|
DEBUG(dbgs() << "AnalyzeBranch: FBB: " << FBB << "\n");
|
||||||
|
|
||||||
|
// this block ends with no branches
|
||||||
|
if (!IsAnyKindOfBranch(instLast1)) {
|
||||||
|
DEBUG(dbgs() << "AnalyzeBranch: ends with no branch\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this block ends with only an unconditional branch
|
||||||
|
if (desc1.isUnconditionalBranch() &&
|
||||||
|
// when IsSizeOne is true, it "absorbs" the evaluation of instLast2
|
||||||
|
(IsSizeOne || !IsAnyKindOfBranch(instLast2))) {
|
||||||
|
DEBUG(dbgs() << "AnalyzeBranch: ends with only uncond branch\n");
|
||||||
|
TBB = GetBranchTarget(instLast1);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this block ends with a conditional branch and
|
||||||
|
// it falls through to a successor block
|
||||||
|
if (desc1.isConditionalBranch() &&
|
||||||
|
IsAnySuccessorAlsoLayoutSuccessor(MBB)) {
|
||||||
|
DEBUG(dbgs() << "AnalyzeBranch: ends with cond branch and fall through\n");
|
||||||
|
TBB = GetBranchTarget(instLast1);
|
||||||
|
int i = instLast1.findFirstPredOperandIdx();
|
||||||
|
Cond.push_back(instLast1.getOperand(i));
|
||||||
|
Cond.push_back(instLast1.getOperand(i+1));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// when IsSizeOne is true, we are done
|
||||||
|
if (IsSizeOne)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// this block ends with a conditional branch
|
||||||
|
// followed by an unconditional branch
|
||||||
|
if (desc2.isConditionalBranch() &&
|
||||||
|
desc1.isUnconditionalBranch()) {
|
||||||
|
DEBUG(dbgs() << "AnalyzeBranch: ends with cond and uncond branch\n");
|
||||||
|
TBB = GetBranchTarget(instLast2);
|
||||||
|
FBB = GetBranchTarget(instLast1);
|
||||||
|
int i = instLast2.findFirstPredOperandIdx();
|
||||||
|
Cond.push_back(instLast2.getOperand(i));
|
||||||
|
Cond.push_back(instLast2.getOperand(i+1));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// branch cannot be understood
|
||||||
|
DEBUG(dbgs() << "AnalyzeBranch: cannot be understood\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned PTXInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
|
||||||
|
unsigned count;
|
||||||
|
for (count = 0; IsAnyKindOfBranch(MBB.back()); ++count)
|
||||||
|
MBB.pop_back();
|
||||||
|
DEBUG(dbgs() << "RemoveBranch: MBB: " << MBB.getName().str() << "\n");
|
||||||
|
DEBUG(dbgs() << "RemoveBranch: count: " << count << "\n");
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned PTXInstrInfo::
|
||||||
|
InsertBranch(MachineBasicBlock &MBB,
|
||||||
|
MachineBasicBlock *TBB,
|
||||||
|
MachineBasicBlock *FBB,
|
||||||
|
const SmallVectorImpl<MachineOperand> &Cond,
|
||||||
|
DebugLoc DL) const {
|
||||||
|
DEBUG(dbgs() << "InsertBranch: MBB: " << MBB.getName().str() << "\n");
|
||||||
|
DEBUG(if (TBB) dbgs() << "InsertBranch: TBB: "
|
||||||
|
<< TBB->getName().str() << "\n";
|
||||||
|
else dbgs() << "InsertBranch: TBB: (NULL)\n");
|
||||||
|
DEBUG(if (FBB) dbgs() << "InsertBranch: FBB: "
|
||||||
|
<< FBB->getName().str() << "\n";
|
||||||
|
else dbgs() << "InsertBranch: FBB: (NULL)\n");
|
||||||
|
DEBUG(dbgs() << "InsertBranch: Cond size: " << Cond.size() << "\n");
|
||||||
|
|
||||||
|
assert(TBB && "TBB is NULL");
|
||||||
|
|
||||||
|
if (FBB) {
|
||||||
|
BuildMI(&MBB, DL, get(PTX::BRAdp))
|
||||||
|
.addMBB(TBB).addReg(Cond[0].getReg()).addImm(Cond[1].getImm());
|
||||||
|
BuildMI(&MBB, DL, get(PTX::BRAd))
|
||||||
|
.addMBB(FBB).addReg(PTX::NoRegister).addImm(PTX::PRED_NORMAL);
|
||||||
|
return 2;
|
||||||
|
} else if (Cond.size()) {
|
||||||
|
BuildMI(&MBB, DL, get(PTX::BRAdp))
|
||||||
|
.addMBB(TBB).addReg(Cond[0].getReg()).addImm(Cond[1].getImm());
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
BuildMI(&MBB, DL, get(PTX::BRAd))
|
||||||
|
.addMBB(TBB).addReg(PTX::NoRegister).addImm(PTX::PRED_NORMAL);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// static helper routines
|
// static helper routines
|
||||||
|
|
||||||
MachineSDNode *PTXInstrInfo::
|
MachineSDNode *PTXInstrInfo::
|
||||||
@@ -187,7 +311,28 @@ GetPTXMachineNode(SelectionDAG *DAG, unsigned Opcode,
|
|||||||
|
|
||||||
void PTXInstrInfo::AddDefaultPredicate(MachineInstr *MI) {
|
void PTXInstrInfo::AddDefaultPredicate(MachineInstr *MI) {
|
||||||
if (MI->findFirstPredOperandIdx() == -1) {
|
if (MI->findFirstPredOperandIdx() == -1) {
|
||||||
MI->addOperand(MachineOperand::CreateReg(0, /*IsDef=*/false));
|
MI->addOperand(MachineOperand::CreateReg(PTX::NoRegister, /*IsDef=*/false));
|
||||||
MI->addOperand(MachineOperand::CreateImm(PTX::PRED_NORMAL));
|
MI->addOperand(MachineOperand::CreateImm(PTX::PRED_NORMAL));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PTXInstrInfo::IsAnyKindOfBranch(const MachineInstr& inst) {
|
||||||
|
const TargetInstrDesc &desc = inst.getDesc();
|
||||||
|
return desc.isTerminator() || desc.isBranch() || desc.isIndirectBranch();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PTXInstrInfo::
|
||||||
|
IsAnySuccessorAlsoLayoutSuccessor(const MachineBasicBlock& MBB) {
|
||||||
|
for (MachineBasicBlock::const_succ_iterator
|
||||||
|
i = MBB.succ_begin(), e = MBB.succ_end(); i != e; ++i)
|
||||||
|
if (MBB.isLayoutSuccessor((const MachineBasicBlock*) &*i))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
MachineBasicBlock *PTXInstrInfo::GetBranchTarget(const MachineInstr& inst) {
|
||||||
|
// FIXME So far all branch instructions put destination in 1st operand
|
||||||
|
const MachineOperand& target = inst.getOperand(0);
|
||||||
|
assert(target.isMBB() && "FIXME: detect branch target operand");
|
||||||
|
return target.getMBB();
|
||||||
|
}
|
||||||
|
@@ -70,6 +70,20 @@ public:
|
|||||||
// PTX is fully-predicable
|
// PTX is fully-predicable
|
||||||
virtual bool isPredicable(MachineInstr *MI) const { return true; }
|
virtual bool isPredicable(MachineInstr *MI) const { return true; }
|
||||||
|
|
||||||
|
// branch support
|
||||||
|
|
||||||
|
virtual bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
|
||||||
|
MachineBasicBlock *&FBB,
|
||||||
|
SmallVectorImpl<MachineOperand> &Cond,
|
||||||
|
bool AllowModify = false) const;
|
||||||
|
|
||||||
|
virtual unsigned RemoveBranch(MachineBasicBlock &MBB) const;
|
||||||
|
|
||||||
|
virtual unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
|
||||||
|
MachineBasicBlock *FBB,
|
||||||
|
const SmallVectorImpl<MachineOperand> &Cond,
|
||||||
|
DebugLoc DL) const;
|
||||||
|
|
||||||
// static helper routines
|
// static helper routines
|
||||||
|
|
||||||
static MachineSDNode *GetPTXMachineNode(SelectionDAG *DAG, unsigned Opcode,
|
static MachineSDNode *GetPTXMachineNode(SelectionDAG *DAG, unsigned Opcode,
|
||||||
@@ -81,6 +95,12 @@ public:
|
|||||||
SDValue Op1, SDValue Op2);
|
SDValue Op1, SDValue Op2);
|
||||||
|
|
||||||
static void AddDefaultPredicate(MachineInstr *MI);
|
static void AddDefaultPredicate(MachineInstr *MI);
|
||||||
|
|
||||||
|
static bool IsAnyKindOfBranch(const MachineInstr& inst);
|
||||||
|
|
||||||
|
static bool IsAnySuccessorAlsoLayoutSuccessor(const MachineBasicBlock& MBB);
|
||||||
|
|
||||||
|
static MachineBasicBlock *GetBranchTarget(const MachineInstr& inst);
|
||||||
}; // class PTXInstrInfo
|
}; // class PTXInstrInfo
|
||||||
} // namespace llvm
|
} // namespace llvm
|
||||||
|
|
||||||
|
@@ -575,10 +575,12 @@ def CVT_u32_pred
|
|||||||
|
|
||||||
///===- Control Flow Instructions -----------------------------------------===//
|
///===- Control Flow Instructions -----------------------------------------===//
|
||||||
|
|
||||||
let isBranch = 1, isTerminator = 1 in {
|
let isBranch = 1, isTerminator = 1, isBarrier = 1 in {
|
||||||
def BRAd
|
def BRAd
|
||||||
: InstPTX<(outs), (ins brtarget:$d), "bra\t$d", [(br bb:$d)]>;
|
: InstPTX<(outs), (ins brtarget:$d), "bra\t$d", [(br bb:$d)]>;
|
||||||
|
}
|
||||||
|
|
||||||
|
let isBranch = 1, isTerminator = 1 in {
|
||||||
// FIXME: should be able to write a pattern for brcond, but can't use
|
// FIXME: should be able to write a pattern for brcond, but can't use
|
||||||
// a two-value operand where a dag node expects two operands. :(
|
// a two-value operand where a dag node expects two operands. :(
|
||||||
// NOTE: ARM & PowerPC backend also report the same problem
|
// NOTE: ARM & PowerPC backend also report the same problem
|
||||||
|
@@ -10,7 +10,10 @@ loop:
|
|||||||
|
|
||||||
define ptx_device i32 @test_bra_cond_direct(i32 %x, i32 %y) {
|
define ptx_device i32 @test_bra_cond_direct(i32 %x, i32 %y) {
|
||||||
entry:
|
entry:
|
||||||
|
; CHECK: setp.le.u32 p0, r1, r2
|
||||||
%p = icmp ugt i32 %x, %y
|
%p = icmp ugt i32 %x, %y
|
||||||
|
; CHECK-NEXT: @p0 bra
|
||||||
|
; CHECK-NOT: bra
|
||||||
br i1 %p, label %clause.if, label %clause.else
|
br i1 %p, label %clause.if, label %clause.else
|
||||||
clause.if:
|
clause.if:
|
||||||
; CHECK: mov.u32 r0, r1
|
; CHECK: mov.u32 r0, r1
|
||||||
|
Reference in New Issue
Block a user