From af53a87052f41664ff5962731d0b64e3b51a5501 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sat, 4 Nov 2006 05:27:39 +0000 Subject: [PATCH] Go through all kinds of trouble to mark 'blr' as having a predicate operand that takes a register and condition code. Print these pieces of BLR the right way, even though it is currently set to 'always'. Next up: get the JIT encoding right, then enhance branch folding to produce predicated blr for simple examples. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@31449 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/PowerPC/PPC.h | 31 +++++++++++++++++++++------- lib/Target/PowerPC/PPCAsmPrinter.cpp | 30 +++++++++++++++++++++++++++ lib/Target/PowerPC/PPCInstrInfo.td | 13 ++++++++---- 3 files changed, 62 insertions(+), 12 deletions(-) diff --git a/lib/Target/PowerPC/PPC.h b/lib/Target/PowerPC/PPC.h index 8fef9662010..c8ea2829c46 100644 --- a/lib/Target/PowerPC/PPC.h +++ b/lib/Target/PowerPC/PPC.h @@ -17,13 +17,31 @@ #include -namespace llvm { -class PPCTargetMachine; -class FunctionPassManager; -class FunctionPass; -class MachineCodeEmitter; +// GCC #defines PPC on Linux but we use it as our namespace name +#undef PPC +namespace llvm { + class PPCTargetMachine; + class FunctionPassManager; + class FunctionPass; + class MachineCodeEmitter; + + namespace PPC { + /// Predicate - These are "(BO << 5) | BI" for various predicates. + enum Predicate { + PRED_ALWAYS = (20 << 5) | 0, + PRED_LT = (12 << 5) | 0, + PRED_LE = ( 4 << 5) | 1, + PRED_EQ = (12 << 5) | 2, + PRED_GE = ( 4 << 5) | 0, + PRED_GT = (12 << 5) | 1, + PRED_NE = ( 4 << 5) | 2, + PRED_UN = (12 << 5) | 3, + PRED_NU = ( 4 << 5) | 3 + }; + } + FunctionPass *createPPCBranchSelectionPass(); FunctionPass *createPPCISelDag(PPCTargetMachine &TM); FunctionPass *createPPCAsmPrinterPass(std::ostream &OS, @@ -34,9 +52,6 @@ void addPPCMachOObjectWriterPass(FunctionPassManager &FPM, std::ostream &o, PPCTargetMachine &tm); } // end namespace llvm; -// GCC #defines PPC on Linux but we use it as our namespace name -#undef PPC - // Defines symbolic names for PowerPC registers. This defines a mapping from // register name to register number. // diff --git a/lib/Target/PowerPC/PPCAsmPrinter.cpp b/lib/Target/PowerPC/PPCAsmPrinter.cpp index ee57cbaaba8..47056de2ab7 100644 --- a/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -236,6 +236,9 @@ namespace { printOperand(MI, OpNo+1); } + void printPredicateOperand(const MachineInstr *MI, unsigned OpNo, + const char *Modifier); + virtual bool runOnMachineFunction(MachineFunction &F) = 0; virtual bool doFinalization(Module &M) = 0; }; @@ -363,6 +366,33 @@ bool PPCAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, return false; } +void PPCAsmPrinter::printPredicateOperand(const MachineInstr *MI, unsigned OpNo, + const char *Modifier) { + assert(Modifier && "Must specify 'cc' or 'reg' as predicate op modifier!"); + unsigned Code = MI->getOperand(OpNo).getImm(); + if (!strcmp(Modifier, "cc")) { + switch ((PPC::Predicate)Code) { + case PPC::PRED_ALWAYS: return; // Don't print anything for always. + case PPC::PRED_LT: O << "lt"; return; + case PPC::PRED_LE: O << "le"; return; + case PPC::PRED_EQ: O << "eq"; return; + case PPC::PRED_GE: O << "ge"; return; + case PPC::PRED_GT: O << "gt"; return; + case PPC::PRED_NE: O << "ne"; return; + case PPC::PRED_UN: O << "un"; return; + case PPC::PRED_NU: O << "nu"; return; + } + + } else { + assert(!strcmp(Modifier, "reg") && + "Need to specify 'cc' or 'reg' as predicate op modifier!"); + // Don't print the register for 'always'. + if (Code == PPC::PRED_ALWAYS) return; + printOperand(MI, OpNo+1); + } +} + + /// printMachineInstruction -- Print out a single PowerPC MI in Darwin syntax to /// the current output stream. /// diff --git a/lib/Target/PowerPC/PPCInstrInfo.td b/lib/Target/PowerPC/PPCInstrInfo.td index 02b066f5825..81332c1acd1 100644 --- a/lib/Target/PowerPC/PPCInstrInfo.td +++ b/lib/Target/PowerPC/PPCInstrInfo.td @@ -255,9 +255,11 @@ def memrix : Operand { // memri where the imm is shifted 2 bits. let MIOperandInfo = (ops i32imm, ptr_rc); } -// PowerPC Predicate operand. 20 = always, CR0 is a dummy reg that doesn't -// matter. -def pred : PredicateOperand<(ops imm, CRRC), (ops 20, CR0)>; +// PowerPC Predicate operand. 640 = ((20<<5)|0) = always, CR0 is a dummy reg +// that doesn't matter. +def pred : PredicateOperand<(ops imm, CRRC), (ops (i32 640), CR0)> { + let PrintMethod = "printPredicateOperand"; +} // Define PowerPC specific addressing mode. def iaddr : ComplexPattern; @@ -315,10 +317,13 @@ let usesCustomDAGSchedInserter = 1, // Expanded by the scheduler. let isTerminator = 1, isBarrier = 1, noResults = 1, PPC970_Unit = 7 in { let isReturn = 1 in - def BLR : XLForm_2_ext<19, 16, 20, 0, 0, (ops), "blr", BrB, [(retflag)]>; + def BLR : XLForm_2_ext<19, 16, 20, 0, 0, + (ops pred:$p), + "b${p:cc}lr ${p:reg}", BrB, [(retflag)]>; def BCTR : XLForm_2_ext<19, 528, 20, 0, 0, (ops), "bctr", BrB, []>; } + let Defs = [LR] in def MovePCtoLR : Pseudo<(ops piclabel:$label), "bl $label", []>, PPC970_Unit_BRU; -- 2.34.1