2012-02-18 12:03:15 +00:00
|
|
|
//===-- PPCInstrInfo.cpp - PowerPC Instruction Information ----------------===//
|
2005-04-21 23:30:14 +00:00
|
|
|
//
|
2004-08-17 04:55:41 +00:00
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
2007-12-29 20:36:04 +00:00
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
2005-04-21 23:30:14 +00:00
|
|
|
//
|
2004-08-17 04:55:41 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file contains the PowerPC implementation of the TargetInstrInfo class.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2005-10-14 23:59:06 +00:00
|
|
|
#include "PPCInstrInfo.h"
|
2012-12-03 16:50:05 +00:00
|
|
|
#include "MCTargetDesc/PPCPredicates.h"
|
2011-07-11 03:57:24 +00:00
|
|
|
#include "PPC.h"
|
2012-12-03 16:50:05 +00:00
|
|
|
#include "PPCHazardRecognizers.h"
|
2008-01-01 21:11:32 +00:00
|
|
|
#include "PPCInstrBuilder.h"
|
2008-03-03 22:19:16 +00:00
|
|
|
#include "PPCMachineFunctionInfo.h"
|
2006-06-17 00:01:04 +00:00
|
|
|
#include "PPCTargetMachine.h"
|
2012-12-03 16:50:05 +00:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2014-01-07 11:48:04 +00:00
|
|
|
#include "llvm/ADT/Statistic.h"
|
[PowerPC] Select between VSX A-type and M-type FMA instructions just before RA
The VSX instruction set has two types of FMA instructions: A-type (where the
addend is taken from the output register) and M-type (where one of the product
operands is taken from the output register). This adds a small pass that runs
just after MI scheduling (and, thus, just before register allocation) that
mutates A-type instructions (that are created during isel) into M-type
instructions when:
1. This will eliminate an otherwise-necessary copy of the addend
2. One of the product operands is killed by the instruction
The "right" moment to make this decision is in between scheduling and register
allocation, because only there do we know whether or not one of the product
operands is killed by any particular instruction. Unfortunately, this also
makes the implementation somewhat complicated, because the MIs are not in SSA
form and we need to preserve the LiveIntervals analysis.
As a simple example, if we have:
%vreg5<def> = COPY %vreg9; VSLRC:%vreg5,%vreg9
%vreg5<def,tied1> = XSMADDADP %vreg5<tied0>, %vreg17, %vreg16,
%RM<imp-use>; VSLRC:%vreg5,%vreg17,%vreg16
...
%vreg9<def,tied1> = XSMADDADP %vreg9<tied0>, %vreg17, %vreg19,
%RM<imp-use>; VSLRC:%vreg9,%vreg17,%vreg19
...
We can eliminate the copy by changing from the A-type to the
M-type instruction. This means:
%vreg5<def,tied1> = XSMADDADP %vreg5<tied0>, %vreg17, %vreg16,
%RM<imp-use>; VSLRC:%vreg5,%vreg17,%vreg16
is replaced by:
%vreg16<def,tied1> = XSMADDMDP %vreg16<tied0>, %vreg18, %vreg9,
%RM<imp-use>; VSLRC:%vreg16,%vreg18,%vreg9
and we remove: %vreg5<def> = COPY %vreg9; VSLRC:%vreg5,%vreg9
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204768 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-25 23:29:21 +00:00
|
|
|
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
|
2010-07-16 18:22:00 +00:00
|
|
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
2013-04-08 16:24:03 +00:00
|
|
|
#include "llvm/CodeGen/MachineFunctionPass.h"
|
2004-08-17 04:55:41 +00:00
|
|
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
2010-07-16 18:22:00 +00:00
|
|
|
#include "llvm/CodeGen/MachineMemOperand.h"
|
2010-02-26 21:09:24 +00:00
|
|
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
2012-04-01 19:22:40 +00:00
|
|
|
#include "llvm/CodeGen/PseudoSourceValue.h"
|
2014-06-12 21:48:52 +00:00
|
|
|
#include "llvm/CodeGen/ScheduleDAG.h"
|
[PowerPC] Select between VSX A-type and M-type FMA instructions just before RA
The VSX instruction set has two types of FMA instructions: A-type (where the
addend is taken from the output register) and M-type (where one of the product
operands is taken from the output register). This adds a small pass that runs
just after MI scheduling (and, thus, just before register allocation) that
mutates A-type instructions (that are created during isel) into M-type
instructions when:
1. This will eliminate an otherwise-necessary copy of the addend
2. One of the product operands is killed by the instruction
The "right" moment to make this decision is in between scheduling and register
allocation, because only there do we know whether or not one of the product
operands is killed by any particular instruction. Unfortunately, this also
makes the implementation somewhat complicated, because the MIs are not in SSA
form and we need to preserve the LiveIntervals analysis.
As a simple example, if we have:
%vreg5<def> = COPY %vreg9; VSLRC:%vreg5,%vreg9
%vreg5<def,tied1> = XSMADDADP %vreg5<tied0>, %vreg17, %vreg16,
%RM<imp-use>; VSLRC:%vreg5,%vreg17,%vreg16
...
%vreg9<def,tied1> = XSMADDADP %vreg9<tied0>, %vreg17, %vreg19,
%RM<imp-use>; VSLRC:%vreg9,%vreg17,%vreg19
...
We can eliminate the copy by changing from the A-type to the
M-type instruction. This means:
%vreg5<def,tied1> = XSMADDADP %vreg5<tied0>, %vreg17, %vreg16,
%RM<imp-use>; VSLRC:%vreg5,%vreg17,%vreg16
is replaced by:
%vreg16<def,tied1> = XSMADDMDP %vreg16<tied0>, %vreg18, %vreg9,
%RM<imp-use>; VSLRC:%vreg16,%vreg18,%vreg9
and we remove: %vreg5<def> = COPY %vreg9; VSLRC:%vreg5,%vreg9
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204768 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-25 23:29:21 +00:00
|
|
|
#include "llvm/CodeGen/SlotIndexes.h"
|
2011-07-11 03:57:24 +00:00
|
|
|
#include "llvm/MC/MCAsmInfo.h"
|
2008-03-04 23:13:51 +00:00
|
|
|
#include "llvm/Support/CommandLine.h"
|
[PowerPC] Select between VSX A-type and M-type FMA instructions just before RA
The VSX instruction set has two types of FMA instructions: A-type (where the
addend is taken from the output register) and M-type (where one of the product
operands is taken from the output register). This adds a small pass that runs
just after MI scheduling (and, thus, just before register allocation) that
mutates A-type instructions (that are created during isel) into M-type
instructions when:
1. This will eliminate an otherwise-necessary copy of the addend
2. One of the product operands is killed by the instruction
The "right" moment to make this decision is in between scheduling and register
allocation, because only there do we know whether or not one of the product
operands is killed by any particular instruction. Unfortunately, this also
makes the implementation somewhat complicated, because the MIs are not in SSA
form and we need to preserve the LiveIntervals analysis.
As a simple example, if we have:
%vreg5<def> = COPY %vreg9; VSLRC:%vreg5,%vreg9
%vreg5<def,tied1> = XSMADDADP %vreg5<tied0>, %vreg17, %vreg16,
%RM<imp-use>; VSLRC:%vreg5,%vreg17,%vreg16
...
%vreg9<def,tied1> = XSMADDADP %vreg9<tied0>, %vreg17, %vreg19,
%RM<imp-use>; VSLRC:%vreg9,%vreg17,%vreg19
...
We can eliminate the copy by changing from the A-type to the
M-type instruction. This means:
%vreg5<def,tied1> = XSMADDADP %vreg5<tied0>, %vreg17, %vreg16,
%RM<imp-use>; VSLRC:%vreg5,%vreg17,%vreg16
is replaced by:
%vreg16<def,tied1> = XSMADDMDP %vreg16<tied0>, %vreg18, %vreg9,
%RM<imp-use>; VSLRC:%vreg16,%vreg18,%vreg9
and we remove: %vreg5<def> = COPY %vreg9; VSLRC:%vreg5,%vreg9
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204768 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-25 23:29:21 +00:00
|
|
|
#include "llvm/Support/Debug.h"
|
2009-07-08 20:53:28 +00:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2011-08-24 18:08:43 +00:00
|
|
|
#include "llvm/Support/TargetRegistry.h"
|
2009-07-08 20:53:28 +00:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2004-08-17 04:55:41 +00:00
|
|
|
|
2010-04-15 17:20:57 +00:00
|
|
|
using namespace llvm;
|
2008-03-04 23:13:51 +00:00
|
|
|
|
2014-04-21 22:55:11 +00:00
|
|
|
#define DEBUG_TYPE "ppc-instr-info"
|
|
|
|
|
2014-04-22 02:03:14 +00:00
|
|
|
#define GET_INSTRMAP_INFO
|
|
|
|
#define GET_INSTRINFO_CTOR_DTOR
|
|
|
|
#include "PPCGenInstrInfo.inc"
|
|
|
|
|
2012-06-08 15:38:25 +00:00
|
|
|
static cl::
|
2012-06-08 19:19:53 +00:00
|
|
|
opt<bool> DisableCTRLoopAnal("disable-ppc-ctrloop-analysis", cl::Hidden,
|
|
|
|
cl::desc("Disable analysis for CTR loops"));
|
2012-06-08 15:38:25 +00:00
|
|
|
|
2013-04-19 22:08:38 +00:00
|
|
|
static cl::opt<bool> DisableCmpOpt("disable-ppc-cmp-opt",
|
2013-04-18 22:54:25 +00:00
|
|
|
cl::desc("Disable compare instruction optimization"), cl::Hidden);
|
|
|
|
|
[PowerPC] Select between VSX A-type and M-type FMA instructions just before RA
The VSX instruction set has two types of FMA instructions: A-type (where the
addend is taken from the output register) and M-type (where one of the product
operands is taken from the output register). This adds a small pass that runs
just after MI scheduling (and, thus, just before register allocation) that
mutates A-type instructions (that are created during isel) into M-type
instructions when:
1. This will eliminate an otherwise-necessary copy of the addend
2. One of the product operands is killed by the instruction
The "right" moment to make this decision is in between scheduling and register
allocation, because only there do we know whether or not one of the product
operands is killed by any particular instruction. Unfortunately, this also
makes the implementation somewhat complicated, because the MIs are not in SSA
form and we need to preserve the LiveIntervals analysis.
As a simple example, if we have:
%vreg5<def> = COPY %vreg9; VSLRC:%vreg5,%vreg9
%vreg5<def,tied1> = XSMADDADP %vreg5<tied0>, %vreg17, %vreg16,
%RM<imp-use>; VSLRC:%vreg5,%vreg17,%vreg16
...
%vreg9<def,tied1> = XSMADDADP %vreg9<tied0>, %vreg17, %vreg19,
%RM<imp-use>; VSLRC:%vreg9,%vreg17,%vreg19
...
We can eliminate the copy by changing from the A-type to the
M-type instruction. This means:
%vreg5<def,tied1> = XSMADDADP %vreg5<tied0>, %vreg17, %vreg16,
%RM<imp-use>; VSLRC:%vreg5,%vreg17,%vreg16
is replaced by:
%vreg16<def,tied1> = XSMADDMDP %vreg16<tied0>, %vreg18, %vreg9,
%RM<imp-use>; VSLRC:%vreg16,%vreg18,%vreg9
and we remove: %vreg5<def> = COPY %vreg9; VSLRC:%vreg5,%vreg9
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204768 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-25 23:29:21 +00:00
|
|
|
static cl::opt<bool> DisableVSXFMAMutate("disable-ppc-vsx-fma-mutation",
|
|
|
|
cl::desc("Disable VSX FMA instruction mutation"), cl::Hidden);
|
|
|
|
|
2014-03-27 22:46:28 +00:00
|
|
|
static cl::opt<bool> VSXSelfCopyCrash("crash-on-ppc-vsx-self-copy",
|
|
|
|
cl::desc("Causes the backend to crash instead of generating a nop VSX copy"),
|
|
|
|
cl::Hidden);
|
|
|
|
|
2013-11-19 00:57:56 +00:00
|
|
|
// Pin the vtable to this file.
|
|
|
|
void PPCInstrInfo::anchor() {}
|
|
|
|
|
2014-06-12 21:48:52 +00:00
|
|
|
PPCInstrInfo::PPCInstrInfo(PPCSubtarget &STI)
|
|
|
|
: PPCGenInstrInfo(PPC::ADJCALLSTACKDOWN, PPC::ADJCALLSTACKUP),
|
|
|
|
Subtarget(STI), RI(STI) {}
|
2006-06-17 00:01:04 +00:00
|
|
|
|
Various bits of framework needed for precise machine-level selection
DAG scheduling during isel. Most new functionality is currently
guarded by -enable-sched-cycles and -enable-sched-hazard.
Added InstrItineraryData::IssueWidth field, currently derived from
ARM itineraries, but could be initialized differently on other targets.
Added ScheduleHazardRecognizer::MaxLookAhead to indicate whether it is
active, and if so how many cycles of state it holds.
Added SchedulingPriorityQueue::HasReadyFilter to allowing gating entry
into the scheduler's available queue.
ScoreboardHazardRecognizer now accesses the ScheduleDAG in order to
get information about it's SUnits, provides RecedeCycle for bottom-up
scheduling, correctly computes scoreboard depth, tracks IssueCount, and
considers potential stall cycles when checking for hazards.
ScheduleDAGRRList now models machine cycles and hazards (under
flags). It tracks MinAvailableCycle, drives the hazard recognizer and
priority queue's ready filter, manages a new PendingQueue, properly
accounts for stall cycles, etc.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@122541 91177308-0d34-0410-b5e6-96231b3b80d8
2010-12-24 05:03:26 +00:00
|
|
|
/// CreateTargetHazardRecognizer - Return the hazard recognizer to use for
|
|
|
|
/// this target when scheduling the DAG.
|
2014-06-13 22:38:52 +00:00
|
|
|
ScheduleHazardRecognizer *
|
|
|
|
PPCInstrInfo::CreateTargetHazardRecognizer(const TargetSubtargetInfo *STI,
|
|
|
|
const ScheduleDAG *DAG) const {
|
|
|
|
unsigned Directive =
|
|
|
|
static_cast<const PPCSubtarget *>(STI)->getDarwinDirective();
|
2012-08-28 16:12:39 +00:00
|
|
|
if (Directive == PPC::DIR_440 || Directive == PPC::DIR_A2 ||
|
|
|
|
Directive == PPC::DIR_E500mc || Directive == PPC::DIR_E5500) {
|
2014-06-13 22:38:52 +00:00
|
|
|
const InstrItineraryData *II =
|
|
|
|
&static_cast<const PPCSubtarget *>(STI)->getInstrItineraryData();
|
2013-12-02 23:52:46 +00:00
|
|
|
return new ScoreboardHazardRecognizer(II, DAG);
|
2011-10-17 04:03:49 +00:00
|
|
|
}
|
2011-12-02 04:58:02 +00:00
|
|
|
|
2014-06-13 22:38:52 +00:00
|
|
|
return TargetInstrInfo::CreateTargetHazardRecognizer(STI, DAG);
|
Various bits of framework needed for precise machine-level selection
DAG scheduling during isel. Most new functionality is currently
guarded by -enable-sched-cycles and -enable-sched-hazard.
Added InstrItineraryData::IssueWidth field, currently derived from
ARM itineraries, but could be initialized differently on other targets.
Added ScheduleHazardRecognizer::MaxLookAhead to indicate whether it is
active, and if so how many cycles of state it holds.
Added SchedulingPriorityQueue::HasReadyFilter to allowing gating entry
into the scheduler's available queue.
ScoreboardHazardRecognizer now accesses the ScheduleDAG in order to
get information about it's SUnits, provides RecedeCycle for bottom-up
scheduling, correctly computes scoreboard depth, tracks IssueCount, and
considers potential stall cycles when checking for hazards.
ScheduleDAGRRList now models machine cycles and hazards (under
flags). It tracks MinAvailableCycle, drives the hazard recognizer and
priority queue's ready filter, manages a new PendingQueue, properly
accounts for stall cycles, etc.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@122541 91177308-0d34-0410-b5e6-96231b3b80d8
2010-12-24 05:03:26 +00:00
|
|
|
}
|
|
|
|
|
2011-12-02 04:58:02 +00:00
|
|
|
/// CreateTargetPostRAHazardRecognizer - Return the postRA hazard recognizer
|
|
|
|
/// to use for this target when scheduling the DAG.
|
|
|
|
ScheduleHazardRecognizer *PPCInstrInfo::CreateTargetPostRAHazardRecognizer(
|
|
|
|
const InstrItineraryData *II,
|
|
|
|
const ScheduleDAG *DAG) const {
|
2014-06-12 21:48:52 +00:00
|
|
|
unsigned Directive =
|
|
|
|
DAG->TM.getSubtarget<PPCSubtarget>().getDarwinDirective();
|
2011-12-02 04:58:02 +00:00
|
|
|
|
2014-06-26 13:36:19 +00:00
|
|
|
if (Directive == PPC::DIR_PWR7 || Directive == PPC::DIR_PWR8)
|
2013-12-12 00:19:11 +00:00
|
|
|
return new PPCDispatchGroupSBHazardRecognizer(II, DAG);
|
|
|
|
|
2011-12-02 04:58:02 +00:00
|
|
|
// Most subtargets use a PPC970 recognizer.
|
2012-08-28 16:12:39 +00:00
|
|
|
if (Directive != PPC::DIR_440 && Directive != PPC::DIR_A2 &&
|
|
|
|
Directive != PPC::DIR_E500mc && Directive != PPC::DIR_E5500) {
|
2014-06-12 21:48:52 +00:00
|
|
|
assert(DAG->TII && "No InstrInfo?");
|
2011-12-02 04:58:02 +00:00
|
|
|
|
2014-06-12 21:48:52 +00:00
|
|
|
return new PPCHazardRecognizer970(*DAG);
|
2011-12-02 04:58:02 +00:00
|
|
|
}
|
|
|
|
|
2013-12-02 23:52:46 +00:00
|
|
|
return new ScoreboardHazardRecognizer(II, DAG);
|
2011-12-02 04:58:02 +00:00
|
|
|
}
|
2012-06-19 21:14:34 +00:00
|
|
|
|
2013-12-12 00:19:11 +00:00
|
|
|
|
|
|
|
int PPCInstrInfo::getOperandLatency(const InstrItineraryData *ItinData,
|
|
|
|
const MachineInstr *DefMI, unsigned DefIdx,
|
|
|
|
const MachineInstr *UseMI,
|
|
|
|
unsigned UseIdx) const {
|
|
|
|
int Latency = PPCGenInstrInfo::getOperandLatency(ItinData, DefMI, DefIdx,
|
|
|
|
UseMI, UseIdx);
|
|
|
|
|
|
|
|
const MachineOperand &DefMO = DefMI->getOperand(DefIdx);
|
|
|
|
unsigned Reg = DefMO.getReg();
|
|
|
|
|
|
|
|
const TargetRegisterInfo *TRI = &getRegisterInfo();
|
|
|
|
bool IsRegCR;
|
|
|
|
if (TRI->isVirtualRegister(Reg)) {
|
|
|
|
const MachineRegisterInfo *MRI =
|
|
|
|
&DefMI->getParent()->getParent()->getRegInfo();
|
|
|
|
IsRegCR = MRI->getRegClass(Reg)->hasSuperClassEq(&PPC::CRRCRegClass) ||
|
|
|
|
MRI->getRegClass(Reg)->hasSuperClassEq(&PPC::CRBITRCRegClass);
|
|
|
|
} else {
|
|
|
|
IsRegCR = PPC::CRRCRegClass.contains(Reg) ||
|
|
|
|
PPC::CRBITRCRegClass.contains(Reg);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (UseMI->isBranch() && IsRegCR) {
|
|
|
|
if (Latency < 0)
|
|
|
|
Latency = getInstrLatency(ItinData, DefMI);
|
|
|
|
|
|
|
|
// On some cores, there is an additional delay between writing to a condition
|
|
|
|
// register, and using it from a branch.
|
2014-06-12 21:48:52 +00:00
|
|
|
unsigned Directive = Subtarget.getDarwinDirective();
|
2013-12-12 00:19:11 +00:00
|
|
|
switch (Directive) {
|
|
|
|
default: break;
|
|
|
|
case PPC::DIR_7400:
|
|
|
|
case PPC::DIR_750:
|
|
|
|
case PPC::DIR_970:
|
|
|
|
case PPC::DIR_E5500:
|
|
|
|
case PPC::DIR_PWR4:
|
|
|
|
case PPC::DIR_PWR5:
|
|
|
|
case PPC::DIR_PWR5X:
|
|
|
|
case PPC::DIR_PWR6:
|
|
|
|
case PPC::DIR_PWR6X:
|
|
|
|
case PPC::DIR_PWR7:
|
2014-06-26 13:36:19 +00:00
|
|
|
case PPC::DIR_PWR8:
|
2013-12-12 00:19:11 +00:00
|
|
|
Latency += 2;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return Latency;
|
|
|
|
}
|
|
|
|
|
2012-06-19 21:14:34 +00:00
|
|
|
// Detect 32 -> 64-bit extensions where we may reuse the low sub-register.
|
|
|
|
bool PPCInstrInfo::isCoalescableExtInstr(const MachineInstr &MI,
|
|
|
|
unsigned &SrcReg, unsigned &DstReg,
|
|
|
|
unsigned &SubIdx) const {
|
|
|
|
switch (MI.getOpcode()) {
|
|
|
|
default: return false;
|
|
|
|
case PPC::EXTSW:
|
|
|
|
case PPC::EXTSW_32_64:
|
|
|
|
SrcReg = MI.getOperand(1).getReg();
|
|
|
|
DstReg = MI.getOperand(0).getReg();
|
|
|
|
SubIdx = PPC::sub_32;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-12-24 04:28:06 +00:00
|
|
|
unsigned PPCInstrInfo::isLoadFromStackSlot(const MachineInstr *MI,
|
2006-03-16 22:24:02 +00:00
|
|
|
int &FrameIndex) const {
|
2013-03-27 21:21:15 +00:00
|
|
|
// Note: This list must be kept consistent with LoadRegFromStackSlot.
|
2006-02-02 20:12:32 +00:00
|
|
|
switch (MI->getOpcode()) {
|
|
|
|
default: break;
|
|
|
|
case PPC::LD:
|
|
|
|
case PPC::LWZ:
|
|
|
|
case PPC::LFS:
|
|
|
|
case PPC::LFD:
|
2013-03-27 21:21:15 +00:00
|
|
|
case PPC::RESTORE_CR:
|
Add CR-bit tracking to the PowerPC backend for i1 values
This change enables tracking i1 values in the PowerPC backend using the
condition register bits. These bits can be treated on PowerPC as separate
registers; individual bit operations (and, or, xor, etc.) are supported.
Tracking booleans in CR bits has several advantages:
- Reduction in register pressure (because we no longer need GPRs to store
boolean values).
- Logical operations on booleans can be handled more efficiently; we used to
have to move all results from comparisons into GPRs, perform promoted
logical operations in GPRs, and then move the result back into condition
register bits to be used by conditional branches. This can be very
inefficient, because the throughput of these CR <-> GPR moves have high
latency and low throughput (especially when other associated instructions
are accounted for).
- On the POWER7 and similar cores, we can increase total throughput by using
the CR bits. CR bit operations have a dedicated functional unit.
Most of this is more-or-less mechanical: Adjustments were needed in the
calling-convention code, support was added for spilling/restoring individual
condition-register bits, and conditional branch instruction definitions taking
specific CR bits were added (plus patterns and code for generating bit-level
operations).
This is enabled by default when running at -O2 and higher. For -O0 and -O1,
where the ability to debug is more important, this feature is disabled by
default. Individual CR bits do not have assigned DWARF register numbers,
and storing values in CR bits makes them invisible to the debugger.
It is critical, however, that we don't move i1 values that have been promoted
to larger values (such as those passed as function arguments) into bit
registers only to quickly turn around and move the values back into GPRs (such
as happens when values are returned by functions). A pair of target-specific
DAG combines are added to remove the trunc/extends in:
trunc(binary-ops(binary-ops(zext(x), zext(y)), ...)
and:
zext(binary-ops(binary-ops(trunc(x), trunc(y)), ...)
In short, we only want to use CR bits where some of the i1 values come from
comparisons or are used by conditional branches or selects. To put it another
way, if we can do the entire i1 computation in GPRs, then we probably should
(on the POWER7, the GPR-operation throughput is higher, and for all cores, the
CR <-> GPR moves are expensive).
POWER7 test-suite performance results (from 10 runs in each configuration):
SingleSource/Benchmarks/Misc/mandel-2: 35% speedup
MultiSource/Benchmarks/Prolangs-C++/city/city: 21% speedup
MultiSource/Benchmarks/MiBench/automotive-susan: 23% speedup
SingleSource/Benchmarks/CoyoteBench/huffbench: 13% speedup
SingleSource/Benchmarks/Misc-C++/Large/sphereflake: 13% speedup
SingleSource/Benchmarks/Misc-C++/mandel-text: 10% speedup
SingleSource/Benchmarks/Misc-C++-EH/spirit: 10% slowdown
MultiSource/Applications/lemon/lemon: 8% slowdown
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202451 91177308-0d34-0410-b5e6-96231b3b80d8
2014-02-28 00:27:01 +00:00
|
|
|
case PPC::RESTORE_CRBIT:
|
2013-03-27 21:21:15 +00:00
|
|
|
case PPC::LVX:
|
[PowerPC] Initial support for the VSX instruction set
VSX is an ISA extension supported on the POWER7 and later cores that enhances
floating-point vector and scalar capabilities. Among other things, this adds
<2 x double> support and generally helps to reduce register pressure.
The interesting part of this ISA feature is the register configuration: there
are 64 new 128-bit vector registers, the 32 of which are super-registers of the
existing 32 scalar floating-point registers, and the second 32 of which overlap
with the 32 Altivec vector registers. This makes things like vector insertion
and extraction tricky: this can be free but only if we force a restriction to
the right register subclass when needed. A new "minipass" PPCVSXCopy takes care
of this (although it could do a more-optimal job of it; see the comment about
unnecessary copies below).
Please note that, currently, VSX is not enabled by default when targeting
anything because it is not yet ready for that. The assembler and disassembler
are fully implemented and tested. However:
- CodeGen support causes miscompiles; test-suite runtime failures:
MultiSource/Benchmarks/FreeBench/distray/distray
MultiSource/Benchmarks/McCat/08-main/main
MultiSource/Benchmarks/Olden/voronoi/voronoi
MultiSource/Benchmarks/mafft/pairlocalalign
MultiSource/Benchmarks/tramp3d-v4/tramp3d-v4
SingleSource/Benchmarks/CoyoteBench/almabench
SingleSource/Benchmarks/Misc/matmul_f64_4x4
- The lowering currently falls back to using Altivec instructions far more
than it should. Worse, there are some things that are scalarized through the
stack that shouldn't be.
- A lot of unnecessary copies make it past the optimizers, and this needs to
be fixed.
- Many more regression tests are needed.
Normally, I'd fix these things prior to committing, but there are some
students and other contributors who would like to work this, and so it makes
sense to move this development process upstream where it can be subject to the
regular code-review procedures.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203768 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-13 07:58:58 +00:00
|
|
|
case PPC::LXVD2X:
|
2013-03-27 21:21:15 +00:00
|
|
|
case PPC::RESTORE_VRSAVE:
|
|
|
|
// Check for the operands added by addFrameReference (the immediate is the
|
|
|
|
// offset which defaults to 0).
|
2008-10-03 15:45:36 +00:00
|
|
|
if (MI->getOperand(1).isImm() && !MI->getOperand(1).getImm() &&
|
|
|
|
MI->getOperand(2).isFI()) {
|
2007-12-30 23:10:15 +00:00
|
|
|
FrameIndex = MI->getOperand(2).getIndex();
|
2006-02-02 20:12:32 +00:00
|
|
|
return MI->getOperand(0).getReg();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return 0;
|
2006-02-02 20:16:12 +00:00
|
|
|
}
|
2006-02-02 20:12:32 +00:00
|
|
|
|
2010-12-24 04:28:06 +00:00
|
|
|
unsigned PPCInstrInfo::isStoreToStackSlot(const MachineInstr *MI,
|
2006-02-02 20:16:12 +00:00
|
|
|
int &FrameIndex) const {
|
2013-03-27 21:21:15 +00:00
|
|
|
// Note: This list must be kept consistent with StoreRegToStackSlot.
|
2006-02-02 20:16:12 +00:00
|
|
|
switch (MI->getOpcode()) {
|
|
|
|
default: break;
|
2006-02-02 21:07:50 +00:00
|
|
|
case PPC::STD:
|
2006-02-02 20:16:12 +00:00
|
|
|
case PPC::STW:
|
|
|
|
case PPC::STFS:
|
|
|
|
case PPC::STFD:
|
2013-03-27 21:21:15 +00:00
|
|
|
case PPC::SPILL_CR:
|
Add CR-bit tracking to the PowerPC backend for i1 values
This change enables tracking i1 values in the PowerPC backend using the
condition register bits. These bits can be treated on PowerPC as separate
registers; individual bit operations (and, or, xor, etc.) are supported.
Tracking booleans in CR bits has several advantages:
- Reduction in register pressure (because we no longer need GPRs to store
boolean values).
- Logical operations on booleans can be handled more efficiently; we used to
have to move all results from comparisons into GPRs, perform promoted
logical operations in GPRs, and then move the result back into condition
register bits to be used by conditional branches. This can be very
inefficient, because the throughput of these CR <-> GPR moves have high
latency and low throughput (especially when other associated instructions
are accounted for).
- On the POWER7 and similar cores, we can increase total throughput by using
the CR bits. CR bit operations have a dedicated functional unit.
Most of this is more-or-less mechanical: Adjustments were needed in the
calling-convention code, support was added for spilling/restoring individual
condition-register bits, and conditional branch instruction definitions taking
specific CR bits were added (plus patterns and code for generating bit-level
operations).
This is enabled by default when running at -O2 and higher. For -O0 and -O1,
where the ability to debug is more important, this feature is disabled by
default. Individual CR bits do not have assigned DWARF register numbers,
and storing values in CR bits makes them invisible to the debugger.
It is critical, however, that we don't move i1 values that have been promoted
to larger values (such as those passed as function arguments) into bit
registers only to quickly turn around and move the values back into GPRs (such
as happens when values are returned by functions). A pair of target-specific
DAG combines are added to remove the trunc/extends in:
trunc(binary-ops(binary-ops(zext(x), zext(y)), ...)
and:
zext(binary-ops(binary-ops(trunc(x), trunc(y)), ...)
In short, we only want to use CR bits where some of the i1 values come from
comparisons or are used by conditional branches or selects. To put it another
way, if we can do the entire i1 computation in GPRs, then we probably should
(on the POWER7, the GPR-operation throughput is higher, and for all cores, the
CR <-> GPR moves are expensive).
POWER7 test-suite performance results (from 10 runs in each configuration):
SingleSource/Benchmarks/Misc/mandel-2: 35% speedup
MultiSource/Benchmarks/Prolangs-C++/city/city: 21% speedup
MultiSource/Benchmarks/MiBench/automotive-susan: 23% speedup
SingleSource/Benchmarks/CoyoteBench/huffbench: 13% speedup
SingleSource/Benchmarks/Misc-C++/Large/sphereflake: 13% speedup
SingleSource/Benchmarks/Misc-C++/mandel-text: 10% speedup
SingleSource/Benchmarks/Misc-C++-EH/spirit: 10% slowdown
MultiSource/Applications/lemon/lemon: 8% slowdown
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202451 91177308-0d34-0410-b5e6-96231b3b80d8
2014-02-28 00:27:01 +00:00
|
|
|
case PPC::SPILL_CRBIT:
|
2013-03-27 21:21:15 +00:00
|
|
|
case PPC::STVX:
|
[PowerPC] Initial support for the VSX instruction set
VSX is an ISA extension supported on the POWER7 and later cores that enhances
floating-point vector and scalar capabilities. Among other things, this adds
<2 x double> support and generally helps to reduce register pressure.
The interesting part of this ISA feature is the register configuration: there
are 64 new 128-bit vector registers, the 32 of which are super-registers of the
existing 32 scalar floating-point registers, and the second 32 of which overlap
with the 32 Altivec vector registers. This makes things like vector insertion
and extraction tricky: this can be free but only if we force a restriction to
the right register subclass when needed. A new "minipass" PPCVSXCopy takes care
of this (although it could do a more-optimal job of it; see the comment about
unnecessary copies below).
Please note that, currently, VSX is not enabled by default when targeting
anything because it is not yet ready for that. The assembler and disassembler
are fully implemented and tested. However:
- CodeGen support causes miscompiles; test-suite runtime failures:
MultiSource/Benchmarks/FreeBench/distray/distray
MultiSource/Benchmarks/McCat/08-main/main
MultiSource/Benchmarks/Olden/voronoi/voronoi
MultiSource/Benchmarks/mafft/pairlocalalign
MultiSource/Benchmarks/tramp3d-v4/tramp3d-v4
SingleSource/Benchmarks/CoyoteBench/almabench
SingleSource/Benchmarks/Misc/matmul_f64_4x4
- The lowering currently falls back to using Altivec instructions far more
than it should. Worse, there are some things that are scalarized through the
stack that shouldn't be.
- A lot of unnecessary copies make it past the optimizers, and this needs to
be fixed.
- Many more regression tests are needed.
Normally, I'd fix these things prior to committing, but there are some
students and other contributors who would like to work this, and so it makes
sense to move this development process upstream where it can be subject to the
regular code-review procedures.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203768 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-13 07:58:58 +00:00
|
|
|
case PPC::STXVD2X:
|
2013-03-27 21:21:15 +00:00
|
|
|
case PPC::SPILL_VRSAVE:
|
|
|
|
// Check for the operands added by addFrameReference (the immediate is the
|
|
|
|
// offset which defaults to 0).
|
2008-10-03 15:45:36 +00:00
|
|
|
if (MI->getOperand(1).isImm() && !MI->getOperand(1).getImm() &&
|
|
|
|
MI->getOperand(2).isFI()) {
|
2007-12-30 23:10:15 +00:00
|
|
|
FrameIndex = MI->getOperand(2).getIndex();
|
2006-02-02 20:16:12 +00:00
|
|
|
return MI->getOperand(0).getReg();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2006-02-02 20:12:32 +00:00
|
|
|
|
2005-09-09 18:17:41 +00:00
|
|
|
// commuteInstruction - We can commute rlwimi instructions, but only if the
|
|
|
|
// rotate amt is zero. We also have to munge the immediates a bit.
|
2008-06-16 07:33:11 +00:00
|
|
|
MachineInstr *
|
|
|
|
PPCInstrInfo::commuteInstruction(MachineInstr *MI, bool NewMI) const {
|
2008-07-07 23:14:23 +00:00
|
|
|
MachineFunction &MF = *MI->getParent()->getParent();
|
|
|
|
|
2005-09-09 18:17:41 +00:00
|
|
|
// Normal instructions can be commuted the obvious way.
|
2013-04-12 02:18:09 +00:00
|
|
|
if (MI->getOpcode() != PPC::RLWIMI &&
|
Add CR-bit tracking to the PowerPC backend for i1 values
This change enables tracking i1 values in the PowerPC backend using the
condition register bits. These bits can be treated on PowerPC as separate
registers; individual bit operations (and, or, xor, etc.) are supported.
Tracking booleans in CR bits has several advantages:
- Reduction in register pressure (because we no longer need GPRs to store
boolean values).
- Logical operations on booleans can be handled more efficiently; we used to
have to move all results from comparisons into GPRs, perform promoted
logical operations in GPRs, and then move the result back into condition
register bits to be used by conditional branches. This can be very
inefficient, because the throughput of these CR <-> GPR moves have high
latency and low throughput (especially when other associated instructions
are accounted for).
- On the POWER7 and similar cores, we can increase total throughput by using
the CR bits. CR bit operations have a dedicated functional unit.
Most of this is more-or-less mechanical: Adjustments were needed in the
calling-convention code, support was added for spilling/restoring individual
condition-register bits, and conditional branch instruction definitions taking
specific CR bits were added (plus patterns and code for generating bit-level
operations).
This is enabled by default when running at -O2 and higher. For -O0 and -O1,
where the ability to debug is more important, this feature is disabled by
default. Individual CR bits do not have assigned DWARF register numbers,
and storing values in CR bits makes them invisible to the debugger.
It is critical, however, that we don't move i1 values that have been promoted
to larger values (such as those passed as function arguments) into bit
registers only to quickly turn around and move the values back into GPRs (such
as happens when values are returned by functions). A pair of target-specific
DAG combines are added to remove the trunc/extends in:
trunc(binary-ops(binary-ops(zext(x), zext(y)), ...)
and:
zext(binary-ops(binary-ops(trunc(x), trunc(y)), ...)
In short, we only want to use CR bits where some of the i1 values come from
comparisons or are used by conditional branches or selects. To put it another
way, if we can do the entire i1 computation in GPRs, then we probably should
(on the POWER7, the GPR-operation throughput is higher, and for all cores, the
CR <-> GPR moves are expensive).
POWER7 test-suite performance results (from 10 runs in each configuration):
SingleSource/Benchmarks/Misc/mandel-2: 35% speedup
MultiSource/Benchmarks/Prolangs-C++/city/city: 21% speedup
MultiSource/Benchmarks/MiBench/automotive-susan: 23% speedup
SingleSource/Benchmarks/CoyoteBench/huffbench: 13% speedup
SingleSource/Benchmarks/Misc-C++/Large/sphereflake: 13% speedup
SingleSource/Benchmarks/Misc-C++/mandel-text: 10% speedup
SingleSource/Benchmarks/Misc-C++-EH/spirit: 10% slowdown
MultiSource/Applications/lemon/lemon: 8% slowdown
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202451 91177308-0d34-0410-b5e6-96231b3b80d8
2014-02-28 00:27:01 +00:00
|
|
|
MI->getOpcode() != PPC::RLWIMIo &&
|
|
|
|
MI->getOpcode() != PPC::RLWIMI8 &&
|
|
|
|
MI->getOpcode() != PPC::RLWIMI8o)
|
2012-11-28 02:35:17 +00:00
|
|
|
return TargetInstrInfo::commuteInstruction(MI, NewMI);
|
2010-12-24 04:28:06 +00:00
|
|
|
|
2005-09-09 18:17:41 +00:00
|
|
|
// Cannot commute if it has a non-zero rotate count.
|
2007-12-30 20:49:49 +00:00
|
|
|
if (MI->getOperand(3).getImm() != 0)
|
2014-04-25 05:30:21 +00:00
|
|
|
return nullptr;
|
2010-12-24 04:28:06 +00:00
|
|
|
|
2005-09-09 18:17:41 +00:00
|
|
|
// If we have a zero rotate count, we have:
|
|
|
|
// M = mask(MB,ME)
|
|
|
|
// Op0 = (Op1 & ~M) | (Op2 & M)
|
|
|
|
// Change this to:
|
|
|
|
// M = mask((ME+1)&31, (MB-1)&31)
|
|
|
|
// Op0 = (Op2 & ~M) | (Op1 & M)
|
|
|
|
|
|
|
|
// Swap op1/op2
|
2008-02-13 02:46:49 +00:00
|
|
|
unsigned Reg0 = MI->getOperand(0).getReg();
|
2005-09-09 18:17:41 +00:00
|
|
|
unsigned Reg1 = MI->getOperand(1).getReg();
|
|
|
|
unsigned Reg2 = MI->getOperand(2).getReg();
|
2013-12-17 04:50:45 +00:00
|
|
|
unsigned SubReg1 = MI->getOperand(1).getSubReg();
|
|
|
|
unsigned SubReg2 = MI->getOperand(2).getSubReg();
|
2006-11-15 20:58:11 +00:00
|
|
|
bool Reg1IsKill = MI->getOperand(1).isKill();
|
|
|
|
bool Reg2IsKill = MI->getOperand(2).isKill();
|
2008-06-16 07:33:11 +00:00
|
|
|
bool ChangeReg0 = false;
|
2008-02-13 02:46:49 +00:00
|
|
|
// If machine instrs are no longer in two-address forms, update
|
|
|
|
// destination register as well.
|
|
|
|
if (Reg0 == Reg1) {
|
|
|
|
// Must be two address instruction!
|
2011-06-28 19:10:37 +00:00
|
|
|
assert(MI->getDesc().getOperandConstraint(0, MCOI::TIED_TO) &&
|
2008-02-13 02:46:49 +00:00
|
|
|
"Expecting a two-address instruction!");
|
2013-12-17 04:50:45 +00:00
|
|
|
assert(MI->getOperand(0).getSubReg() == SubReg1 && "Tied subreg mismatch");
|
2008-02-13 02:46:49 +00:00
|
|
|
Reg2IsKill = false;
|
2008-06-16 07:33:11 +00:00
|
|
|
ChangeReg0 = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Masks.
|
|
|
|
unsigned MB = MI->getOperand(4).getImm();
|
|
|
|
unsigned ME = MI->getOperand(5).getImm();
|
|
|
|
|
|
|
|
if (NewMI) {
|
|
|
|
// Create a new instruction.
|
|
|
|
unsigned Reg0 = ChangeReg0 ? Reg2 : MI->getOperand(0).getReg();
|
|
|
|
bool Reg0IsDead = MI->getOperand(0).isDead();
|
2009-02-12 00:02:55 +00:00
|
|
|
return BuildMI(MF, MI->getDebugLoc(), MI->getDesc())
|
2009-05-13 21:33:08 +00:00
|
|
|
.addReg(Reg0, RegState::Define | getDeadRegState(Reg0IsDead))
|
|
|
|
.addReg(Reg2, getKillRegState(Reg2IsKill))
|
|
|
|
.addReg(Reg1, getKillRegState(Reg1IsKill))
|
2008-06-16 07:33:11 +00:00
|
|
|
.addImm((ME+1) & 31)
|
|
|
|
.addImm((MB-1) & 31);
|
2008-02-13 02:46:49 +00:00
|
|
|
}
|
2008-06-16 07:33:11 +00:00
|
|
|
|
2013-12-17 04:50:45 +00:00
|
|
|
if (ChangeReg0) {
|
2008-06-16 07:33:11 +00:00
|
|
|
MI->getOperand(0).setReg(Reg2);
|
2013-12-17 04:50:45 +00:00
|
|
|
MI->getOperand(0).setSubReg(SubReg2);
|
|
|
|
}
|
2006-05-04 17:52:23 +00:00
|
|
|
MI->getOperand(2).setReg(Reg1);
|
|
|
|
MI->getOperand(1).setReg(Reg2);
|
2013-12-17 04:50:45 +00:00
|
|
|
MI->getOperand(2).setSubReg(SubReg1);
|
|
|
|
MI->getOperand(1).setSubReg(SubReg2);
|
2007-12-30 21:56:09 +00:00
|
|
|
MI->getOperand(2).setIsKill(Reg1IsKill);
|
|
|
|
MI->getOperand(1).setIsKill(Reg2IsKill);
|
2010-12-24 04:28:06 +00:00
|
|
|
|
2005-09-09 18:17:41 +00:00
|
|
|
// Swap the mask around.
|
2007-12-30 20:49:49 +00:00
|
|
|
MI->getOperand(4).setImm((ME+1) & 31);
|
|
|
|
MI->getOperand(5).setImm((MB-1) & 31);
|
2005-09-09 18:17:41 +00:00
|
|
|
return MI;
|
|
|
|
}
|
2006-03-05 23:49:55 +00:00
|
|
|
|
2014-03-25 19:26:43 +00:00
|
|
|
bool PPCInstrInfo::findCommutedOpIndices(MachineInstr *MI, unsigned &SrcOpIdx1,
|
|
|
|
unsigned &SrcOpIdx2) const {
|
|
|
|
// For VSX A-Type FMA instructions, it is the first two operands that can be
|
|
|
|
// commuted, however, because the non-encoded tied input operand is listed
|
|
|
|
// first, the operands to swap are actually the second and third.
|
|
|
|
|
|
|
|
int AltOpc = PPC::getAltVSXFMAOpcode(MI->getOpcode());
|
|
|
|
if (AltOpc == -1)
|
|
|
|
return TargetInstrInfo::findCommutedOpIndices(MI, SrcOpIdx1, SrcOpIdx2);
|
|
|
|
|
|
|
|
SrcOpIdx1 = 2;
|
|
|
|
SrcOpIdx2 = 3;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-12-24 04:28:06 +00:00
|
|
|
void PPCInstrInfo::insertNoop(MachineBasicBlock &MBB,
|
2006-03-05 23:49:55 +00:00
|
|
|
MachineBasicBlock::iterator MI) const {
|
2013-12-12 00:19:11 +00:00
|
|
|
// This function is used for scheduling, and the nop wanted here is the type
|
|
|
|
// that terminates dispatch groups on the POWER cores.
|
2014-06-12 21:48:52 +00:00
|
|
|
unsigned Directive = Subtarget.getDarwinDirective();
|
2013-12-12 00:19:11 +00:00
|
|
|
unsigned Opcode;
|
|
|
|
switch (Directive) {
|
|
|
|
default: Opcode = PPC::NOP; break;
|
|
|
|
case PPC::DIR_PWR6: Opcode = PPC::NOP_GT_PWR6; break;
|
|
|
|
case PPC::DIR_PWR7: Opcode = PPC::NOP_GT_PWR7; break;
|
2014-06-26 13:36:19 +00:00
|
|
|
case PPC::DIR_PWR8: Opcode = PPC::NOP_GT_PWR7; break; /* FIXME: Update when P8 InstrScheduling model is ready */
|
2013-12-12 00:19:11 +00:00
|
|
|
}
|
|
|
|
|
2010-04-02 20:16:16 +00:00
|
|
|
DebugLoc DL;
|
2013-12-12 00:19:11 +00:00
|
|
|
BuildMI(MBB, MI, DL, get(Opcode));
|
2006-03-05 23:49:55 +00:00
|
|
|
}
|
2006-10-13 21:21:17 +00:00
|
|
|
|
|
|
|
// Branch analysis.
|
2012-06-08 15:38:21 +00:00
|
|
|
// Note: If the condition register is set to CTR or CTR8 then this is a
|
|
|
|
// BDNZ (imm == 1) or BDZ (imm == 0) branch.
|
2006-10-13 21:21:17 +00:00
|
|
|
bool PPCInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,MachineBasicBlock *&TBB,
|
|
|
|
MachineBasicBlock *&FBB,
|
2009-02-09 07:14:22 +00:00
|
|
|
SmallVectorImpl<MachineOperand> &Cond,
|
|
|
|
bool AllowModify) const {
|
2014-06-12 21:48:52 +00:00
|
|
|
bool isPPC64 = Subtarget.isPPC64();
|
2012-06-08 15:38:21 +00:00
|
|
|
|
2006-10-13 21:21:17 +00:00
|
|
|
// If the block has no terminators, it just falls into the block after it.
|
|
|
|
MachineBasicBlock::iterator I = MBB.end();
|
2010-04-02 01:38:09 +00:00
|
|
|
if (I == MBB.begin())
|
|
|
|
return false;
|
|
|
|
--I;
|
|
|
|
while (I->isDebugValue()) {
|
|
|
|
if (I == MBB.begin())
|
|
|
|
return false;
|
|
|
|
--I;
|
|
|
|
}
|
|
|
|
if (!isUnpredicatedTerminator(I))
|
2006-10-13 21:21:17 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
// Get the last instruction in the block.
|
|
|
|
MachineInstr *LastInst = I;
|
2010-12-24 04:28:06 +00:00
|
|
|
|
2006-10-13 21:21:17 +00:00
|
|
|
// If there is only one terminator instruction, process it.
|
2007-06-08 21:59:56 +00:00
|
|
|
if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) {
|
2006-10-13 21:21:17 +00:00
|
|
|
if (LastInst->getOpcode() == PPC::B) {
|
2009-05-08 23:09:25 +00:00
|
|
|
if (!LastInst->getOperand(0).isMBB())
|
|
|
|
return true;
|
2007-12-30 23:10:15 +00:00
|
|
|
TBB = LastInst->getOperand(0).getMBB();
|
2006-10-13 21:21:17 +00:00
|
|
|
return false;
|
2006-11-17 22:14:47 +00:00
|
|
|
} else if (LastInst->getOpcode() == PPC::BCC) {
|
2009-05-08 23:09:25 +00:00
|
|
|
if (!LastInst->getOperand(2).isMBB())
|
|
|
|
return true;
|
2006-10-13 21:21:17 +00:00
|
|
|
// Block ends with fall-through condbranch.
|
2007-12-30 23:10:15 +00:00
|
|
|
TBB = LastInst->getOperand(2).getMBB();
|
2006-10-13 21:21:17 +00:00
|
|
|
Cond.push_back(LastInst->getOperand(0));
|
|
|
|
Cond.push_back(LastInst->getOperand(1));
|
2006-10-21 06:03:11 +00:00
|
|
|
return false;
|
Add CR-bit tracking to the PowerPC backend for i1 values
This change enables tracking i1 values in the PowerPC backend using the
condition register bits. These bits can be treated on PowerPC as separate
registers; individual bit operations (and, or, xor, etc.) are supported.
Tracking booleans in CR bits has several advantages:
- Reduction in register pressure (because we no longer need GPRs to store
boolean values).
- Logical operations on booleans can be handled more efficiently; we used to
have to move all results from comparisons into GPRs, perform promoted
logical operations in GPRs, and then move the result back into condition
register bits to be used by conditional branches. This can be very
inefficient, because the throughput of these CR <-> GPR moves have high
latency and low throughput (especially when other associated instructions
are accounted for).
- On the POWER7 and similar cores, we can increase total throughput by using
the CR bits. CR bit operations have a dedicated functional unit.
Most of this is more-or-less mechanical: Adjustments were needed in the
calling-convention code, support was added for spilling/restoring individual
condition-register bits, and conditional branch instruction definitions taking
specific CR bits were added (plus patterns and code for generating bit-level
operations).
This is enabled by default when running at -O2 and higher. For -O0 and -O1,
where the ability to debug is more important, this feature is disabled by
default. Individual CR bits do not have assigned DWARF register numbers,
and storing values in CR bits makes them invisible to the debugger.
It is critical, however, that we don't move i1 values that have been promoted
to larger values (such as those passed as function arguments) into bit
registers only to quickly turn around and move the values back into GPRs (such
as happens when values are returned by functions). A pair of target-specific
DAG combines are added to remove the trunc/extends in:
trunc(binary-ops(binary-ops(zext(x), zext(y)), ...)
and:
zext(binary-ops(binary-ops(trunc(x), trunc(y)), ...)
In short, we only want to use CR bits where some of the i1 values come from
comparisons or are used by conditional branches or selects. To put it another
way, if we can do the entire i1 computation in GPRs, then we probably should
(on the POWER7, the GPR-operation throughput is higher, and for all cores, the
CR <-> GPR moves are expensive).
POWER7 test-suite performance results (from 10 runs in each configuration):
SingleSource/Benchmarks/Misc/mandel-2: 35% speedup
MultiSource/Benchmarks/Prolangs-C++/city/city: 21% speedup
MultiSource/Benchmarks/MiBench/automotive-susan: 23% speedup
SingleSource/Benchmarks/CoyoteBench/huffbench: 13% speedup
SingleSource/Benchmarks/Misc-C++/Large/sphereflake: 13% speedup
SingleSource/Benchmarks/Misc-C++/mandel-text: 10% speedup
SingleSource/Benchmarks/Misc-C++-EH/spirit: 10% slowdown
MultiSource/Applications/lemon/lemon: 8% slowdown
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202451 91177308-0d34-0410-b5e6-96231b3b80d8
2014-02-28 00:27:01 +00:00
|
|
|
} else if (LastInst->getOpcode() == PPC::BC) {
|
|
|
|
if (!LastInst->getOperand(1).isMBB())
|
|
|
|
return true;
|
|
|
|
// Block ends with fall-through condbranch.
|
|
|
|
TBB = LastInst->getOperand(1).getMBB();
|
|
|
|
Cond.push_back(MachineOperand::CreateImm(PPC::PRED_BIT_SET));
|
|
|
|
Cond.push_back(LastInst->getOperand(0));
|
|
|
|
return false;
|
|
|
|
} else if (LastInst->getOpcode() == PPC::BCn) {
|
|
|
|
if (!LastInst->getOperand(1).isMBB())
|
|
|
|
return true;
|
|
|
|
// Block ends with fall-through condbranch.
|
|
|
|
TBB = LastInst->getOperand(1).getMBB();
|
|
|
|
Cond.push_back(MachineOperand::CreateImm(PPC::PRED_BIT_UNSET));
|
|
|
|
Cond.push_back(LastInst->getOperand(0));
|
|
|
|
return false;
|
2012-06-08 15:38:21 +00:00
|
|
|
} else if (LastInst->getOpcode() == PPC::BDNZ8 ||
|
|
|
|
LastInst->getOpcode() == PPC::BDNZ) {
|
|
|
|
if (!LastInst->getOperand(0).isMBB())
|
|
|
|
return true;
|
2012-06-08 19:19:53 +00:00
|
|
|
if (DisableCTRLoopAnal)
|
2012-06-08 15:38:25 +00:00
|
|
|
return true;
|
2012-06-08 15:38:21 +00:00
|
|
|
TBB = LastInst->getOperand(0).getMBB();
|
|
|
|
Cond.push_back(MachineOperand::CreateImm(1));
|
|
|
|
Cond.push_back(MachineOperand::CreateReg(isPPC64 ? PPC::CTR8 : PPC::CTR,
|
|
|
|
true));
|
|
|
|
return false;
|
|
|
|
} else if (LastInst->getOpcode() == PPC::BDZ8 ||
|
|
|
|
LastInst->getOpcode() == PPC::BDZ) {
|
|
|
|
if (!LastInst->getOperand(0).isMBB())
|
|
|
|
return true;
|
2012-06-08 19:19:53 +00:00
|
|
|
if (DisableCTRLoopAnal)
|
2012-06-08 15:38:25 +00:00
|
|
|
return true;
|
2012-06-08 15:38:21 +00:00
|
|
|
TBB = LastInst->getOperand(0).getMBB();
|
|
|
|
Cond.push_back(MachineOperand::CreateImm(0));
|
|
|
|
Cond.push_back(MachineOperand::CreateReg(isPPC64 ? PPC::CTR8 : PPC::CTR,
|
|
|
|
true));
|
|
|
|
return false;
|
2006-10-13 21:21:17 +00:00
|
|
|
}
|
2012-06-08 15:38:21 +00:00
|
|
|
|
2006-10-13 21:21:17 +00:00
|
|
|
// Otherwise, don't know what this is.
|
|
|
|
return true;
|
|
|
|
}
|
2010-12-24 04:28:06 +00:00
|
|
|
|
2006-10-13 21:21:17 +00:00
|
|
|
// Get the instruction before it if it's a terminator.
|
|
|
|
MachineInstr *SecondLastInst = I;
|
|
|
|
|
|
|
|
// If there are three terminators, we don't know what sort of block this is.
|
|
|
|
if (SecondLastInst && I != MBB.begin() &&
|
2007-06-08 21:59:56 +00:00
|
|
|
isUnpredicatedTerminator(--I))
|
2006-10-13 21:21:17 +00:00
|
|
|
return true;
|
2010-12-24 04:28:06 +00:00
|
|
|
|
2006-11-17 22:14:47 +00:00
|
|
|
// If the block ends with PPC::B and PPC:BCC, handle it.
|
2010-12-24 04:28:06 +00:00
|
|
|
if (SecondLastInst->getOpcode() == PPC::BCC &&
|
2006-10-13 21:21:17 +00:00
|
|
|
LastInst->getOpcode() == PPC::B) {
|
2009-05-08 23:09:25 +00:00
|
|
|
if (!SecondLastInst->getOperand(2).isMBB() ||
|
|
|
|
!LastInst->getOperand(0).isMBB())
|
|
|
|
return true;
|
2007-12-30 23:10:15 +00:00
|
|
|
TBB = SecondLastInst->getOperand(2).getMBB();
|
2006-10-13 21:21:17 +00:00
|
|
|
Cond.push_back(SecondLastInst->getOperand(0));
|
|
|
|
Cond.push_back(SecondLastInst->getOperand(1));
|
2007-12-30 23:10:15 +00:00
|
|
|
FBB = LastInst->getOperand(0).getMBB();
|
2006-10-13 21:21:17 +00:00
|
|
|
return false;
|
Add CR-bit tracking to the PowerPC backend for i1 values
This change enables tracking i1 values in the PowerPC backend using the
condition register bits. These bits can be treated on PowerPC as separate
registers; individual bit operations (and, or, xor, etc.) are supported.
Tracking booleans in CR bits has several advantages:
- Reduction in register pressure (because we no longer need GPRs to store
boolean values).
- Logical operations on booleans can be handled more efficiently; we used to
have to move all results from comparisons into GPRs, perform promoted
logical operations in GPRs, and then move the result back into condition
register bits to be used by conditional branches. This can be very
inefficient, because the throughput of these CR <-> GPR moves have high
latency and low throughput (especially when other associated instructions
are accounted for).
- On the POWER7 and similar cores, we can increase total throughput by using
the CR bits. CR bit operations have a dedicated functional unit.
Most of this is more-or-less mechanical: Adjustments were needed in the
calling-convention code, support was added for spilling/restoring individual
condition-register bits, and conditional branch instruction definitions taking
specific CR bits were added (plus patterns and code for generating bit-level
operations).
This is enabled by default when running at -O2 and higher. For -O0 and -O1,
where the ability to debug is more important, this feature is disabled by
default. Individual CR bits do not have assigned DWARF register numbers,
and storing values in CR bits makes them invisible to the debugger.
It is critical, however, that we don't move i1 values that have been promoted
to larger values (such as those passed as function arguments) into bit
registers only to quickly turn around and move the values back into GPRs (such
as happens when values are returned by functions). A pair of target-specific
DAG combines are added to remove the trunc/extends in:
trunc(binary-ops(binary-ops(zext(x), zext(y)), ...)
and:
zext(binary-ops(binary-ops(trunc(x), trunc(y)), ...)
In short, we only want to use CR bits where some of the i1 values come from
comparisons or are used by conditional branches or selects. To put it another
way, if we can do the entire i1 computation in GPRs, then we probably should
(on the POWER7, the GPR-operation throughput is higher, and for all cores, the
CR <-> GPR moves are expensive).
POWER7 test-suite performance results (from 10 runs in each configuration):
SingleSource/Benchmarks/Misc/mandel-2: 35% speedup
MultiSource/Benchmarks/Prolangs-C++/city/city: 21% speedup
MultiSource/Benchmarks/MiBench/automotive-susan: 23% speedup
SingleSource/Benchmarks/CoyoteBench/huffbench: 13% speedup
SingleSource/Benchmarks/Misc-C++/Large/sphereflake: 13% speedup
SingleSource/Benchmarks/Misc-C++/mandel-text: 10% speedup
SingleSource/Benchmarks/Misc-C++-EH/spirit: 10% slowdown
MultiSource/Applications/lemon/lemon: 8% slowdown
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202451 91177308-0d34-0410-b5e6-96231b3b80d8
2014-02-28 00:27:01 +00:00
|
|
|
} else if (SecondLastInst->getOpcode() == PPC::BC &&
|
|
|
|
LastInst->getOpcode() == PPC::B) {
|
|
|
|
if (!SecondLastInst->getOperand(1).isMBB() ||
|
|
|
|
!LastInst->getOperand(0).isMBB())
|
|
|
|
return true;
|
|
|
|
TBB = SecondLastInst->getOperand(1).getMBB();
|
|
|
|
Cond.push_back(MachineOperand::CreateImm(PPC::PRED_BIT_SET));
|
|
|
|
Cond.push_back(SecondLastInst->getOperand(0));
|
|
|
|
FBB = LastInst->getOperand(0).getMBB();
|
|
|
|
return false;
|
|
|
|
} else if (SecondLastInst->getOpcode() == PPC::BCn &&
|
|
|
|
LastInst->getOpcode() == PPC::B) {
|
|
|
|
if (!SecondLastInst->getOperand(1).isMBB() ||
|
|
|
|
!LastInst->getOperand(0).isMBB())
|
|
|
|
return true;
|
|
|
|
TBB = SecondLastInst->getOperand(1).getMBB();
|
|
|
|
Cond.push_back(MachineOperand::CreateImm(PPC::PRED_BIT_UNSET));
|
|
|
|
Cond.push_back(SecondLastInst->getOperand(0));
|
|
|
|
FBB = LastInst->getOperand(0).getMBB();
|
|
|
|
return false;
|
2012-06-08 15:38:21 +00:00
|
|
|
} else if ((SecondLastInst->getOpcode() == PPC::BDNZ8 ||
|
|
|
|
SecondLastInst->getOpcode() == PPC::BDNZ) &&
|
|
|
|
LastInst->getOpcode() == PPC::B) {
|
|
|
|
if (!SecondLastInst->getOperand(0).isMBB() ||
|
|
|
|
!LastInst->getOperand(0).isMBB())
|
|
|
|
return true;
|
2012-06-08 19:19:53 +00:00
|
|
|
if (DisableCTRLoopAnal)
|
2012-06-08 15:38:25 +00:00
|
|
|
return true;
|
2012-06-08 15:38:21 +00:00
|
|
|
TBB = SecondLastInst->getOperand(0).getMBB();
|
|
|
|
Cond.push_back(MachineOperand::CreateImm(1));
|
|
|
|
Cond.push_back(MachineOperand::CreateReg(isPPC64 ? PPC::CTR8 : PPC::CTR,
|
|
|
|
true));
|
|
|
|
FBB = LastInst->getOperand(0).getMBB();
|
|
|
|
return false;
|
|
|
|
} else if ((SecondLastInst->getOpcode() == PPC::BDZ8 ||
|
|
|
|
SecondLastInst->getOpcode() == PPC::BDZ) &&
|
|
|
|
LastInst->getOpcode() == PPC::B) {
|
|
|
|
if (!SecondLastInst->getOperand(0).isMBB() ||
|
|
|
|
!LastInst->getOperand(0).isMBB())
|
|
|
|
return true;
|
2012-06-08 19:19:53 +00:00
|
|
|
if (DisableCTRLoopAnal)
|
2012-06-08 15:38:25 +00:00
|
|
|
return true;
|
2012-06-08 15:38:21 +00:00
|
|
|
TBB = SecondLastInst->getOperand(0).getMBB();
|
|
|
|
Cond.push_back(MachineOperand::CreateImm(0));
|
|
|
|
Cond.push_back(MachineOperand::CreateReg(isPPC64 ? PPC::CTR8 : PPC::CTR,
|
|
|
|
true));
|
|
|
|
FBB = LastInst->getOperand(0).getMBB();
|
|
|
|
return false;
|
2006-10-13 21:21:17 +00:00
|
|
|
}
|
2010-12-24 04:28:06 +00:00
|
|
|
|
2007-06-13 17:59:52 +00:00
|
|
|
// If the block ends with two PPC:Bs, handle it. The second one is not
|
|
|
|
// executed, so remove it.
|
2010-12-24 04:28:06 +00:00
|
|
|
if (SecondLastInst->getOpcode() == PPC::B &&
|
2007-06-13 17:59:52 +00:00
|
|
|
LastInst->getOpcode() == PPC::B) {
|
2009-05-08 23:09:25 +00:00
|
|
|
if (!SecondLastInst->getOperand(0).isMBB())
|
|
|
|
return true;
|
2007-12-30 23:10:15 +00:00
|
|
|
TBB = SecondLastInst->getOperand(0).getMBB();
|
2007-06-13 17:59:52 +00:00
|
|
|
I = LastInst;
|
2009-02-09 07:14:22 +00:00
|
|
|
if (AllowModify)
|
|
|
|
I->eraseFromParent();
|
2007-06-13 17:59:52 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2006-10-13 21:21:17 +00:00
|
|
|
// Otherwise, can't handle this.
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2007-05-18 00:05:48 +00:00
|
|
|
unsigned PPCInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
|
2006-10-13 21:21:17 +00:00
|
|
|
MachineBasicBlock::iterator I = MBB.end();
|
2007-05-18 00:05:48 +00:00
|
|
|
if (I == MBB.begin()) return 0;
|
2006-10-13 21:21:17 +00:00
|
|
|
--I;
|
2010-04-02 01:38:09 +00:00
|
|
|
while (I->isDebugValue()) {
|
|
|
|
if (I == MBB.begin())
|
|
|
|
return 0;
|
|
|
|
--I;
|
|
|
|
}
|
2012-06-08 15:38:21 +00:00
|
|
|
if (I->getOpcode() != PPC::B && I->getOpcode() != PPC::BCC &&
|
Add CR-bit tracking to the PowerPC backend for i1 values
This change enables tracking i1 values in the PowerPC backend using the
condition register bits. These bits can be treated on PowerPC as separate
registers; individual bit operations (and, or, xor, etc.) are supported.
Tracking booleans in CR bits has several advantages:
- Reduction in register pressure (because we no longer need GPRs to store
boolean values).
- Logical operations on booleans can be handled more efficiently; we used to
have to move all results from comparisons into GPRs, perform promoted
logical operations in GPRs, and then move the result back into condition
register bits to be used by conditional branches. This can be very
inefficient, because the throughput of these CR <-> GPR moves have high
latency and low throughput (especially when other associated instructions
are accounted for).
- On the POWER7 and similar cores, we can increase total throughput by using
the CR bits. CR bit operations have a dedicated functional unit.
Most of this is more-or-less mechanical: Adjustments were needed in the
calling-convention code, support was added for spilling/restoring individual
condition-register bits, and conditional branch instruction definitions taking
specific CR bits were added (plus patterns and code for generating bit-level
operations).
This is enabled by default when running at -O2 and higher. For -O0 and -O1,
where the ability to debug is more important, this feature is disabled by
default. Individual CR bits do not have assigned DWARF register numbers,
and storing values in CR bits makes them invisible to the debugger.
It is critical, however, that we don't move i1 values that have been promoted
to larger values (such as those passed as function arguments) into bit
registers only to quickly turn around and move the values back into GPRs (such
as happens when values are returned by functions). A pair of target-specific
DAG combines are added to remove the trunc/extends in:
trunc(binary-ops(binary-ops(zext(x), zext(y)), ...)
and:
zext(binary-ops(binary-ops(trunc(x), trunc(y)), ...)
In short, we only want to use CR bits where some of the i1 values come from
comparisons or are used by conditional branches or selects. To put it another
way, if we can do the entire i1 computation in GPRs, then we probably should
(on the POWER7, the GPR-operation throughput is higher, and for all cores, the
CR <-> GPR moves are expensive).
POWER7 test-suite performance results (from 10 runs in each configuration):
SingleSource/Benchmarks/Misc/mandel-2: 35% speedup
MultiSource/Benchmarks/Prolangs-C++/city/city: 21% speedup
MultiSource/Benchmarks/MiBench/automotive-susan: 23% speedup
SingleSource/Benchmarks/CoyoteBench/huffbench: 13% speedup
SingleSource/Benchmarks/Misc-C++/Large/sphereflake: 13% speedup
SingleSource/Benchmarks/Misc-C++/mandel-text: 10% speedup
SingleSource/Benchmarks/Misc-C++-EH/spirit: 10% slowdown
MultiSource/Applications/lemon/lemon: 8% slowdown
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202451 91177308-0d34-0410-b5e6-96231b3b80d8
2014-02-28 00:27:01 +00:00
|
|
|
I->getOpcode() != PPC::BC && I->getOpcode() != PPC::BCn &&
|
2012-06-08 15:38:21 +00:00
|
|
|
I->getOpcode() != PPC::BDNZ8 && I->getOpcode() != PPC::BDNZ &&
|
|
|
|
I->getOpcode() != PPC::BDZ8 && I->getOpcode() != PPC::BDZ)
|
2007-05-18 00:05:48 +00:00
|
|
|
return 0;
|
2010-12-24 04:28:06 +00:00
|
|
|
|
2006-10-13 21:21:17 +00:00
|
|
|
// Remove the branch.
|
|
|
|
I->eraseFromParent();
|
2010-12-24 04:28:06 +00:00
|
|
|
|
2006-10-13 21:21:17 +00:00
|
|
|
I = MBB.end();
|
|
|
|
|
2007-05-18 00:05:48 +00:00
|
|
|
if (I == MBB.begin()) return 1;
|
2006-10-13 21:21:17 +00:00
|
|
|
--I;
|
2012-06-08 15:38:21 +00:00
|
|
|
if (I->getOpcode() != PPC::BCC &&
|
Add CR-bit tracking to the PowerPC backend for i1 values
This change enables tracking i1 values in the PowerPC backend using the
condition register bits. These bits can be treated on PowerPC as separate
registers; individual bit operations (and, or, xor, etc.) are supported.
Tracking booleans in CR bits has several advantages:
- Reduction in register pressure (because we no longer need GPRs to store
boolean values).
- Logical operations on booleans can be handled more efficiently; we used to
have to move all results from comparisons into GPRs, perform promoted
logical operations in GPRs, and then move the result back into condition
register bits to be used by conditional branches. This can be very
inefficient, because the throughput of these CR <-> GPR moves have high
latency and low throughput (especially when other associated instructions
are accounted for).
- On the POWER7 and similar cores, we can increase total throughput by using
the CR bits. CR bit operations have a dedicated functional unit.
Most of this is more-or-less mechanical: Adjustments were needed in the
calling-convention code, support was added for spilling/restoring individual
condition-register bits, and conditional branch instruction definitions taking
specific CR bits were added (plus patterns and code for generating bit-level
operations).
This is enabled by default when running at -O2 and higher. For -O0 and -O1,
where the ability to debug is more important, this feature is disabled by
default. Individual CR bits do not have assigned DWARF register numbers,
and storing values in CR bits makes them invisible to the debugger.
It is critical, however, that we don't move i1 values that have been promoted
to larger values (such as those passed as function arguments) into bit
registers only to quickly turn around and move the values back into GPRs (such
as happens when values are returned by functions). A pair of target-specific
DAG combines are added to remove the trunc/extends in:
trunc(binary-ops(binary-ops(zext(x), zext(y)), ...)
and:
zext(binary-ops(binary-ops(trunc(x), trunc(y)), ...)
In short, we only want to use CR bits where some of the i1 values come from
comparisons or are used by conditional branches or selects. To put it another
way, if we can do the entire i1 computation in GPRs, then we probably should
(on the POWER7, the GPR-operation throughput is higher, and for all cores, the
CR <-> GPR moves are expensive).
POWER7 test-suite performance results (from 10 runs in each configuration):
SingleSource/Benchmarks/Misc/mandel-2: 35% speedup
MultiSource/Benchmarks/Prolangs-C++/city/city: 21% speedup
MultiSource/Benchmarks/MiBench/automotive-susan: 23% speedup
SingleSource/Benchmarks/CoyoteBench/huffbench: 13% speedup
SingleSource/Benchmarks/Misc-C++/Large/sphereflake: 13% speedup
SingleSource/Benchmarks/Misc-C++/mandel-text: 10% speedup
SingleSource/Benchmarks/Misc-C++-EH/spirit: 10% slowdown
MultiSource/Applications/lemon/lemon: 8% slowdown
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202451 91177308-0d34-0410-b5e6-96231b3b80d8
2014-02-28 00:27:01 +00:00
|
|
|
I->getOpcode() != PPC::BC && I->getOpcode() != PPC::BCn &&
|
2012-06-08 15:38:21 +00:00
|
|
|
I->getOpcode() != PPC::BDNZ8 && I->getOpcode() != PPC::BDNZ &&
|
|
|
|
I->getOpcode() != PPC::BDZ8 && I->getOpcode() != PPC::BDZ)
|
2007-05-18 00:05:48 +00:00
|
|
|
return 1;
|
2010-12-24 04:28:06 +00:00
|
|
|
|
2006-10-13 21:21:17 +00:00
|
|
|
// Remove the branch.
|
|
|
|
I->eraseFromParent();
|
2007-05-18 00:05:48 +00:00
|
|
|
return 2;
|
2006-10-13 21:21:17 +00:00
|
|
|
}
|
|
|
|
|
2007-05-18 00:05:48 +00:00
|
|
|
unsigned
|
|
|
|
PPCInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
|
|
|
|
MachineBasicBlock *FBB,
|
2010-06-17 22:43:56 +00:00
|
|
|
const SmallVectorImpl<MachineOperand> &Cond,
|
|
|
|
DebugLoc DL) const {
|
2006-10-17 18:06:55 +00:00
|
|
|
// Shouldn't be a fall through.
|
|
|
|
assert(TBB && "InsertBranch must not be told to insert a fallthrough");
|
2010-12-24 04:28:06 +00:00
|
|
|
assert((Cond.size() == 2 || Cond.size() == 0) &&
|
2006-10-21 05:36:13 +00:00
|
|
|
"PPC branch conditions have two components!");
|
2010-12-24 04:28:06 +00:00
|
|
|
|
2014-06-12 21:48:52 +00:00
|
|
|
bool isPPC64 = Subtarget.isPPC64();
|
2012-06-08 15:38:21 +00:00
|
|
|
|
2006-10-21 05:36:13 +00:00
|
|
|
// One-way branch.
|
2014-04-25 05:30:21 +00:00
|
|
|
if (!FBB) {
|
2006-10-21 05:36:13 +00:00
|
|
|
if (Cond.empty()) // Unconditional branch
|
2010-06-17 22:43:56 +00:00
|
|
|
BuildMI(&MBB, DL, get(PPC::B)).addMBB(TBB);
|
2012-06-08 15:38:21 +00:00
|
|
|
else if (Cond[1].getReg() == PPC::CTR || Cond[1].getReg() == PPC::CTR8)
|
|
|
|
BuildMI(&MBB, DL, get(Cond[0].getImm() ?
|
|
|
|
(isPPC64 ? PPC::BDNZ8 : PPC::BDNZ) :
|
|
|
|
(isPPC64 ? PPC::BDZ8 : PPC::BDZ))).addMBB(TBB);
|
Add CR-bit tracking to the PowerPC backend for i1 values
This change enables tracking i1 values in the PowerPC backend using the
condition register bits. These bits can be treated on PowerPC as separate
registers; individual bit operations (and, or, xor, etc.) are supported.
Tracking booleans in CR bits has several advantages:
- Reduction in register pressure (because we no longer need GPRs to store
boolean values).
- Logical operations on booleans can be handled more efficiently; we used to
have to move all results from comparisons into GPRs, perform promoted
logical operations in GPRs, and then move the result back into condition
register bits to be used by conditional branches. This can be very
inefficient, because the throughput of these CR <-> GPR moves have high
latency and low throughput (especially when other associated instructions
are accounted for).
- On the POWER7 and similar cores, we can increase total throughput by using
the CR bits. CR bit operations have a dedicated functional unit.
Most of this is more-or-less mechanical: Adjustments were needed in the
calling-convention code, support was added for spilling/restoring individual
condition-register bits, and conditional branch instruction definitions taking
specific CR bits were added (plus patterns and code for generating bit-level
operations).
This is enabled by default when running at -O2 and higher. For -O0 and -O1,
where the ability to debug is more important, this feature is disabled by
default. Individual CR bits do not have assigned DWARF register numbers,
and storing values in CR bits makes them invisible to the debugger.
It is critical, however, that we don't move i1 values that have been promoted
to larger values (such as those passed as function arguments) into bit
registers only to quickly turn around and move the values back into GPRs (such
as happens when values are returned by functions). A pair of target-specific
DAG combines are added to remove the trunc/extends in:
trunc(binary-ops(binary-ops(zext(x), zext(y)), ...)
and:
zext(binary-ops(binary-ops(trunc(x), trunc(y)), ...)
In short, we only want to use CR bits where some of the i1 values come from
comparisons or are used by conditional branches or selects. To put it another
way, if we can do the entire i1 computation in GPRs, then we probably should
(on the POWER7, the GPR-operation throughput is higher, and for all cores, the
CR <-> GPR moves are expensive).
POWER7 test-suite performance results (from 10 runs in each configuration):
SingleSource/Benchmarks/Misc/mandel-2: 35% speedup
MultiSource/Benchmarks/Prolangs-C++/city/city: 21% speedup
MultiSource/Benchmarks/MiBench/automotive-susan: 23% speedup
SingleSource/Benchmarks/CoyoteBench/huffbench: 13% speedup
SingleSource/Benchmarks/Misc-C++/Large/sphereflake: 13% speedup
SingleSource/Benchmarks/Misc-C++/mandel-text: 10% speedup
SingleSource/Benchmarks/Misc-C++-EH/spirit: 10% slowdown
MultiSource/Applications/lemon/lemon: 8% slowdown
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202451 91177308-0d34-0410-b5e6-96231b3b80d8
2014-02-28 00:27:01 +00:00
|
|
|
else if (Cond[0].getImm() == PPC::PRED_BIT_SET)
|
|
|
|
BuildMI(&MBB, DL, get(PPC::BC)).addOperand(Cond[1]).addMBB(TBB);
|
|
|
|
else if (Cond[0].getImm() == PPC::PRED_BIT_UNSET)
|
|
|
|
BuildMI(&MBB, DL, get(PPC::BCn)).addOperand(Cond[1]).addMBB(TBB);
|
2006-10-21 05:36:13 +00:00
|
|
|
else // Conditional branch
|
2010-06-17 22:43:56 +00:00
|
|
|
BuildMI(&MBB, DL, get(PPC::BCC))
|
Add CR-bit tracking to the PowerPC backend for i1 values
This change enables tracking i1 values in the PowerPC backend using the
condition register bits. These bits can be treated on PowerPC as separate
registers; individual bit operations (and, or, xor, etc.) are supported.
Tracking booleans in CR bits has several advantages:
- Reduction in register pressure (because we no longer need GPRs to store
boolean values).
- Logical operations on booleans can be handled more efficiently; we used to
have to move all results from comparisons into GPRs, perform promoted
logical operations in GPRs, and then move the result back into condition
register bits to be used by conditional branches. This can be very
inefficient, because the throughput of these CR <-> GPR moves have high
latency and low throughput (especially when other associated instructions
are accounted for).
- On the POWER7 and similar cores, we can increase total throughput by using
the CR bits. CR bit operations have a dedicated functional unit.
Most of this is more-or-less mechanical: Adjustments were needed in the
calling-convention code, support was added for spilling/restoring individual
condition-register bits, and conditional branch instruction definitions taking
specific CR bits were added (plus patterns and code for generating bit-level
operations).
This is enabled by default when running at -O2 and higher. For -O0 and -O1,
where the ability to debug is more important, this feature is disabled by
default. Individual CR bits do not have assigned DWARF register numbers,
and storing values in CR bits makes them invisible to the debugger.
It is critical, however, that we don't move i1 values that have been promoted
to larger values (such as those passed as function arguments) into bit
registers only to quickly turn around and move the values back into GPRs (such
as happens when values are returned by functions). A pair of target-specific
DAG combines are added to remove the trunc/extends in:
trunc(binary-ops(binary-ops(zext(x), zext(y)), ...)
and:
zext(binary-ops(binary-ops(trunc(x), trunc(y)), ...)
In short, we only want to use CR bits where some of the i1 values come from
comparisons or are used by conditional branches or selects. To put it another
way, if we can do the entire i1 computation in GPRs, then we probably should
(on the POWER7, the GPR-operation throughput is higher, and for all cores, the
CR <-> GPR moves are expensive).
POWER7 test-suite performance results (from 10 runs in each configuration):
SingleSource/Benchmarks/Misc/mandel-2: 35% speedup
MultiSource/Benchmarks/Prolangs-C++/city/city: 21% speedup
MultiSource/Benchmarks/MiBench/automotive-susan: 23% speedup
SingleSource/Benchmarks/CoyoteBench/huffbench: 13% speedup
SingleSource/Benchmarks/Misc-C++/Large/sphereflake: 13% speedup
SingleSource/Benchmarks/Misc-C++/mandel-text: 10% speedup
SingleSource/Benchmarks/Misc-C++-EH/spirit: 10% slowdown
MultiSource/Applications/lemon/lemon: 8% slowdown
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202451 91177308-0d34-0410-b5e6-96231b3b80d8
2014-02-28 00:27:01 +00:00
|
|
|
.addImm(Cond[0].getImm()).addOperand(Cond[1]).addMBB(TBB);
|
2007-05-18 00:05:48 +00:00
|
|
|
return 1;
|
2006-10-17 18:06:55 +00:00
|
|
|
}
|
2010-12-24 04:28:06 +00:00
|
|
|
|
2006-10-21 05:42:09 +00:00
|
|
|
// Two-way Conditional Branch.
|
2012-06-08 15:38:21 +00:00
|
|
|
if (Cond[1].getReg() == PPC::CTR || Cond[1].getReg() == PPC::CTR8)
|
|
|
|
BuildMI(&MBB, DL, get(Cond[0].getImm() ?
|
|
|
|
(isPPC64 ? PPC::BDNZ8 : PPC::BDNZ) :
|
|
|
|
(isPPC64 ? PPC::BDZ8 : PPC::BDZ))).addMBB(TBB);
|
Add CR-bit tracking to the PowerPC backend for i1 values
This change enables tracking i1 values in the PowerPC backend using the
condition register bits. These bits can be treated on PowerPC as separate
registers; individual bit operations (and, or, xor, etc.) are supported.
Tracking booleans in CR bits has several advantages:
- Reduction in register pressure (because we no longer need GPRs to store
boolean values).
- Logical operations on booleans can be handled more efficiently; we used to
have to move all results from comparisons into GPRs, perform promoted
logical operations in GPRs, and then move the result back into condition
register bits to be used by conditional branches. This can be very
inefficient, because the throughput of these CR <-> GPR moves have high
latency and low throughput (especially when other associated instructions
are accounted for).
- On the POWER7 and similar cores, we can increase total throughput by using
the CR bits. CR bit operations have a dedicated functional unit.
Most of this is more-or-less mechanical: Adjustments were needed in the
calling-convention code, support was added for spilling/restoring individual
condition-register bits, and conditional branch instruction definitions taking
specific CR bits were added (plus patterns and code for generating bit-level
operations).
This is enabled by default when running at -O2 and higher. For -O0 and -O1,
where the ability to debug is more important, this feature is disabled by
default. Individual CR bits do not have assigned DWARF register numbers,
and storing values in CR bits makes them invisible to the debugger.
It is critical, however, that we don't move i1 values that have been promoted
to larger values (such as those passed as function arguments) into bit
registers only to quickly turn around and move the values back into GPRs (such
as happens when values are returned by functions). A pair of target-specific
DAG combines are added to remove the trunc/extends in:
trunc(binary-ops(binary-ops(zext(x), zext(y)), ...)
and:
zext(binary-ops(binary-ops(trunc(x), trunc(y)), ...)
In short, we only want to use CR bits where some of the i1 values come from
comparisons or are used by conditional branches or selects. To put it another
way, if we can do the entire i1 computation in GPRs, then we probably should
(on the POWER7, the GPR-operation throughput is higher, and for all cores, the
CR <-> GPR moves are expensive).
POWER7 test-suite performance results (from 10 runs in each configuration):
SingleSource/Benchmarks/Misc/mandel-2: 35% speedup
MultiSource/Benchmarks/Prolangs-C++/city/city: 21% speedup
MultiSource/Benchmarks/MiBench/automotive-susan: 23% speedup
SingleSource/Benchmarks/CoyoteBench/huffbench: 13% speedup
SingleSource/Benchmarks/Misc-C++/Large/sphereflake: 13% speedup
SingleSource/Benchmarks/Misc-C++/mandel-text: 10% speedup
SingleSource/Benchmarks/Misc-C++-EH/spirit: 10% slowdown
MultiSource/Applications/lemon/lemon: 8% slowdown
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202451 91177308-0d34-0410-b5e6-96231b3b80d8
2014-02-28 00:27:01 +00:00
|
|
|
else if (Cond[0].getImm() == PPC::PRED_BIT_SET)
|
|
|
|
BuildMI(&MBB, DL, get(PPC::BC)).addOperand(Cond[1]).addMBB(TBB);
|
|
|
|
else if (Cond[0].getImm() == PPC::PRED_BIT_UNSET)
|
|
|
|
BuildMI(&MBB, DL, get(PPC::BCn)).addOperand(Cond[1]).addMBB(TBB);
|
2012-06-08 15:38:21 +00:00
|
|
|
else
|
|
|
|
BuildMI(&MBB, DL, get(PPC::BCC))
|
Add CR-bit tracking to the PowerPC backend for i1 values
This change enables tracking i1 values in the PowerPC backend using the
condition register bits. These bits can be treated on PowerPC as separate
registers; individual bit operations (and, or, xor, etc.) are supported.
Tracking booleans in CR bits has several advantages:
- Reduction in register pressure (because we no longer need GPRs to store
boolean values).
- Logical operations on booleans can be handled more efficiently; we used to
have to move all results from comparisons into GPRs, perform promoted
logical operations in GPRs, and then move the result back into condition
register bits to be used by conditional branches. This can be very
inefficient, because the throughput of these CR <-> GPR moves have high
latency and low throughput (especially when other associated instructions
are accounted for).
- On the POWER7 and similar cores, we can increase total throughput by using
the CR bits. CR bit operations have a dedicated functional unit.
Most of this is more-or-less mechanical: Adjustments were needed in the
calling-convention code, support was added for spilling/restoring individual
condition-register bits, and conditional branch instruction definitions taking
specific CR bits were added (plus patterns and code for generating bit-level
operations).
This is enabled by default when running at -O2 and higher. For -O0 and -O1,
where the ability to debug is more important, this feature is disabled by
default. Individual CR bits do not have assigned DWARF register numbers,
and storing values in CR bits makes them invisible to the debugger.
It is critical, however, that we don't move i1 values that have been promoted
to larger values (such as those passed as function arguments) into bit
registers only to quickly turn around and move the values back into GPRs (such
as happens when values are returned by functions). A pair of target-specific
DAG combines are added to remove the trunc/extends in:
trunc(binary-ops(binary-ops(zext(x), zext(y)), ...)
and:
zext(binary-ops(binary-ops(trunc(x), trunc(y)), ...)
In short, we only want to use CR bits where some of the i1 values come from
comparisons or are used by conditional branches or selects. To put it another
way, if we can do the entire i1 computation in GPRs, then we probably should
(on the POWER7, the GPR-operation throughput is higher, and for all cores, the
CR <-> GPR moves are expensive).
POWER7 test-suite performance results (from 10 runs in each configuration):
SingleSource/Benchmarks/Misc/mandel-2: 35% speedup
MultiSource/Benchmarks/Prolangs-C++/city/city: 21% speedup
MultiSource/Benchmarks/MiBench/automotive-susan: 23% speedup
SingleSource/Benchmarks/CoyoteBench/huffbench: 13% speedup
SingleSource/Benchmarks/Misc-C++/Large/sphereflake: 13% speedup
SingleSource/Benchmarks/Misc-C++/mandel-text: 10% speedup
SingleSource/Benchmarks/Misc-C++-EH/spirit: 10% slowdown
MultiSource/Applications/lemon/lemon: 8% slowdown
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202451 91177308-0d34-0410-b5e6-96231b3b80d8
2014-02-28 00:27:01 +00:00
|
|
|
.addImm(Cond[0].getImm()).addOperand(Cond[1]).addMBB(TBB);
|
2010-06-17 22:43:56 +00:00
|
|
|
BuildMI(&MBB, DL, get(PPC::B)).addMBB(FBB);
|
2007-05-18 00:05:48 +00:00
|
|
|
return 2;
|
2006-10-13 21:21:17 +00:00
|
|
|
}
|
|
|
|
|
2013-04-05 23:29:01 +00:00
|
|
|
// Select analysis.
|
|
|
|
bool PPCInstrInfo::canInsertSelect(const MachineBasicBlock &MBB,
|
|
|
|
const SmallVectorImpl<MachineOperand> &Cond,
|
|
|
|
unsigned TrueReg, unsigned FalseReg,
|
|
|
|
int &CondCycles, int &TrueCycles, int &FalseCycles) const {
|
2014-06-12 21:48:52 +00:00
|
|
|
if (!Subtarget.hasISEL())
|
2013-04-05 23:29:01 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
if (Cond.size() != 2)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// If this is really a bdnz-like condition, then it cannot be turned into a
|
|
|
|
// select.
|
|
|
|
if (Cond[1].getReg() == PPC::CTR || Cond[1].getReg() == PPC::CTR8)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Check register classes.
|
|
|
|
const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
|
|
|
|
const TargetRegisterClass *RC =
|
|
|
|
RI.getCommonSubClass(MRI.getRegClass(TrueReg), MRI.getRegClass(FalseReg));
|
|
|
|
if (!RC)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// isel is for regular integer GPRs only.
|
|
|
|
if (!PPC::GPRCRegClass.hasSubClassEq(RC) &&
|
Fix register subclass handling in PPCInstrInfo::insertSelect
PPCInstrInfo::insertSelect and PPCInstrInfo::canInsertSelect were computing the
common subclass of the true and false inputs, and then selecting either the
32-bit or the 64-bit isel variant based on the result of calling
PPC::GPRCRegClass.hasSubClassEq(RC) and PPC::G8RCRegClass.hasSubClassEq(RC)
(where RC is the common subclass). Unfortunately, this is not quite right: if
we have something like this:
%vreg8<def> = SELECT_CC_I8 %vreg4<kill>, %vreg7<kill>, %vreg6<kill>, 76;
G8RC_and_G8RC_NOX0:%vreg8 CRRC:%vreg4 G8RC_NOX0:%vreg7,%vreg6
then the common subclass of G8RC_and_G8RC_NOX0 and G8RC_NOX0 is G8RC_NOX0, and
G8RC_NOX0 is not a subclass of G8RC (because it also contains the ZERO8
pseudo-register). As a result, we also need to check the common subclass
against GPRC_NOR0 and G8RC_NOX0 explicitly.
This had not been a problem for clients of insertSelect that called
canInsertSelect first (because it had a compensating mistake), but insertSelect
is also used by the PPC pseudo-instruction expander, and this error was causing
a problem in that context.
This problem was found by csmith.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@186343 91177308-0d34-0410-b5e6-96231b3b80d8
2013-07-15 20:22:58 +00:00
|
|
|
!PPC::GPRC_NOR0RegClass.hasSubClassEq(RC) &&
|
|
|
|
!PPC::G8RCRegClass.hasSubClassEq(RC) &&
|
|
|
|
!PPC::G8RC_NOX0RegClass.hasSubClassEq(RC))
|
2013-04-05 23:29:01 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
// FIXME: These numbers are for the A2, how well they work for other cores is
|
|
|
|
// an open question. On the A2, the isel instruction has a 2-cycle latency
|
|
|
|
// but single-cycle throughput. These numbers are used in combination with
|
|
|
|
// the MispredictPenalty setting from the active SchedMachineModel.
|
|
|
|
CondCycles = 1;
|
|
|
|
TrueCycles = 1;
|
|
|
|
FalseCycles = 1;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PPCInstrInfo::insertSelect(MachineBasicBlock &MBB,
|
|
|
|
MachineBasicBlock::iterator MI, DebugLoc dl,
|
|
|
|
unsigned DestReg,
|
|
|
|
const SmallVectorImpl<MachineOperand> &Cond,
|
|
|
|
unsigned TrueReg, unsigned FalseReg) const {
|
|
|
|
assert(Cond.size() == 2 &&
|
|
|
|
"PPC branch conditions have two components!");
|
|
|
|
|
2014-06-12 21:48:52 +00:00
|
|
|
assert(Subtarget.hasISEL() &&
|
2013-04-05 23:29:01 +00:00
|
|
|
"Cannot insert select on target without ISEL support");
|
|
|
|
|
|
|
|
// Get the register classes.
|
|
|
|
MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
|
|
|
|
const TargetRegisterClass *RC =
|
|
|
|
RI.getCommonSubClass(MRI.getRegClass(TrueReg), MRI.getRegClass(FalseReg));
|
|
|
|
assert(RC && "TrueReg and FalseReg must have overlapping register classes");
|
Fix register subclass handling in PPCInstrInfo::insertSelect
PPCInstrInfo::insertSelect and PPCInstrInfo::canInsertSelect were computing the
common subclass of the true and false inputs, and then selecting either the
32-bit or the 64-bit isel variant based on the result of calling
PPC::GPRCRegClass.hasSubClassEq(RC) and PPC::G8RCRegClass.hasSubClassEq(RC)
(where RC is the common subclass). Unfortunately, this is not quite right: if
we have something like this:
%vreg8<def> = SELECT_CC_I8 %vreg4<kill>, %vreg7<kill>, %vreg6<kill>, 76;
G8RC_and_G8RC_NOX0:%vreg8 CRRC:%vreg4 G8RC_NOX0:%vreg7,%vreg6
then the common subclass of G8RC_and_G8RC_NOX0 and G8RC_NOX0 is G8RC_NOX0, and
G8RC_NOX0 is not a subclass of G8RC (because it also contains the ZERO8
pseudo-register). As a result, we also need to check the common subclass
against GPRC_NOR0 and G8RC_NOX0 explicitly.
This had not been a problem for clients of insertSelect that called
canInsertSelect first (because it had a compensating mistake), but insertSelect
is also used by the PPC pseudo-instruction expander, and this error was causing
a problem in that context.
This problem was found by csmith.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@186343 91177308-0d34-0410-b5e6-96231b3b80d8
2013-07-15 20:22:58 +00:00
|
|
|
|
|
|
|
bool Is64Bit = PPC::G8RCRegClass.hasSubClassEq(RC) ||
|
|
|
|
PPC::G8RC_NOX0RegClass.hasSubClassEq(RC);
|
|
|
|
assert((Is64Bit ||
|
|
|
|
PPC::GPRCRegClass.hasSubClassEq(RC) ||
|
|
|
|
PPC::GPRC_NOR0RegClass.hasSubClassEq(RC)) &&
|
2013-04-05 23:29:01 +00:00
|
|
|
"isel is for regular integer GPRs only");
|
|
|
|
|
Fix register subclass handling in PPCInstrInfo::insertSelect
PPCInstrInfo::insertSelect and PPCInstrInfo::canInsertSelect were computing the
common subclass of the true and false inputs, and then selecting either the
32-bit or the 64-bit isel variant based on the result of calling
PPC::GPRCRegClass.hasSubClassEq(RC) and PPC::G8RCRegClass.hasSubClassEq(RC)
(where RC is the common subclass). Unfortunately, this is not quite right: if
we have something like this:
%vreg8<def> = SELECT_CC_I8 %vreg4<kill>, %vreg7<kill>, %vreg6<kill>, 76;
G8RC_and_G8RC_NOX0:%vreg8 CRRC:%vreg4 G8RC_NOX0:%vreg7,%vreg6
then the common subclass of G8RC_and_G8RC_NOX0 and G8RC_NOX0 is G8RC_NOX0, and
G8RC_NOX0 is not a subclass of G8RC (because it also contains the ZERO8
pseudo-register). As a result, we also need to check the common subclass
against GPRC_NOR0 and G8RC_NOX0 explicitly.
This had not been a problem for clients of insertSelect that called
canInsertSelect first (because it had a compensating mistake), but insertSelect
is also used by the PPC pseudo-instruction expander, and this error was causing
a problem in that context.
This problem was found by csmith.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@186343 91177308-0d34-0410-b5e6-96231b3b80d8
2013-07-15 20:22:58 +00:00
|
|
|
unsigned OpCode = Is64Bit ? PPC::ISEL8 : PPC::ISEL;
|
2013-04-05 23:29:01 +00:00
|
|
|
unsigned SelectPred = Cond[0].getImm();
|
|
|
|
|
|
|
|
unsigned SubIdx;
|
|
|
|
bool SwapOps;
|
|
|
|
switch (SelectPred) {
|
|
|
|
default: llvm_unreachable("invalid predicate for isel");
|
|
|
|
case PPC::PRED_EQ: SubIdx = PPC::sub_eq; SwapOps = false; break;
|
|
|
|
case PPC::PRED_NE: SubIdx = PPC::sub_eq; SwapOps = true; break;
|
|
|
|
case PPC::PRED_LT: SubIdx = PPC::sub_lt; SwapOps = false; break;
|
|
|
|
case PPC::PRED_GE: SubIdx = PPC::sub_lt; SwapOps = true; break;
|
|
|
|
case PPC::PRED_GT: SubIdx = PPC::sub_gt; SwapOps = false; break;
|
|
|
|
case PPC::PRED_LE: SubIdx = PPC::sub_gt; SwapOps = true; break;
|
|
|
|
case PPC::PRED_UN: SubIdx = PPC::sub_un; SwapOps = false; break;
|
|
|
|
case PPC::PRED_NU: SubIdx = PPC::sub_un; SwapOps = true; break;
|
Add CR-bit tracking to the PowerPC backend for i1 values
This change enables tracking i1 values in the PowerPC backend using the
condition register bits. These bits can be treated on PowerPC as separate
registers; individual bit operations (and, or, xor, etc.) are supported.
Tracking booleans in CR bits has several advantages:
- Reduction in register pressure (because we no longer need GPRs to store
boolean values).
- Logical operations on booleans can be handled more efficiently; we used to
have to move all results from comparisons into GPRs, perform promoted
logical operations in GPRs, and then move the result back into condition
register bits to be used by conditional branches. This can be very
inefficient, because the throughput of these CR <-> GPR moves have high
latency and low throughput (especially when other associated instructions
are accounted for).
- On the POWER7 and similar cores, we can increase total throughput by using
the CR bits. CR bit operations have a dedicated functional unit.
Most of this is more-or-less mechanical: Adjustments were needed in the
calling-convention code, support was added for spilling/restoring individual
condition-register bits, and conditional branch instruction definitions taking
specific CR bits were added (plus patterns and code for generating bit-level
operations).
This is enabled by default when running at -O2 and higher. For -O0 and -O1,
where the ability to debug is more important, this feature is disabled by
default. Individual CR bits do not have assigned DWARF register numbers,
and storing values in CR bits makes them invisible to the debugger.
It is critical, however, that we don't move i1 values that have been promoted
to larger values (such as those passed as function arguments) into bit
registers only to quickly turn around and move the values back into GPRs (such
as happens when values are returned by functions). A pair of target-specific
DAG combines are added to remove the trunc/extends in:
trunc(binary-ops(binary-ops(zext(x), zext(y)), ...)
and:
zext(binary-ops(binary-ops(trunc(x), trunc(y)), ...)
In short, we only want to use CR bits where some of the i1 values come from
comparisons or are used by conditional branches or selects. To put it another
way, if we can do the entire i1 computation in GPRs, then we probably should
(on the POWER7, the GPR-operation throughput is higher, and for all cores, the
CR <-> GPR moves are expensive).
POWER7 test-suite performance results (from 10 runs in each configuration):
SingleSource/Benchmarks/Misc/mandel-2: 35% speedup
MultiSource/Benchmarks/Prolangs-C++/city/city: 21% speedup
MultiSource/Benchmarks/MiBench/automotive-susan: 23% speedup
SingleSource/Benchmarks/CoyoteBench/huffbench: 13% speedup
SingleSource/Benchmarks/Misc-C++/Large/sphereflake: 13% speedup
SingleSource/Benchmarks/Misc-C++/mandel-text: 10% speedup
SingleSource/Benchmarks/Misc-C++-EH/spirit: 10% slowdown
MultiSource/Applications/lemon/lemon: 8% slowdown
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202451 91177308-0d34-0410-b5e6-96231b3b80d8
2014-02-28 00:27:01 +00:00
|
|
|
case PPC::PRED_BIT_SET: SubIdx = 0; SwapOps = false; break;
|
|
|
|
case PPC::PRED_BIT_UNSET: SubIdx = 0; SwapOps = true; break;
|
2013-04-05 23:29:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
unsigned FirstReg = SwapOps ? FalseReg : TrueReg,
|
|
|
|
SecondReg = SwapOps ? TrueReg : FalseReg;
|
|
|
|
|
|
|
|
// The first input register of isel cannot be r0. If it is a member
|
|
|
|
// of a register class that can be r0, then copy it first (the
|
|
|
|
// register allocator should eliminate the copy).
|
|
|
|
if (MRI.getRegClass(FirstReg)->contains(PPC::R0) ||
|
|
|
|
MRI.getRegClass(FirstReg)->contains(PPC::X0)) {
|
|
|
|
const TargetRegisterClass *FirstRC =
|
|
|
|
MRI.getRegClass(FirstReg)->contains(PPC::X0) ?
|
|
|
|
&PPC::G8RC_NOX0RegClass : &PPC::GPRC_NOR0RegClass;
|
|
|
|
unsigned OldFirstReg = FirstReg;
|
|
|
|
FirstReg = MRI.createVirtualRegister(FirstRC);
|
|
|
|
BuildMI(MBB, MI, dl, get(TargetOpcode::COPY), FirstReg)
|
|
|
|
.addReg(OldFirstReg);
|
|
|
|
}
|
|
|
|
|
|
|
|
BuildMI(MBB, MI, dl, get(OpCode), DestReg)
|
|
|
|
.addReg(FirstReg).addReg(SecondReg)
|
|
|
|
.addReg(Cond[1].getReg(), 0, SubIdx);
|
|
|
|
}
|
|
|
|
|
2010-07-11 07:31:00 +00:00
|
|
|
void PPCInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
|
|
|
|
MachineBasicBlock::iterator I, DebugLoc DL,
|
|
|
|
unsigned DestReg, unsigned SrcReg,
|
|
|
|
bool KillSrc) const {
|
[PowerPC] Initial support for the VSX instruction set
VSX is an ISA extension supported on the POWER7 and later cores that enhances
floating-point vector and scalar capabilities. Among other things, this adds
<2 x double> support and generally helps to reduce register pressure.
The interesting part of this ISA feature is the register configuration: there
are 64 new 128-bit vector registers, the 32 of which are super-registers of the
existing 32 scalar floating-point registers, and the second 32 of which overlap
with the 32 Altivec vector registers. This makes things like vector insertion
and extraction tricky: this can be free but only if we force a restriction to
the right register subclass when needed. A new "minipass" PPCVSXCopy takes care
of this (although it could do a more-optimal job of it; see the comment about
unnecessary copies below).
Please note that, currently, VSX is not enabled by default when targeting
anything because it is not yet ready for that. The assembler and disassembler
are fully implemented and tested. However:
- CodeGen support causes miscompiles; test-suite runtime failures:
MultiSource/Benchmarks/FreeBench/distray/distray
MultiSource/Benchmarks/McCat/08-main/main
MultiSource/Benchmarks/Olden/voronoi/voronoi
MultiSource/Benchmarks/mafft/pairlocalalign
MultiSource/Benchmarks/tramp3d-v4/tramp3d-v4
SingleSource/Benchmarks/CoyoteBench/almabench
SingleSource/Benchmarks/Misc/matmul_f64_4x4
- The lowering currently falls back to using Altivec instructions far more
than it should. Worse, there are some things that are scalarized through the
stack that shouldn't be.
- A lot of unnecessary copies make it past the optimizers, and this needs to
be fixed.
- Many more regression tests are needed.
Normally, I'd fix these things prior to committing, but there are some
students and other contributors who would like to work this, and so it makes
sense to move this development process upstream where it can be subject to the
regular code-review procedures.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203768 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-13 07:58:58 +00:00
|
|
|
// We can end up with self copies and similar things as a result of VSX copy
|
2014-03-27 22:46:28 +00:00
|
|
|
// legalization. Promote them here.
|
[PowerPC] Initial support for the VSX instruction set
VSX is an ISA extension supported on the POWER7 and later cores that enhances
floating-point vector and scalar capabilities. Among other things, this adds
<2 x double> support and generally helps to reduce register pressure.
The interesting part of this ISA feature is the register configuration: there
are 64 new 128-bit vector registers, the 32 of which are super-registers of the
existing 32 scalar floating-point registers, and the second 32 of which overlap
with the 32 Altivec vector registers. This makes things like vector insertion
and extraction tricky: this can be free but only if we force a restriction to
the right register subclass when needed. A new "minipass" PPCVSXCopy takes care
of this (although it could do a more-optimal job of it; see the comment about
unnecessary copies below).
Please note that, currently, VSX is not enabled by default when targeting
anything because it is not yet ready for that. The assembler and disassembler
are fully implemented and tested. However:
- CodeGen support causes miscompiles; test-suite runtime failures:
MultiSource/Benchmarks/FreeBench/distray/distray
MultiSource/Benchmarks/McCat/08-main/main
MultiSource/Benchmarks/Olden/voronoi/voronoi
MultiSource/Benchmarks/mafft/pairlocalalign
MultiSource/Benchmarks/tramp3d-v4/tramp3d-v4
SingleSource/Benchmarks/CoyoteBench/almabench
SingleSource/Benchmarks/Misc/matmul_f64_4x4
- The lowering currently falls back to using Altivec instructions far more
than it should. Worse, there are some things that are scalarized through the
stack that shouldn't be.
- A lot of unnecessary copies make it past the optimizers, and this needs to
be fixed.
- Many more regression tests are needed.
Normally, I'd fix these things prior to committing, but there are some
students and other contributors who would like to work this, and so it makes
sense to move this development process upstream where it can be subject to the
regular code-review procedures.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203768 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-13 07:58:58 +00:00
|
|
|
const TargetRegisterInfo *TRI = &getRegisterInfo();
|
|
|
|
if (PPC::F8RCRegClass.contains(DestReg) &&
|
|
|
|
PPC::VSLRCRegClass.contains(SrcReg)) {
|
|
|
|
unsigned SuperReg =
|
|
|
|
TRI->getMatchingSuperReg(DestReg, PPC::sub_64, &PPC::VSRCRegClass);
|
|
|
|
|
2014-03-27 22:46:28 +00:00
|
|
|
if (VSXSelfCopyCrash && SrcReg == SuperReg)
|
|
|
|
llvm_unreachable("nop VSX copy");
|
[PowerPC] Initial support for the VSX instruction set
VSX is an ISA extension supported on the POWER7 and later cores that enhances
floating-point vector and scalar capabilities. Among other things, this adds
<2 x double> support and generally helps to reduce register pressure.
The interesting part of this ISA feature is the register configuration: there
are 64 new 128-bit vector registers, the 32 of which are super-registers of the
existing 32 scalar floating-point registers, and the second 32 of which overlap
with the 32 Altivec vector registers. This makes things like vector insertion
and extraction tricky: this can be free but only if we force a restriction to
the right register subclass when needed. A new "minipass" PPCVSXCopy takes care
of this (although it could do a more-optimal job of it; see the comment about
unnecessary copies below).
Please note that, currently, VSX is not enabled by default when targeting
anything because it is not yet ready for that. The assembler and disassembler
are fully implemented and tested. However:
- CodeGen support causes miscompiles; test-suite runtime failures:
MultiSource/Benchmarks/FreeBench/distray/distray
MultiSource/Benchmarks/McCat/08-main/main
MultiSource/Benchmarks/Olden/voronoi/voronoi
MultiSource/Benchmarks/mafft/pairlocalalign
MultiSource/Benchmarks/tramp3d-v4/tramp3d-v4
SingleSource/Benchmarks/CoyoteBench/almabench
SingleSource/Benchmarks/Misc/matmul_f64_4x4
- The lowering currently falls back to using Altivec instructions far more
than it should. Worse, there are some things that are scalarized through the
stack that shouldn't be.
- A lot of unnecessary copies make it past the optimizers, and this needs to
be fixed.
- Many more regression tests are needed.
Normally, I'd fix these things prior to committing, but there are some
students and other contributors who would like to work this, and so it makes
sense to move this development process upstream where it can be subject to the
regular code-review procedures.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203768 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-13 07:58:58 +00:00
|
|
|
|
|
|
|
DestReg = SuperReg;
|
|
|
|
} else if (PPC::VRRCRegClass.contains(DestReg) &&
|
|
|
|
PPC::VSHRCRegClass.contains(SrcReg)) {
|
|
|
|
unsigned SuperReg =
|
|
|
|
TRI->getMatchingSuperReg(DestReg, PPC::sub_128, &PPC::VSRCRegClass);
|
|
|
|
|
2014-03-27 22:46:28 +00:00
|
|
|
if (VSXSelfCopyCrash && SrcReg == SuperReg)
|
|
|
|
llvm_unreachable("nop VSX copy");
|
[PowerPC] Initial support for the VSX instruction set
VSX is an ISA extension supported on the POWER7 and later cores that enhances
floating-point vector and scalar capabilities. Among other things, this adds
<2 x double> support and generally helps to reduce register pressure.
The interesting part of this ISA feature is the register configuration: there
are 64 new 128-bit vector registers, the 32 of which are super-registers of the
existing 32 scalar floating-point registers, and the second 32 of which overlap
with the 32 Altivec vector registers. This makes things like vector insertion
and extraction tricky: this can be free but only if we force a restriction to
the right register subclass when needed. A new "minipass" PPCVSXCopy takes care
of this (although it could do a more-optimal job of it; see the comment about
unnecessary copies below).
Please note that, currently, VSX is not enabled by default when targeting
anything because it is not yet ready for that. The assembler and disassembler
are fully implemented and tested. However:
- CodeGen support causes miscompiles; test-suite runtime failures:
MultiSource/Benchmarks/FreeBench/distray/distray
MultiSource/Benchmarks/McCat/08-main/main
MultiSource/Benchmarks/Olden/voronoi/voronoi
MultiSource/Benchmarks/mafft/pairlocalalign
MultiSource/Benchmarks/tramp3d-v4/tramp3d-v4
SingleSource/Benchmarks/CoyoteBench/almabench
SingleSource/Benchmarks/Misc/matmul_f64_4x4
- The lowering currently falls back to using Altivec instructions far more
than it should. Worse, there are some things that are scalarized through the
stack that shouldn't be.
- A lot of unnecessary copies make it past the optimizers, and this needs to
be fixed.
- Many more regression tests are needed.
Normally, I'd fix these things prior to committing, but there are some
students and other contributors who would like to work this, and so it makes
sense to move this development process upstream where it can be subject to the
regular code-review procedures.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203768 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-13 07:58:58 +00:00
|
|
|
|
|
|
|
DestReg = SuperReg;
|
|
|
|
} else if (PPC::F8RCRegClass.contains(SrcReg) &&
|
|
|
|
PPC::VSLRCRegClass.contains(DestReg)) {
|
|
|
|
unsigned SuperReg =
|
|
|
|
TRI->getMatchingSuperReg(SrcReg, PPC::sub_64, &PPC::VSRCRegClass);
|
|
|
|
|
2014-03-27 22:46:28 +00:00
|
|
|
if (VSXSelfCopyCrash && DestReg == SuperReg)
|
|
|
|
llvm_unreachable("nop VSX copy");
|
[PowerPC] Initial support for the VSX instruction set
VSX is an ISA extension supported on the POWER7 and later cores that enhances
floating-point vector and scalar capabilities. Among other things, this adds
<2 x double> support and generally helps to reduce register pressure.
The interesting part of this ISA feature is the register configuration: there
are 64 new 128-bit vector registers, the 32 of which are super-registers of the
existing 32 scalar floating-point registers, and the second 32 of which overlap
with the 32 Altivec vector registers. This makes things like vector insertion
and extraction tricky: this can be free but only if we force a restriction to
the right register subclass when needed. A new "minipass" PPCVSXCopy takes care
of this (although it could do a more-optimal job of it; see the comment about
unnecessary copies below).
Please note that, currently, VSX is not enabled by default when targeting
anything because it is not yet ready for that. The assembler and disassembler
are fully implemented and tested. However:
- CodeGen support causes miscompiles; test-suite runtime failures:
MultiSource/Benchmarks/FreeBench/distray/distray
MultiSource/Benchmarks/McCat/08-main/main
MultiSource/Benchmarks/Olden/voronoi/voronoi
MultiSource/Benchmarks/mafft/pairlocalalign
MultiSource/Benchmarks/tramp3d-v4/tramp3d-v4
SingleSource/Benchmarks/CoyoteBench/almabench
SingleSource/Benchmarks/Misc/matmul_f64_4x4
- The lowering currently falls back to using Altivec instructions far more
than it should. Worse, there are some things that are scalarized through the
stack that shouldn't be.
- A lot of unnecessary copies make it past the optimizers, and this needs to
be fixed.
- Many more regression tests are needed.
Normally, I'd fix these things prior to committing, but there are some
students and other contributors who would like to work this, and so it makes
sense to move this development process upstream where it can be subject to the
regular code-review procedures.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203768 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-13 07:58:58 +00:00
|
|
|
|
|
|
|
SrcReg = SuperReg;
|
|
|
|
} else if (PPC::VRRCRegClass.contains(SrcReg) &&
|
|
|
|
PPC::VSHRCRegClass.contains(DestReg)) {
|
|
|
|
unsigned SuperReg =
|
|
|
|
TRI->getMatchingSuperReg(SrcReg, PPC::sub_128, &PPC::VSRCRegClass);
|
|
|
|
|
2014-03-27 22:46:28 +00:00
|
|
|
if (VSXSelfCopyCrash && DestReg == SuperReg)
|
|
|
|
llvm_unreachable("nop VSX copy");
|
[PowerPC] Initial support for the VSX instruction set
VSX is an ISA extension supported on the POWER7 and later cores that enhances
floating-point vector and scalar capabilities. Among other things, this adds
<2 x double> support and generally helps to reduce register pressure.
The interesting part of this ISA feature is the register configuration: there
are 64 new 128-bit vector registers, the 32 of which are super-registers of the
existing 32 scalar floating-point registers, and the second 32 of which overlap
with the 32 Altivec vector registers. This makes things like vector insertion
and extraction tricky: this can be free but only if we force a restriction to
the right register subclass when needed. A new "minipass" PPCVSXCopy takes care
of this (although it could do a more-optimal job of it; see the comment about
unnecessary copies below).
Please note that, currently, VSX is not enabled by default when targeting
anything because it is not yet ready for that. The assembler and disassembler
are fully implemented and tested. However:
- CodeGen support causes miscompiles; test-suite runtime failures:
MultiSource/Benchmarks/FreeBench/distray/distray
MultiSource/Benchmarks/McCat/08-main/main
MultiSource/Benchmarks/Olden/voronoi/voronoi
MultiSource/Benchmarks/mafft/pairlocalalign
MultiSource/Benchmarks/tramp3d-v4/tramp3d-v4
SingleSource/Benchmarks/CoyoteBench/almabench
SingleSource/Benchmarks/Misc/matmul_f64_4x4
- The lowering currently falls back to using Altivec instructions far more
than it should. Worse, there are some things that are scalarized through the
stack that shouldn't be.
- A lot of unnecessary copies make it past the optimizers, and this needs to
be fixed.
- Many more regression tests are needed.
Normally, I'd fix these things prior to committing, but there are some
students and other contributors who would like to work this, and so it makes
sense to move this development process upstream where it can be subject to the
regular code-review procedures.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203768 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-13 07:58:58 +00:00
|
|
|
|
|
|
|
SrcReg = SuperReg;
|
|
|
|
}
|
|
|
|
|
2010-07-11 07:31:00 +00:00
|
|
|
unsigned Opc;
|
|
|
|
if (PPC::GPRCRegClass.contains(DestReg, SrcReg))
|
|
|
|
Opc = PPC::OR;
|
|
|
|
else if (PPC::G8RCRegClass.contains(DestReg, SrcReg))
|
|
|
|
Opc = PPC::OR8;
|
|
|
|
else if (PPC::F4RCRegClass.contains(DestReg, SrcReg))
|
|
|
|
Opc = PPC::FMR;
|
|
|
|
else if (PPC::CRRCRegClass.contains(DestReg, SrcReg))
|
|
|
|
Opc = PPC::MCRF;
|
|
|
|
else if (PPC::VRRCRegClass.contains(DestReg, SrcReg))
|
|
|
|
Opc = PPC::VOR;
|
[PowerPC] Initial support for the VSX instruction set
VSX is an ISA extension supported on the POWER7 and later cores that enhances
floating-point vector and scalar capabilities. Among other things, this adds
<2 x double> support and generally helps to reduce register pressure.
The interesting part of this ISA feature is the register configuration: there
are 64 new 128-bit vector registers, the 32 of which are super-registers of the
existing 32 scalar floating-point registers, and the second 32 of which overlap
with the 32 Altivec vector registers. This makes things like vector insertion
and extraction tricky: this can be free but only if we force a restriction to
the right register subclass when needed. A new "minipass" PPCVSXCopy takes care
of this (although it could do a more-optimal job of it; see the comment about
unnecessary copies below).
Please note that, currently, VSX is not enabled by default when targeting
anything because it is not yet ready for that. The assembler and disassembler
are fully implemented and tested. However:
- CodeGen support causes miscompiles; test-suite runtime failures:
MultiSource/Benchmarks/FreeBench/distray/distray
MultiSource/Benchmarks/McCat/08-main/main
MultiSource/Benchmarks/Olden/voronoi/voronoi
MultiSource/Benchmarks/mafft/pairlocalalign
MultiSource/Benchmarks/tramp3d-v4/tramp3d-v4
SingleSource/Benchmarks/CoyoteBench/almabench
SingleSource/Benchmarks/Misc/matmul_f64_4x4
- The lowering currently falls back to using Altivec instructions far more
than it should. Worse, there are some things that are scalarized through the
stack that shouldn't be.
- A lot of unnecessary copies make it past the optimizers, and this needs to
be fixed.
- Many more regression tests are needed.
Normally, I'd fix these things prior to committing, but there are some
students and other contributors who would like to work this, and so it makes
sense to move this development process upstream where it can be subject to the
regular code-review procedures.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203768 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-13 07:58:58 +00:00
|
|
|
else if (PPC::VSRCRegClass.contains(DestReg, SrcReg))
|
[PowerPC] Update comment re: VSX copy-instruction selection
I've done some experimentation with this, and it looks like using the
lower-latency (but lower throughput) copy instruction is essentially always the
right thing to do.
My assumption is that, in order to be relatively sure that the higher-latency
copy will increase throughput, we'd want to have it unlikely to be in-flight
with its use. On the P7, the global completion table (GCT) can hold a maximum
of 120 instructions, shared among all active threads (up to 4), giving 30
instructions per thread. So specifically, I'd require at least that many
instructions between the copy and the use before the high-latency variant is
used.
Trying this, however, over the entire test suite resulted in zero cases where
the high-latency form would be preferable. This may be a consequence of the
fact that the scheduler views copies as free, and so they tend to end up close
to their uses. For this experiment I created a function:
unsigned chooseVSXCopy(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I,
unsigned DestReg, unsigned SrcReg,
unsigned StartDist = 1,
unsigned Depth = 3) const;
with an implementation like:
if (!Depth)
return PPC::XXLOR;
const unsigned MaxDist = 30;
unsigned Dist = StartDist;
for (auto J = I, JE = MBB.end(); J != JE && Dist <= MaxDist; ++J) {
if (J->isTransient() && !J->isCopy())
continue;
if (J->isCall() || J->isReturn() || J->readsRegister(DestReg, TRI))
return PPC::XXLOR;
++Dist;
}
// We've exceeded the required distance for the high-latency form, use it.
if (Dist > MaxDist)
return PPC::XVCPSGNDP;
// If this is only an exit block, use the low-latency form.
if (MBB.succ_empty())
return PPC::XXLOR;
// We've reached the end of the block, check the successor blocks (up to some
// depth), and use the high-latency form if that is okay with all successors.
for (auto J = MBB.succ_begin(), JE = MBB.succ_end(); J != JE; ++J) {
if (chooseVSXCopy(**J, (*J)->begin(), DestReg, SrcReg,
Dist, --Depth) == PPC::XXLOR)
return PPC::XXLOR;
}
// All of our successor blocks seem okay with the high-latency variant, so
// we'll use it.
return PPC::XVCPSGNDP;
and then changed the copy opcode selection from:
Opc = PPC::XXLOR;
to:
Opc = chooseVSXCopy(MBB, std::next(I), DestReg, SrcReg);
In conclusion, I'm removing the FIXME from the comment, because I believe that
there is, at least absent other examples, nothing to fix.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204591 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-24 09:36:36 +00:00
|
|
|
// There are two different ways this can be done:
|
[PowerPC] Initial support for the VSX instruction set
VSX is an ISA extension supported on the POWER7 and later cores that enhances
floating-point vector and scalar capabilities. Among other things, this adds
<2 x double> support and generally helps to reduce register pressure.
The interesting part of this ISA feature is the register configuration: there
are 64 new 128-bit vector registers, the 32 of which are super-registers of the
existing 32 scalar floating-point registers, and the second 32 of which overlap
with the 32 Altivec vector registers. This makes things like vector insertion
and extraction tricky: this can be free but only if we force a restriction to
the right register subclass when needed. A new "minipass" PPCVSXCopy takes care
of this (although it could do a more-optimal job of it; see the comment about
unnecessary copies below).
Please note that, currently, VSX is not enabled by default when targeting
anything because it is not yet ready for that. The assembler and disassembler
are fully implemented and tested. However:
- CodeGen support causes miscompiles; test-suite runtime failures:
MultiSource/Benchmarks/FreeBench/distray/distray
MultiSource/Benchmarks/McCat/08-main/main
MultiSource/Benchmarks/Olden/voronoi/voronoi
MultiSource/Benchmarks/mafft/pairlocalalign
MultiSource/Benchmarks/tramp3d-v4/tramp3d-v4
SingleSource/Benchmarks/CoyoteBench/almabench
SingleSource/Benchmarks/Misc/matmul_f64_4x4
- The lowering currently falls back to using Altivec instructions far more
than it should. Worse, there are some things that are scalarized through the
stack that shouldn't be.
- A lot of unnecessary copies make it past the optimizers, and this needs to
be fixed.
- Many more regression tests are needed.
Normally, I'd fix these things prior to committing, but there are some
students and other contributors who would like to work this, and so it makes
sense to move this development process upstream where it can be subject to the
regular code-review procedures.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203768 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-13 07:58:58 +00:00
|
|
|
// 1. xxlor : This has lower latency (on the P7), 2 cycles, but can only
|
|
|
|
// issue in VSU pipeline 0.
|
|
|
|
// 2. xmovdp/xmovsp: This has higher latency (on the P7), 6 cycles, but
|
|
|
|
// can go to either pipeline.
|
[PowerPC] Update comment re: VSX copy-instruction selection
I've done some experimentation with this, and it looks like using the
lower-latency (but lower throughput) copy instruction is essentially always the
right thing to do.
My assumption is that, in order to be relatively sure that the higher-latency
copy will increase throughput, we'd want to have it unlikely to be in-flight
with its use. On the P7, the global completion table (GCT) can hold a maximum
of 120 instructions, shared among all active threads (up to 4), giving 30
instructions per thread. So specifically, I'd require at least that many
instructions between the copy and the use before the high-latency variant is
used.
Trying this, however, over the entire test suite resulted in zero cases where
the high-latency form would be preferable. This may be a consequence of the
fact that the scheduler views copies as free, and so they tend to end up close
to their uses. For this experiment I created a function:
unsigned chooseVSXCopy(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I,
unsigned DestReg, unsigned SrcReg,
unsigned StartDist = 1,
unsigned Depth = 3) const;
with an implementation like:
if (!Depth)
return PPC::XXLOR;
const unsigned MaxDist = 30;
unsigned Dist = StartDist;
for (auto J = I, JE = MBB.end(); J != JE && Dist <= MaxDist; ++J) {
if (J->isTransient() && !J->isCopy())
continue;
if (J->isCall() || J->isReturn() || J->readsRegister(DestReg, TRI))
return PPC::XXLOR;
++Dist;
}
// We've exceeded the required distance for the high-latency form, use it.
if (Dist > MaxDist)
return PPC::XVCPSGNDP;
// If this is only an exit block, use the low-latency form.
if (MBB.succ_empty())
return PPC::XXLOR;
// We've reached the end of the block, check the successor blocks (up to some
// depth), and use the high-latency form if that is okay with all successors.
for (auto J = MBB.succ_begin(), JE = MBB.succ_end(); J != JE; ++J) {
if (chooseVSXCopy(**J, (*J)->begin(), DestReg, SrcReg,
Dist, --Depth) == PPC::XXLOR)
return PPC::XXLOR;
}
// All of our successor blocks seem okay with the high-latency variant, so
// we'll use it.
return PPC::XVCPSGNDP;
and then changed the copy opcode selection from:
Opc = PPC::XXLOR;
to:
Opc = chooseVSXCopy(MBB, std::next(I), DestReg, SrcReg);
In conclusion, I'm removing the FIXME from the comment, because I believe that
there is, at least absent other examples, nothing to fix.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204591 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-24 09:36:36 +00:00
|
|
|
// We'll always use xxlor here, because in practically all cases where
|
|
|
|
// copies are generated, they are close enough to some use that the
|
|
|
|
// lower-latency form is preferable.
|
[PowerPC] Initial support for the VSX instruction set
VSX is an ISA extension supported on the POWER7 and later cores that enhances
floating-point vector and scalar capabilities. Among other things, this adds
<2 x double> support and generally helps to reduce register pressure.
The interesting part of this ISA feature is the register configuration: there
are 64 new 128-bit vector registers, the 32 of which are super-registers of the
existing 32 scalar floating-point registers, and the second 32 of which overlap
with the 32 Altivec vector registers. This makes things like vector insertion
and extraction tricky: this can be free but only if we force a restriction to
the right register subclass when needed. A new "minipass" PPCVSXCopy takes care
of this (although it could do a more-optimal job of it; see the comment about
unnecessary copies below).
Please note that, currently, VSX is not enabled by default when targeting
anything because it is not yet ready for that. The assembler and disassembler
are fully implemented and tested. However:
- CodeGen support causes miscompiles; test-suite runtime failures:
MultiSource/Benchmarks/FreeBench/distray/distray
MultiSource/Benchmarks/McCat/08-main/main
MultiSource/Benchmarks/Olden/voronoi/voronoi
MultiSource/Benchmarks/mafft/pairlocalalign
MultiSource/Benchmarks/tramp3d-v4/tramp3d-v4
SingleSource/Benchmarks/CoyoteBench/almabench
SingleSource/Benchmarks/Misc/matmul_f64_4x4
- The lowering currently falls back to using Altivec instructions far more
than it should. Worse, there are some things that are scalarized through the
stack that shouldn't be.
- A lot of unnecessary copies make it past the optimizers, and this needs to
be fixed.
- Many more regression tests are needed.
Normally, I'd fix these things prior to committing, but there are some
students and other contributors who would like to work this, and so it makes
sense to move this development process upstream where it can be subject to the
regular code-review procedures.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203768 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-13 07:58:58 +00:00
|
|
|
Opc = PPC::XXLOR;
|
2014-03-29 05:29:01 +00:00
|
|
|
else if (PPC::VSFRCRegClass.contains(DestReg, SrcReg))
|
|
|
|
Opc = PPC::XXLORf;
|
2010-07-11 07:31:00 +00:00
|
|
|
else if (PPC::CRBITRCRegClass.contains(DestReg, SrcReg))
|
|
|
|
Opc = PPC::CROR;
|
|
|
|
else
|
|
|
|
llvm_unreachable("Impossible reg-to-reg copy");
|
2007-12-31 06:32:00 +00:00
|
|
|
|
2011-06-28 19:10:37 +00:00
|
|
|
const MCInstrDesc &MCID = get(Opc);
|
|
|
|
if (MCID.getNumOperands() == 3)
|
|
|
|
BuildMI(MBB, I, DL, MCID, DestReg)
|
2010-07-11 07:31:00 +00:00
|
|
|
.addReg(SrcReg).addReg(SrcReg, getKillRegState(KillSrc));
|
|
|
|
else
|
2011-06-28 19:10:37 +00:00
|
|
|
BuildMI(MBB, I, DL, MCID, DestReg).addReg(SrcReg, getKillRegState(KillSrc));
|
2007-12-31 06:32:00 +00:00
|
|
|
}
|
|
|
|
|
2011-12-05 17:55:17 +00:00
|
|
|
// This function returns true if a CR spill is necessary and false otherwise.
|
2008-03-10 22:49:16 +00:00
|
|
|
bool
|
2008-07-07 23:14:23 +00:00
|
|
|
PPCInstrInfo::StoreRegToStackSlot(MachineFunction &MF,
|
|
|
|
unsigned SrcReg, bool isKill,
|
2008-03-10 22:49:16 +00:00
|
|
|
int FrameIdx,
|
|
|
|
const TargetRegisterClass *RC,
|
2013-03-17 04:43:44 +00:00
|
|
|
SmallVectorImpl<MachineInstr*> &NewMIs,
|
2013-03-23 22:06:03 +00:00
|
|
|
bool &NonRI, bool &SpillsVRS) const{
|
2013-03-27 21:21:15 +00:00
|
|
|
// Note: If additional store instructions are added here,
|
|
|
|
// update isStoreToStackSlot.
|
|
|
|
|
2010-04-02 20:16:16 +00:00
|
|
|
DebugLoc DL;
|
2014-01-28 05:32:58 +00:00
|
|
|
if (PPC::GPRCRegClass.hasSubClassEq(RC) ||
|
|
|
|
PPC::GPRC_NOR0RegClass.hasSubClassEq(RC)) {
|
2013-03-23 17:14:27 +00:00
|
|
|
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::STW))
|
|
|
|
.addReg(SrcReg,
|
|
|
|
getKillRegState(isKill)),
|
|
|
|
FrameIdx));
|
2014-01-28 05:32:58 +00:00
|
|
|
} else if (PPC::G8RCRegClass.hasSubClassEq(RC) ||
|
|
|
|
PPC::G8RC_NOX0RegClass.hasSubClassEq(RC)) {
|
2013-03-23 17:14:27 +00:00
|
|
|
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::STD))
|
|
|
|
.addReg(SrcReg,
|
|
|
|
getKillRegState(isKill)),
|
|
|
|
FrameIdx));
|
2012-04-20 06:31:50 +00:00
|
|
|
} else if (PPC::F8RCRegClass.hasSubClassEq(RC)) {
|
2009-02-12 23:08:38 +00:00
|
|
|
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::STFD))
|
2009-05-13 21:33:08 +00:00
|
|
|
.addReg(SrcReg,
|
|
|
|
getKillRegState(isKill)),
|
|
|
|
FrameIdx));
|
2012-04-20 06:31:50 +00:00
|
|
|
} else if (PPC::F4RCRegClass.hasSubClassEq(RC)) {
|
2009-02-12 23:08:38 +00:00
|
|
|
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::STFS))
|
2009-05-13 21:33:08 +00:00
|
|
|
.addReg(SrcReg,
|
|
|
|
getKillRegState(isKill)),
|
|
|
|
FrameIdx));
|
2012-04-20 06:31:50 +00:00
|
|
|
} else if (PPC::CRRCRegClass.hasSubClassEq(RC)) {
|
2013-03-12 14:12:16 +00:00
|
|
|
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::SPILL_CR))
|
|
|
|
.addReg(SrcReg,
|
|
|
|
getKillRegState(isKill)),
|
|
|
|
FrameIdx));
|
|
|
|
return true;
|
2012-04-20 06:31:50 +00:00
|
|
|
} else if (PPC::CRBITRCRegClass.hasSubClassEq(RC)) {
|
Add CR-bit tracking to the PowerPC backend for i1 values
This change enables tracking i1 values in the PowerPC backend using the
condition register bits. These bits can be treated on PowerPC as separate
registers; individual bit operations (and, or, xor, etc.) are supported.
Tracking booleans in CR bits has several advantages:
- Reduction in register pressure (because we no longer need GPRs to store
boolean values).
- Logical operations on booleans can be handled more efficiently; we used to
have to move all results from comparisons into GPRs, perform promoted
logical operations in GPRs, and then move the result back into condition
register bits to be used by conditional branches. This can be very
inefficient, because the throughput of these CR <-> GPR moves have high
latency and low throughput (especially when other associated instructions
are accounted for).
- On the POWER7 and similar cores, we can increase total throughput by using
the CR bits. CR bit operations have a dedicated functional unit.
Most of this is more-or-less mechanical: Adjustments were needed in the
calling-convention code, support was added for spilling/restoring individual
condition-register bits, and conditional branch instruction definitions taking
specific CR bits were added (plus patterns and code for generating bit-level
operations).
This is enabled by default when running at -O2 and higher. For -O0 and -O1,
where the ability to debug is more important, this feature is disabled by
default. Individual CR bits do not have assigned DWARF register numbers,
and storing values in CR bits makes them invisible to the debugger.
It is critical, however, that we don't move i1 values that have been promoted
to larger values (such as those passed as function arguments) into bit
registers only to quickly turn around and move the values back into GPRs (such
as happens when values are returned by functions). A pair of target-specific
DAG combines are added to remove the trunc/extends in:
trunc(binary-ops(binary-ops(zext(x), zext(y)), ...)
and:
zext(binary-ops(binary-ops(trunc(x), trunc(y)), ...)
In short, we only want to use CR bits where some of the i1 values come from
comparisons or are used by conditional branches or selects. To put it another
way, if we can do the entire i1 computation in GPRs, then we probably should
(on the POWER7, the GPR-operation throughput is higher, and for all cores, the
CR <-> GPR moves are expensive).
POWER7 test-suite performance results (from 10 runs in each configuration):
SingleSource/Benchmarks/Misc/mandel-2: 35% speedup
MultiSource/Benchmarks/Prolangs-C++/city/city: 21% speedup
MultiSource/Benchmarks/MiBench/automotive-susan: 23% speedup
SingleSource/Benchmarks/CoyoteBench/huffbench: 13% speedup
SingleSource/Benchmarks/Misc-C++/Large/sphereflake: 13% speedup
SingleSource/Benchmarks/Misc-C++/mandel-text: 10% speedup
SingleSource/Benchmarks/Misc-C++-EH/spirit: 10% slowdown
MultiSource/Applications/lemon/lemon: 8% slowdown
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202451 91177308-0d34-0410-b5e6-96231b3b80d8
2014-02-28 00:27:01 +00:00
|
|
|
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::SPILL_CRBIT))
|
|
|
|
.addReg(SrcReg,
|
|
|
|
getKillRegState(isKill)),
|
|
|
|
FrameIdx));
|
|
|
|
return true;
|
2012-04-20 06:31:50 +00:00
|
|
|
} else if (PPC::VRRCRegClass.hasSubClassEq(RC)) {
|
2013-03-17 04:43:44 +00:00
|
|
|
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::STVX))
|
|
|
|
.addReg(SrcReg,
|
|
|
|
getKillRegState(isKill)),
|
|
|
|
FrameIdx));
|
|
|
|
NonRI = true;
|
[PowerPC] Initial support for the VSX instruction set
VSX is an ISA extension supported on the POWER7 and later cores that enhances
floating-point vector and scalar capabilities. Among other things, this adds
<2 x double> support and generally helps to reduce register pressure.
The interesting part of this ISA feature is the register configuration: there
are 64 new 128-bit vector registers, the 32 of which are super-registers of the
existing 32 scalar floating-point registers, and the second 32 of which overlap
with the 32 Altivec vector registers. This makes things like vector insertion
and extraction tricky: this can be free but only if we force a restriction to
the right register subclass when needed. A new "minipass" PPCVSXCopy takes care
of this (although it could do a more-optimal job of it; see the comment about
unnecessary copies below).
Please note that, currently, VSX is not enabled by default when targeting
anything because it is not yet ready for that. The assembler and disassembler
are fully implemented and tested. However:
- CodeGen support causes miscompiles; test-suite runtime failures:
MultiSource/Benchmarks/FreeBench/distray/distray
MultiSource/Benchmarks/McCat/08-main/main
MultiSource/Benchmarks/Olden/voronoi/voronoi
MultiSource/Benchmarks/mafft/pairlocalalign
MultiSource/Benchmarks/tramp3d-v4/tramp3d-v4
SingleSource/Benchmarks/CoyoteBench/almabench
SingleSource/Benchmarks/Misc/matmul_f64_4x4
- The lowering currently falls back to using Altivec instructions far more
than it should. Worse, there are some things that are scalarized through the
stack that shouldn't be.
- A lot of unnecessary copies make it past the optimizers, and this needs to
be fixed.
- Many more regression tests are needed.
Normally, I'd fix these things prior to committing, but there are some
students and other contributors who would like to work this, and so it makes
sense to move this development process upstream where it can be subject to the
regular code-review procedures.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203768 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-13 07:58:58 +00:00
|
|
|
} else if (PPC::VSRCRegClass.hasSubClassEq(RC)) {
|
|
|
|
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::STXVD2X))
|
|
|
|
.addReg(SrcReg,
|
|
|
|
getKillRegState(isKill)),
|
|
|
|
FrameIdx));
|
|
|
|
NonRI = true;
|
2014-03-29 05:29:01 +00:00
|
|
|
} else if (PPC::VSFRCRegClass.hasSubClassEq(RC)) {
|
|
|
|
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::STXSDX))
|
|
|
|
.addReg(SrcReg,
|
|
|
|
getKillRegState(isKill)),
|
|
|
|
FrameIdx));
|
|
|
|
NonRI = true;
|
2013-03-21 19:03:21 +00:00
|
|
|
} else if (PPC::VRSAVERCRegClass.hasSubClassEq(RC)) {
|
2014-06-12 21:48:52 +00:00
|
|
|
assert(Subtarget.isDarwin() &&
|
2013-03-27 00:02:20 +00:00
|
|
|
"VRSAVE only needs spill/restore on Darwin");
|
2013-03-21 19:03:21 +00:00
|
|
|
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::SPILL_VRSAVE))
|
|
|
|
.addReg(SrcReg,
|
|
|
|
getKillRegState(isKill)),
|
|
|
|
FrameIdx));
|
2013-03-23 22:06:03 +00:00
|
|
|
SpillsVRS = true;
|
2008-01-01 21:11:32 +00:00
|
|
|
} else {
|
2009-07-14 16:55:14 +00:00
|
|
|
llvm_unreachable("Unknown regclass!");
|
2008-01-01 21:11:32 +00:00
|
|
|
}
|
2008-03-03 22:19:16 +00:00
|
|
|
|
|
|
|
return false;
|
2008-01-01 21:11:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
PPCInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
|
2008-03-03 22:19:16 +00:00
|
|
|
MachineBasicBlock::iterator MI,
|
|
|
|
unsigned SrcReg, bool isKill, int FrameIdx,
|
2010-05-06 19:06:44 +00:00
|
|
|
const TargetRegisterClass *RC,
|
|
|
|
const TargetRegisterInfo *TRI) const {
|
2008-07-07 23:14:23 +00:00
|
|
|
MachineFunction &MF = *MBB.getParent();
|
2008-01-01 21:11:32 +00:00
|
|
|
SmallVector<MachineInstr*, 4> NewMIs;
|
2008-03-03 22:19:16 +00:00
|
|
|
|
2013-03-15 05:06:04 +00:00
|
|
|
PPCFunctionInfo *FuncInfo = MF.getInfo<PPCFunctionInfo>();
|
|
|
|
FuncInfo->setHasSpills();
|
|
|
|
|
2013-03-23 22:06:03 +00:00
|
|
|
bool NonRI = false, SpillsVRS = false;
|
|
|
|
if (StoreRegToStackSlot(MF, SrcReg, isKill, FrameIdx, RC, NewMIs,
|
|
|
|
NonRI, SpillsVRS))
|
2008-03-03 22:19:16 +00:00
|
|
|
FuncInfo->setSpillsCR();
|
|
|
|
|
2013-03-23 22:06:03 +00:00
|
|
|
if (SpillsVRS)
|
|
|
|
FuncInfo->setSpillsVRSAVE();
|
|
|
|
|
2013-03-17 04:43:44 +00:00
|
|
|
if (NonRI)
|
|
|
|
FuncInfo->setHasNonRISpills();
|
|
|
|
|
2008-01-01 21:11:32 +00:00
|
|
|
for (unsigned i = 0, e = NewMIs.size(); i != e; ++i)
|
|
|
|
MBB.insert(MI, NewMIs[i]);
|
2010-07-16 18:22:00 +00:00
|
|
|
|
|
|
|
const MachineFrameInfo &MFI = *MF.getFrameInfo();
|
|
|
|
MachineMemOperand *MMO =
|
2011-11-15 07:34:52 +00:00
|
|
|
MF.getMachineMemOperand(MachinePointerInfo::getFixedStack(FrameIdx),
|
2010-09-21 04:39:43 +00:00
|
|
|
MachineMemOperand::MOStore,
|
2010-07-16 18:22:00 +00:00
|
|
|
MFI.getObjectSize(FrameIdx),
|
|
|
|
MFI.getObjectAlignment(FrameIdx));
|
|
|
|
NewMIs.back()->addMemOperand(MF, MMO);
|
2008-01-01 21:11:32 +00:00
|
|
|
}
|
|
|
|
|
2011-12-06 20:55:36 +00:00
|
|
|
bool
|
2009-02-12 00:02:55 +00:00
|
|
|
PPCInstrInfo::LoadRegFromStackSlot(MachineFunction &MF, DebugLoc DL,
|
2008-07-07 23:14:23 +00:00
|
|
|
unsigned DestReg, int FrameIdx,
|
2008-03-10 22:49:16 +00:00
|
|
|
const TargetRegisterClass *RC,
|
2013-03-17 04:43:44 +00:00
|
|
|
SmallVectorImpl<MachineInstr*> &NewMIs,
|
2013-03-23 22:06:03 +00:00
|
|
|
bool &NonRI, bool &SpillsVRS) const{
|
2013-03-27 21:21:15 +00:00
|
|
|
// Note: If additional load instructions are added here,
|
|
|
|
// update isLoadFromStackSlot.
|
|
|
|
|
2014-01-28 05:32:58 +00:00
|
|
|
if (PPC::GPRCRegClass.hasSubClassEq(RC) ||
|
|
|
|
PPC::GPRC_NOR0RegClass.hasSubClassEq(RC)) {
|
2013-03-27 19:10:40 +00:00
|
|
|
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::LWZ),
|
|
|
|
DestReg), FrameIdx));
|
2014-01-28 05:32:58 +00:00
|
|
|
} else if (PPC::G8RCRegClass.hasSubClassEq(RC) ||
|
|
|
|
PPC::G8RC_NOX0RegClass.hasSubClassEq(RC)) {
|
2013-03-27 19:10:40 +00:00
|
|
|
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::LD), DestReg),
|
|
|
|
FrameIdx));
|
2012-04-20 06:31:50 +00:00
|
|
|
} else if (PPC::F8RCRegClass.hasSubClassEq(RC)) {
|
2009-02-12 00:02:55 +00:00
|
|
|
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::LFD), DestReg),
|
2008-01-01 21:11:32 +00:00
|
|
|
FrameIdx));
|
2012-04-20 06:31:50 +00:00
|
|
|
} else if (PPC::F4RCRegClass.hasSubClassEq(RC)) {
|
2009-02-12 00:02:55 +00:00
|
|
|
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::LFS), DestReg),
|
2008-01-01 21:11:32 +00:00
|
|
|
FrameIdx));
|
2012-04-20 06:31:50 +00:00
|
|
|
} else if (PPC::CRRCRegClass.hasSubClassEq(RC)) {
|
2013-03-12 14:12:16 +00:00
|
|
|
NewMIs.push_back(addFrameReference(BuildMI(MF, DL,
|
|
|
|
get(PPC::RESTORE_CR), DestReg),
|
|
|
|
FrameIdx));
|
|
|
|
return true;
|
2012-04-20 06:31:50 +00:00
|
|
|
} else if (PPC::CRBITRCRegClass.hasSubClassEq(RC)) {
|
Add CR-bit tracking to the PowerPC backend for i1 values
This change enables tracking i1 values in the PowerPC backend using the
condition register bits. These bits can be treated on PowerPC as separate
registers; individual bit operations (and, or, xor, etc.) are supported.
Tracking booleans in CR bits has several advantages:
- Reduction in register pressure (because we no longer need GPRs to store
boolean values).
- Logical operations on booleans can be handled more efficiently; we used to
have to move all results from comparisons into GPRs, perform promoted
logical operations in GPRs, and then move the result back into condition
register bits to be used by conditional branches. This can be very
inefficient, because the throughput of these CR <-> GPR moves have high
latency and low throughput (especially when other associated instructions
are accounted for).
- On the POWER7 and similar cores, we can increase total throughput by using
the CR bits. CR bit operations have a dedicated functional unit.
Most of this is more-or-less mechanical: Adjustments were needed in the
calling-convention code, support was added for spilling/restoring individual
condition-register bits, and conditional branch instruction definitions taking
specific CR bits were added (plus patterns and code for generating bit-level
operations).
This is enabled by default when running at -O2 and higher. For -O0 and -O1,
where the ability to debug is more important, this feature is disabled by
default. Individual CR bits do not have assigned DWARF register numbers,
and storing values in CR bits makes them invisible to the debugger.
It is critical, however, that we don't move i1 values that have been promoted
to larger values (such as those passed as function arguments) into bit
registers only to quickly turn around and move the values back into GPRs (such
as happens when values are returned by functions). A pair of target-specific
DAG combines are added to remove the trunc/extends in:
trunc(binary-ops(binary-ops(zext(x), zext(y)), ...)
and:
zext(binary-ops(binary-ops(trunc(x), trunc(y)), ...)
In short, we only want to use CR bits where some of the i1 values come from
comparisons or are used by conditional branches or selects. To put it another
way, if we can do the entire i1 computation in GPRs, then we probably should
(on the POWER7, the GPR-operation throughput is higher, and for all cores, the
CR <-> GPR moves are expensive).
POWER7 test-suite performance results (from 10 runs in each configuration):
SingleSource/Benchmarks/Misc/mandel-2: 35% speedup
MultiSource/Benchmarks/Prolangs-C++/city/city: 21% speedup
MultiSource/Benchmarks/MiBench/automotive-susan: 23% speedup
SingleSource/Benchmarks/CoyoteBench/huffbench: 13% speedup
SingleSource/Benchmarks/Misc-C++/Large/sphereflake: 13% speedup
SingleSource/Benchmarks/Misc-C++/mandel-text: 10% speedup
SingleSource/Benchmarks/Misc-C++-EH/spirit: 10% slowdown
MultiSource/Applications/lemon/lemon: 8% slowdown
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202451 91177308-0d34-0410-b5e6-96231b3b80d8
2014-02-28 00:27:01 +00:00
|
|
|
NewMIs.push_back(addFrameReference(BuildMI(MF, DL,
|
|
|
|
get(PPC::RESTORE_CRBIT), DestReg),
|
|
|
|
FrameIdx));
|
|
|
|
return true;
|
2012-04-20 06:31:50 +00:00
|
|
|
} else if (PPC::VRRCRegClass.hasSubClassEq(RC)) {
|
2013-03-17 04:43:44 +00:00
|
|
|
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::LVX), DestReg),
|
|
|
|
FrameIdx));
|
|
|
|
NonRI = true;
|
[PowerPC] Initial support for the VSX instruction set
VSX is an ISA extension supported on the POWER7 and later cores that enhances
floating-point vector and scalar capabilities. Among other things, this adds
<2 x double> support and generally helps to reduce register pressure.
The interesting part of this ISA feature is the register configuration: there
are 64 new 128-bit vector registers, the 32 of which are super-registers of the
existing 32 scalar floating-point registers, and the second 32 of which overlap
with the 32 Altivec vector registers. This makes things like vector insertion
and extraction tricky: this can be free but only if we force a restriction to
the right register subclass when needed. A new "minipass" PPCVSXCopy takes care
of this (although it could do a more-optimal job of it; see the comment about
unnecessary copies below).
Please note that, currently, VSX is not enabled by default when targeting
anything because it is not yet ready for that. The assembler and disassembler
are fully implemented and tested. However:
- CodeGen support causes miscompiles; test-suite runtime failures:
MultiSource/Benchmarks/FreeBench/distray/distray
MultiSource/Benchmarks/McCat/08-main/main
MultiSource/Benchmarks/Olden/voronoi/voronoi
MultiSource/Benchmarks/mafft/pairlocalalign
MultiSource/Benchmarks/tramp3d-v4/tramp3d-v4
SingleSource/Benchmarks/CoyoteBench/almabench
SingleSource/Benchmarks/Misc/matmul_f64_4x4
- The lowering currently falls back to using Altivec instructions far more
than it should. Worse, there are some things that are scalarized through the
stack that shouldn't be.
- A lot of unnecessary copies make it past the optimizers, and this needs to
be fixed.
- Many more regression tests are needed.
Normally, I'd fix these things prior to committing, but there are some
students and other contributors who would like to work this, and so it makes
sense to move this development process upstream where it can be subject to the
regular code-review procedures.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203768 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-13 07:58:58 +00:00
|
|
|
} else if (PPC::VSRCRegClass.hasSubClassEq(RC)) {
|
|
|
|
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::LXVD2X), DestReg),
|
|
|
|
FrameIdx));
|
|
|
|
NonRI = true;
|
2014-03-29 05:29:01 +00:00
|
|
|
} else if (PPC::VSFRCRegClass.hasSubClassEq(RC)) {
|
|
|
|
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::LXSDX), DestReg),
|
|
|
|
FrameIdx));
|
|
|
|
NonRI = true;
|
2013-03-21 19:03:21 +00:00
|
|
|
} else if (PPC::VRSAVERCRegClass.hasSubClassEq(RC)) {
|
2014-06-12 21:48:52 +00:00
|
|
|
assert(Subtarget.isDarwin() &&
|
2013-03-27 00:02:20 +00:00
|
|
|
"VRSAVE only needs spill/restore on Darwin");
|
2013-03-21 19:03:21 +00:00
|
|
|
NewMIs.push_back(addFrameReference(BuildMI(MF, DL,
|
|
|
|
get(PPC::RESTORE_VRSAVE),
|
|
|
|
DestReg),
|
|
|
|
FrameIdx));
|
2013-03-23 22:06:03 +00:00
|
|
|
SpillsVRS = true;
|
2008-01-01 21:11:32 +00:00
|
|
|
} else {
|
2009-07-14 16:55:14 +00:00
|
|
|
llvm_unreachable("Unknown regclass!");
|
2008-01-01 21:11:32 +00:00
|
|
|
}
|
2011-12-06 20:55:36 +00:00
|
|
|
|
|
|
|
return false;
|
2008-01-01 21:11:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
PPCInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
|
2008-03-03 22:19:16 +00:00
|
|
|
MachineBasicBlock::iterator MI,
|
|
|
|
unsigned DestReg, int FrameIdx,
|
2010-05-06 19:06:44 +00:00
|
|
|
const TargetRegisterClass *RC,
|
|
|
|
const TargetRegisterInfo *TRI) const {
|
2008-07-07 23:14:23 +00:00
|
|
|
MachineFunction &MF = *MBB.getParent();
|
2008-01-01 21:11:32 +00:00
|
|
|
SmallVector<MachineInstr*, 4> NewMIs;
|
2010-04-02 20:16:16 +00:00
|
|
|
DebugLoc DL;
|
2009-02-12 00:02:55 +00:00
|
|
|
if (MI != MBB.end()) DL = MI->getDebugLoc();
|
2013-03-17 04:43:44 +00:00
|
|
|
|
|
|
|
PPCFunctionInfo *FuncInfo = MF.getInfo<PPCFunctionInfo>();
|
|
|
|
FuncInfo->setHasSpills();
|
|
|
|
|
2013-03-23 22:06:03 +00:00
|
|
|
bool NonRI = false, SpillsVRS = false;
|
|
|
|
if (LoadRegFromStackSlot(MF, DL, DestReg, FrameIdx, RC, NewMIs,
|
|
|
|
NonRI, SpillsVRS))
|
2011-12-06 20:55:36 +00:00
|
|
|
FuncInfo->setSpillsCR();
|
2013-03-17 04:43:44 +00:00
|
|
|
|
2013-03-23 22:06:03 +00:00
|
|
|
if (SpillsVRS)
|
|
|
|
FuncInfo->setSpillsVRSAVE();
|
|
|
|
|
2013-03-17 04:43:44 +00:00
|
|
|
if (NonRI)
|
|
|
|
FuncInfo->setHasNonRISpills();
|
|
|
|
|
2008-01-01 21:11:32 +00:00
|
|
|
for (unsigned i = 0, e = NewMIs.size(); i != e; ++i)
|
|
|
|
MBB.insert(MI, NewMIs[i]);
|
2010-07-16 18:22:00 +00:00
|
|
|
|
|
|
|
const MachineFrameInfo &MFI = *MF.getFrameInfo();
|
|
|
|
MachineMemOperand *MMO =
|
2011-11-15 07:34:52 +00:00
|
|
|
MF.getMachineMemOperand(MachinePointerInfo::getFixedStack(FrameIdx),
|
2010-09-21 04:39:43 +00:00
|
|
|
MachineMemOperand::MOLoad,
|
2010-07-16 18:22:00 +00:00
|
|
|
MFI.getObjectSize(FrameIdx),
|
|
|
|
MFI.getObjectAlignment(FrameIdx));
|
|
|
|
NewMIs.back()->addMemOperand(MF, MMO);
|
2008-01-01 21:11:32 +00:00
|
|
|
}
|
|
|
|
|
2006-10-13 21:21:17 +00:00
|
|
|
bool PPCInstrInfo::
|
2008-08-14 22:49:33 +00:00
|
|
|
ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
|
2006-10-21 06:03:11 +00:00
|
|
|
assert(Cond.size() == 2 && "Invalid PPC branch opcode!");
|
2012-06-08 15:38:21 +00:00
|
|
|
if (Cond[1].getReg() == PPC::CTR8 || Cond[1].getReg() == PPC::CTR)
|
|
|
|
Cond[0].setImm(Cond[0].getImm() == 0 ? 1 : 0);
|
|
|
|
else
|
|
|
|
// Leave the CR# the same, but invert the condition.
|
|
|
|
Cond[0].setImm(PPC::InvertPredicate((PPC::Predicate)Cond[0].getImm()));
|
2006-10-21 06:03:11 +00:00
|
|
|
return false;
|
2006-10-13 21:21:17 +00:00
|
|
|
}
|
2008-04-16 20:10:13 +00:00
|
|
|
|
2013-04-06 19:30:30 +00:00
|
|
|
bool PPCInstrInfo::FoldImmediate(MachineInstr *UseMI, MachineInstr *DefMI,
|
|
|
|
unsigned Reg, MachineRegisterInfo *MRI) const {
|
|
|
|
// For some instructions, it is legal to fold ZERO into the RA register field.
|
|
|
|
// A zero immediate should always be loaded with a single li.
|
|
|
|
unsigned DefOpc = DefMI->getOpcode();
|
|
|
|
if (DefOpc != PPC::LI && DefOpc != PPC::LI8)
|
|
|
|
return false;
|
|
|
|
if (!DefMI->getOperand(1).isImm())
|
|
|
|
return false;
|
|
|
|
if (DefMI->getOperand(1).getImm() != 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Note that we cannot here invert the arguments of an isel in order to fold
|
|
|
|
// a ZERO into what is presented as the second argument. All we have here
|
|
|
|
// is the condition bit, and that might come from a CR-logical bit operation.
|
|
|
|
|
|
|
|
const MCInstrDesc &UseMCID = UseMI->getDesc();
|
|
|
|
|
|
|
|
// Only fold into real machine instructions.
|
|
|
|
if (UseMCID.isPseudo())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
unsigned UseIdx;
|
|
|
|
for (UseIdx = 0; UseIdx < UseMI->getNumOperands(); ++UseIdx)
|
|
|
|
if (UseMI->getOperand(UseIdx).isReg() &&
|
|
|
|
UseMI->getOperand(UseIdx).getReg() == Reg)
|
|
|
|
break;
|
|
|
|
|
|
|
|
assert(UseIdx < UseMI->getNumOperands() && "Cannot find Reg in UseMI");
|
|
|
|
assert(UseIdx < UseMCID.getNumOperands() && "No operand description for Reg");
|
|
|
|
|
|
|
|
const MCOperandInfo *UseInfo = &UseMCID.OpInfo[UseIdx];
|
|
|
|
|
|
|
|
// We can fold the zero if this register requires a GPRC_NOR0/G8RC_NOX0
|
|
|
|
// register (which might also be specified as a pointer class kind).
|
|
|
|
if (UseInfo->isLookupPtrRegClass()) {
|
|
|
|
if (UseInfo->RegClass /* Kind */ != 1)
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
if (UseInfo->RegClass != PPC::GPRC_NOR0RegClassID &&
|
|
|
|
UseInfo->RegClass != PPC::G8RC_NOX0RegClassID)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make sure this is not tied to an output register (or otherwise
|
|
|
|
// constrained). This is true for ST?UX registers, for example, which
|
|
|
|
// are tied to their output registers.
|
|
|
|
if (UseInfo->Constraints != 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
unsigned ZeroReg;
|
|
|
|
if (UseInfo->isLookupPtrRegClass()) {
|
2014-06-12 21:48:52 +00:00
|
|
|
bool isPPC64 = Subtarget.isPPC64();
|
2013-04-06 19:30:30 +00:00
|
|
|
ZeroReg = isPPC64 ? PPC::ZERO8 : PPC::ZERO;
|
|
|
|
} else {
|
|
|
|
ZeroReg = UseInfo->RegClass == PPC::G8RC_NOX0RegClassID ?
|
|
|
|
PPC::ZERO8 : PPC::ZERO;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DeleteDef = MRI->hasOneNonDBGUse(Reg);
|
|
|
|
UseMI->getOperand(UseIdx).setReg(ZeroReg);
|
|
|
|
|
|
|
|
if (DeleteDef)
|
|
|
|
DefMI->eraseFromParent();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-04-10 18:30:16 +00:00
|
|
|
static bool MBBDefinesCTR(MachineBasicBlock &MBB) {
|
|
|
|
for (MachineBasicBlock::iterator I = MBB.begin(), IE = MBB.end();
|
|
|
|
I != IE; ++I)
|
|
|
|
if (I->definesRegister(PPC::CTR) || I->definesRegister(PPC::CTR8))
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We should make sure that, if we're going to predicate both sides of a
|
|
|
|
// condition (a diamond), that both sides don't define the counter register. We
|
|
|
|
// can predicate counter-decrement-based branches, but while that predicates
|
|
|
|
// the branching, it does not predicate the counter decrement. If we tried to
|
|
|
|
// merge the triangle into one predicated block, we'd decrement the counter
|
|
|
|
// twice.
|
|
|
|
bool PPCInstrInfo::isProfitableToIfCvt(MachineBasicBlock &TMBB,
|
|
|
|
unsigned NumT, unsigned ExtraT,
|
|
|
|
MachineBasicBlock &FMBB,
|
|
|
|
unsigned NumF, unsigned ExtraF,
|
|
|
|
const BranchProbability &Probability) const {
|
|
|
|
return !(MBBDefinesCTR(TMBB) && MBBDefinesCTR(FMBB));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-04-09 22:58:37 +00:00
|
|
|
bool PPCInstrInfo::isPredicated(const MachineInstr *MI) const {
|
2013-04-11 01:23:34 +00:00
|
|
|
// The predicated branches are identified by their type, not really by the
|
|
|
|
// explicit presence of a predicate. Furthermore, some of them can be
|
|
|
|
// predicated more than once. Because if conversion won't try to predicate
|
|
|
|
// any instruction which already claims to be predicated (by returning true
|
|
|
|
// here), always return false. In doing so, we let isPredicable() be the
|
|
|
|
// final word on whether not the instruction can be (further) predicated.
|
|
|
|
|
|
|
|
return false;
|
2013-04-09 22:58:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool PPCInstrInfo::isUnpredicatedTerminator(const MachineInstr *MI) const {
|
|
|
|
if (!MI->isTerminator())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Conditional branch is a special case.
|
|
|
|
if (MI->isBranch() && !MI->isBarrier())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return !isPredicated(MI);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool PPCInstrInfo::PredicateInstruction(
|
|
|
|
MachineInstr *MI,
|
|
|
|
const SmallVectorImpl<MachineOperand> &Pred) const {
|
|
|
|
unsigned OpC = MI->getOpcode();
|
|
|
|
if (OpC == PPC::BLR) {
|
|
|
|
if (Pred[1].getReg() == PPC::CTR8 || Pred[1].getReg() == PPC::CTR) {
|
2014-06-12 21:48:52 +00:00
|
|
|
bool isPPC64 = Subtarget.isPPC64();
|
2013-04-09 22:58:37 +00:00
|
|
|
MI->setDesc(get(Pred[0].getImm() ?
|
|
|
|
(isPPC64 ? PPC::BDNZLR8 : PPC::BDNZLR) :
|
|
|
|
(isPPC64 ? PPC::BDZLR8 : PPC::BDZLR)));
|
Add CR-bit tracking to the PowerPC backend for i1 values
This change enables tracking i1 values in the PowerPC backend using the
condition register bits. These bits can be treated on PowerPC as separate
registers; individual bit operations (and, or, xor, etc.) are supported.
Tracking booleans in CR bits has several advantages:
- Reduction in register pressure (because we no longer need GPRs to store
boolean values).
- Logical operations on booleans can be handled more efficiently; we used to
have to move all results from comparisons into GPRs, perform promoted
logical operations in GPRs, and then move the result back into condition
register bits to be used by conditional branches. This can be very
inefficient, because the throughput of these CR <-> GPR moves have high
latency and low throughput (especially when other associated instructions
are accounted for).
- On the POWER7 and similar cores, we can increase total throughput by using
the CR bits. CR bit operations have a dedicated functional unit.
Most of this is more-or-less mechanical: Adjustments were needed in the
calling-convention code, support was added for spilling/restoring individual
condition-register bits, and conditional branch instruction definitions taking
specific CR bits were added (plus patterns and code for generating bit-level
operations).
This is enabled by default when running at -O2 and higher. For -O0 and -O1,
where the ability to debug is more important, this feature is disabled by
default. Individual CR bits do not have assigned DWARF register numbers,
and storing values in CR bits makes them invisible to the debugger.
It is critical, however, that we don't move i1 values that have been promoted
to larger values (such as those passed as function arguments) into bit
registers only to quickly turn around and move the values back into GPRs (such
as happens when values are returned by functions). A pair of target-specific
DAG combines are added to remove the trunc/extends in:
trunc(binary-ops(binary-ops(zext(x), zext(y)), ...)
and:
zext(binary-ops(binary-ops(trunc(x), trunc(y)), ...)
In short, we only want to use CR bits where some of the i1 values come from
comparisons or are used by conditional branches or selects. To put it another
way, if we can do the entire i1 computation in GPRs, then we probably should
(on the POWER7, the GPR-operation throughput is higher, and for all cores, the
CR <-> GPR moves are expensive).
POWER7 test-suite performance results (from 10 runs in each configuration):
SingleSource/Benchmarks/Misc/mandel-2: 35% speedup
MultiSource/Benchmarks/Prolangs-C++/city/city: 21% speedup
MultiSource/Benchmarks/MiBench/automotive-susan: 23% speedup
SingleSource/Benchmarks/CoyoteBench/huffbench: 13% speedup
SingleSource/Benchmarks/Misc-C++/Large/sphereflake: 13% speedup
SingleSource/Benchmarks/Misc-C++/mandel-text: 10% speedup
SingleSource/Benchmarks/Misc-C++-EH/spirit: 10% slowdown
MultiSource/Applications/lemon/lemon: 8% slowdown
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202451 91177308-0d34-0410-b5e6-96231b3b80d8
2014-02-28 00:27:01 +00:00
|
|
|
} else if (Pred[0].getImm() == PPC::PRED_BIT_SET) {
|
2013-04-09 22:58:37 +00:00
|
|
|
MI->setDesc(get(PPC::BCLR));
|
Add CR-bit tracking to the PowerPC backend for i1 values
This change enables tracking i1 values in the PowerPC backend using the
condition register bits. These bits can be treated on PowerPC as separate
registers; individual bit operations (and, or, xor, etc.) are supported.
Tracking booleans in CR bits has several advantages:
- Reduction in register pressure (because we no longer need GPRs to store
boolean values).
- Logical operations on booleans can be handled more efficiently; we used to
have to move all results from comparisons into GPRs, perform promoted
logical operations in GPRs, and then move the result back into condition
register bits to be used by conditional branches. This can be very
inefficient, because the throughput of these CR <-> GPR moves have high
latency and low throughput (especially when other associated instructions
are accounted for).
- On the POWER7 and similar cores, we can increase total throughput by using
the CR bits. CR bit operations have a dedicated functional unit.
Most of this is more-or-less mechanical: Adjustments were needed in the
calling-convention code, support was added for spilling/restoring individual
condition-register bits, and conditional branch instruction definitions taking
specific CR bits were added (plus patterns and code for generating bit-level
operations).
This is enabled by default when running at -O2 and higher. For -O0 and -O1,
where the ability to debug is more important, this feature is disabled by
default. Individual CR bits do not have assigned DWARF register numbers,
and storing values in CR bits makes them invisible to the debugger.
It is critical, however, that we don't move i1 values that have been promoted
to larger values (such as those passed as function arguments) into bit
registers only to quickly turn around and move the values back into GPRs (such
as happens when values are returned by functions). A pair of target-specific
DAG combines are added to remove the trunc/extends in:
trunc(binary-ops(binary-ops(zext(x), zext(y)), ...)
and:
zext(binary-ops(binary-ops(trunc(x), trunc(y)), ...)
In short, we only want to use CR bits where some of the i1 values come from
comparisons or are used by conditional branches or selects. To put it another
way, if we can do the entire i1 computation in GPRs, then we probably should
(on the POWER7, the GPR-operation throughput is higher, and for all cores, the
CR <-> GPR moves are expensive).
POWER7 test-suite performance results (from 10 runs in each configuration):
SingleSource/Benchmarks/Misc/mandel-2: 35% speedup
MultiSource/Benchmarks/Prolangs-C++/city/city: 21% speedup
MultiSource/Benchmarks/MiBench/automotive-susan: 23% speedup
SingleSource/Benchmarks/CoyoteBench/huffbench: 13% speedup
SingleSource/Benchmarks/Misc-C++/Large/sphereflake: 13% speedup
SingleSource/Benchmarks/Misc-C++/mandel-text: 10% speedup
SingleSource/Benchmarks/Misc-C++-EH/spirit: 10% slowdown
MultiSource/Applications/lemon/lemon: 8% slowdown
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202451 91177308-0d34-0410-b5e6-96231b3b80d8
2014-02-28 00:27:01 +00:00
|
|
|
MachineInstrBuilder(*MI->getParent()->getParent(), MI)
|
|
|
|
.addReg(Pred[1].getReg());
|
|
|
|
} else if (Pred[0].getImm() == PPC::PRED_BIT_UNSET) {
|
|
|
|
MI->setDesc(get(PPC::BCLRn));
|
|
|
|
MachineInstrBuilder(*MI->getParent()->getParent(), MI)
|
|
|
|
.addReg(Pred[1].getReg());
|
|
|
|
} else {
|
|
|
|
MI->setDesc(get(PPC::BCCLR));
|
2013-04-09 22:58:37 +00:00
|
|
|
MachineInstrBuilder(*MI->getParent()->getParent(), MI)
|
|
|
|
.addImm(Pred[0].getImm())
|
|
|
|
.addReg(Pred[1].getReg());
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
} else if (OpC == PPC::B) {
|
|
|
|
if (Pred[1].getReg() == PPC::CTR8 || Pred[1].getReg() == PPC::CTR) {
|
2014-06-12 21:48:52 +00:00
|
|
|
bool isPPC64 = Subtarget.isPPC64();
|
2013-04-09 22:58:37 +00:00
|
|
|
MI->setDesc(get(Pred[0].getImm() ?
|
|
|
|
(isPPC64 ? PPC::BDNZ8 : PPC::BDNZ) :
|
|
|
|
(isPPC64 ? PPC::BDZ8 : PPC::BDZ)));
|
Add CR-bit tracking to the PowerPC backend for i1 values
This change enables tracking i1 values in the PowerPC backend using the
condition register bits. These bits can be treated on PowerPC as separate
registers; individual bit operations (and, or, xor, etc.) are supported.
Tracking booleans in CR bits has several advantages:
- Reduction in register pressure (because we no longer need GPRs to store
boolean values).
- Logical operations on booleans can be handled more efficiently; we used to
have to move all results from comparisons into GPRs, perform promoted
logical operations in GPRs, and then move the result back into condition
register bits to be used by conditional branches. This can be very
inefficient, because the throughput of these CR <-> GPR moves have high
latency and low throughput (especially when other associated instructions
are accounted for).
- On the POWER7 and similar cores, we can increase total throughput by using
the CR bits. CR bit operations have a dedicated functional unit.
Most of this is more-or-less mechanical: Adjustments were needed in the
calling-convention code, support was added for spilling/restoring individual
condition-register bits, and conditional branch instruction definitions taking
specific CR bits were added (plus patterns and code for generating bit-level
operations).
This is enabled by default when running at -O2 and higher. For -O0 and -O1,
where the ability to debug is more important, this feature is disabled by
default. Individual CR bits do not have assigned DWARF register numbers,
and storing values in CR bits makes them invisible to the debugger.
It is critical, however, that we don't move i1 values that have been promoted
to larger values (such as those passed as function arguments) into bit
registers only to quickly turn around and move the values back into GPRs (such
as happens when values are returned by functions). A pair of target-specific
DAG combines are added to remove the trunc/extends in:
trunc(binary-ops(binary-ops(zext(x), zext(y)), ...)
and:
zext(binary-ops(binary-ops(trunc(x), trunc(y)), ...)
In short, we only want to use CR bits where some of the i1 values come from
comparisons or are used by conditional branches or selects. To put it another
way, if we can do the entire i1 computation in GPRs, then we probably should
(on the POWER7, the GPR-operation throughput is higher, and for all cores, the
CR <-> GPR moves are expensive).
POWER7 test-suite performance results (from 10 runs in each configuration):
SingleSource/Benchmarks/Misc/mandel-2: 35% speedup
MultiSource/Benchmarks/Prolangs-C++/city/city: 21% speedup
MultiSource/Benchmarks/MiBench/automotive-susan: 23% speedup
SingleSource/Benchmarks/CoyoteBench/huffbench: 13% speedup
SingleSource/Benchmarks/Misc-C++/Large/sphereflake: 13% speedup
SingleSource/Benchmarks/Misc-C++/mandel-text: 10% speedup
SingleSource/Benchmarks/Misc-C++-EH/spirit: 10% slowdown
MultiSource/Applications/lemon/lemon: 8% slowdown
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202451 91177308-0d34-0410-b5e6-96231b3b80d8
2014-02-28 00:27:01 +00:00
|
|
|
} else if (Pred[0].getImm() == PPC::PRED_BIT_SET) {
|
|
|
|
MachineBasicBlock *MBB = MI->getOperand(0).getMBB();
|
|
|
|
MI->RemoveOperand(0);
|
|
|
|
|
|
|
|
MI->setDesc(get(PPC::BC));
|
|
|
|
MachineInstrBuilder(*MI->getParent()->getParent(), MI)
|
|
|
|
.addReg(Pred[1].getReg())
|
|
|
|
.addMBB(MBB);
|
|
|
|
} else if (Pred[0].getImm() == PPC::PRED_BIT_UNSET) {
|
|
|
|
MachineBasicBlock *MBB = MI->getOperand(0).getMBB();
|
|
|
|
MI->RemoveOperand(0);
|
|
|
|
|
|
|
|
MI->setDesc(get(PPC::BCn));
|
|
|
|
MachineInstrBuilder(*MI->getParent()->getParent(), MI)
|
|
|
|
.addReg(Pred[1].getReg())
|
|
|
|
.addMBB(MBB);
|
2013-04-09 22:58:37 +00:00
|
|
|
} else {
|
|
|
|
MachineBasicBlock *MBB = MI->getOperand(0).getMBB();
|
|
|
|
MI->RemoveOperand(0);
|
|
|
|
|
|
|
|
MI->setDesc(get(PPC::BCC));
|
|
|
|
MachineInstrBuilder(*MI->getParent()->getParent(), MI)
|
|
|
|
.addImm(Pred[0].getImm())
|
|
|
|
.addReg(Pred[1].getReg())
|
|
|
|
.addMBB(MBB);
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
PPC: Prep for if conversion of bctr[l]
This adds in-principle support for if-converting the bctr[l] instructions.
These instructions are used for indirect branching. It seems, however, that the
current if converter will never actually predicate these. To do so, it would
need the ability to hoist a few setup insts. out of the conditionally-executed
block. For example, code like this:
void foo(int a, int (*bar)()) { if (a != 0) bar(); }
becomes:
...
beq 0, .LBB0_2
std 2, 40(1)
mr 12, 4
ld 3, 0(4)
ld 11, 16(4)
ld 2, 8(4)
mtctr 3
bctrl
ld 2, 40(1)
.LBB0_2:
...
and it would be safe to do all of this unconditionally with a predicated
beqctrl instruction.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179156 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-10 06:42:34 +00:00
|
|
|
} else if (OpC == PPC::BCTR || OpC == PPC::BCTR8 ||
|
|
|
|
OpC == PPC::BCTRL || OpC == PPC::BCTRL8) {
|
|
|
|
if (Pred[1].getReg() == PPC::CTR8 || Pred[1].getReg() == PPC::CTR)
|
|
|
|
llvm_unreachable("Cannot predicate bctr[l] on the ctr register");
|
|
|
|
|
|
|
|
bool setLR = OpC == PPC::BCTRL || OpC == PPC::BCTRL8;
|
2014-06-12 21:48:52 +00:00
|
|
|
bool isPPC64 = Subtarget.isPPC64();
|
Add CR-bit tracking to the PowerPC backend for i1 values
This change enables tracking i1 values in the PowerPC backend using the
condition register bits. These bits can be treated on PowerPC as separate
registers; individual bit operations (and, or, xor, etc.) are supported.
Tracking booleans in CR bits has several advantages:
- Reduction in register pressure (because we no longer need GPRs to store
boolean values).
- Logical operations on booleans can be handled more efficiently; we used to
have to move all results from comparisons into GPRs, perform promoted
logical operations in GPRs, and then move the result back into condition
register bits to be used by conditional branches. This can be very
inefficient, because the throughput of these CR <-> GPR moves have high
latency and low throughput (especially when other associated instructions
are accounted for).
- On the POWER7 and similar cores, we can increase total throughput by using
the CR bits. CR bit operations have a dedicated functional unit.
Most of this is more-or-less mechanical: Adjustments were needed in the
calling-convention code, support was added for spilling/restoring individual
condition-register bits, and conditional branch instruction definitions taking
specific CR bits were added (plus patterns and code for generating bit-level
operations).
This is enabled by default when running at -O2 and higher. For -O0 and -O1,
where the ability to debug is more important, this feature is disabled by
default. Individual CR bits do not have assigned DWARF register numbers,
and storing values in CR bits makes them invisible to the debugger.
It is critical, however, that we don't move i1 values that have been promoted
to larger values (such as those passed as function arguments) into bit
registers only to quickly turn around and move the values back into GPRs (such
as happens when values are returned by functions). A pair of target-specific
DAG combines are added to remove the trunc/extends in:
trunc(binary-ops(binary-ops(zext(x), zext(y)), ...)
and:
zext(binary-ops(binary-ops(trunc(x), trunc(y)), ...)
In short, we only want to use CR bits where some of the i1 values come from
comparisons or are used by conditional branches or selects. To put it another
way, if we can do the entire i1 computation in GPRs, then we probably should
(on the POWER7, the GPR-operation throughput is higher, and for all cores, the
CR <-> GPR moves are expensive).
POWER7 test-suite performance results (from 10 runs in each configuration):
SingleSource/Benchmarks/Misc/mandel-2: 35% speedup
MultiSource/Benchmarks/Prolangs-C++/city/city: 21% speedup
MultiSource/Benchmarks/MiBench/automotive-susan: 23% speedup
SingleSource/Benchmarks/CoyoteBench/huffbench: 13% speedup
SingleSource/Benchmarks/Misc-C++/Large/sphereflake: 13% speedup
SingleSource/Benchmarks/Misc-C++/mandel-text: 10% speedup
SingleSource/Benchmarks/Misc-C++-EH/spirit: 10% slowdown
MultiSource/Applications/lemon/lemon: 8% slowdown
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202451 91177308-0d34-0410-b5e6-96231b3b80d8
2014-02-28 00:27:01 +00:00
|
|
|
|
|
|
|
if (Pred[0].getImm() == PPC::PRED_BIT_SET) {
|
|
|
|
MI->setDesc(get(isPPC64 ? (setLR ? PPC::BCCTRL8 : PPC::BCCTR8) :
|
|
|
|
(setLR ? PPC::BCCTRL : PPC::BCCTR)));
|
|
|
|
MachineInstrBuilder(*MI->getParent()->getParent(), MI)
|
|
|
|
.addReg(Pred[1].getReg());
|
|
|
|
return true;
|
|
|
|
} else if (Pred[0].getImm() == PPC::PRED_BIT_UNSET) {
|
|
|
|
MI->setDesc(get(isPPC64 ? (setLR ? PPC::BCCTRL8n : PPC::BCCTR8n) :
|
|
|
|
(setLR ? PPC::BCCTRLn : PPC::BCCTRn)));
|
|
|
|
MachineInstrBuilder(*MI->getParent()->getParent(), MI)
|
|
|
|
.addReg(Pred[1].getReg());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
MI->setDesc(get(isPPC64 ? (setLR ? PPC::BCCCTRL8 : PPC::BCCCTR8) :
|
|
|
|
(setLR ? PPC::BCCCTRL : PPC::BCCCTR)));
|
PPC: Prep for if conversion of bctr[l]
This adds in-principle support for if-converting the bctr[l] instructions.
These instructions are used for indirect branching. It seems, however, that the
current if converter will never actually predicate these. To do so, it would
need the ability to hoist a few setup insts. out of the conditionally-executed
block. For example, code like this:
void foo(int a, int (*bar)()) { if (a != 0) bar(); }
becomes:
...
beq 0, .LBB0_2
std 2, 40(1)
mr 12, 4
ld 3, 0(4)
ld 11, 16(4)
ld 2, 8(4)
mtctr 3
bctrl
ld 2, 40(1)
.LBB0_2:
...
and it would be safe to do all of this unconditionally with a predicated
beqctrl instruction.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179156 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-10 06:42:34 +00:00
|
|
|
MachineInstrBuilder(*MI->getParent()->getParent(), MI)
|
|
|
|
.addImm(Pred[0].getImm())
|
|
|
|
.addReg(Pred[1].getReg());
|
|
|
|
return true;
|
2013-04-09 22:58:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool PPCInstrInfo::SubsumesPredicate(
|
|
|
|
const SmallVectorImpl<MachineOperand> &Pred1,
|
|
|
|
const SmallVectorImpl<MachineOperand> &Pred2) const {
|
|
|
|
assert(Pred1.size() == 2 && "Invalid PPC first predicate");
|
|
|
|
assert(Pred2.size() == 2 && "Invalid PPC second predicate");
|
|
|
|
|
|
|
|
if (Pred1[1].getReg() == PPC::CTR8 || Pred1[1].getReg() == PPC::CTR)
|
|
|
|
return false;
|
|
|
|
if (Pred2[1].getReg() == PPC::CTR8 || Pred2[1].getReg() == PPC::CTR)
|
|
|
|
return false;
|
|
|
|
|
2013-12-11 23:12:25 +00:00
|
|
|
// P1 can only subsume P2 if they test the same condition register.
|
|
|
|
if (Pred1[1].getReg() != Pred2[1].getReg())
|
|
|
|
return false;
|
|
|
|
|
2013-04-09 22:58:37 +00:00
|
|
|
PPC::Predicate P1 = (PPC::Predicate) Pred1[0].getImm();
|
|
|
|
PPC::Predicate P2 = (PPC::Predicate) Pred2[0].getImm();
|
|
|
|
|
|
|
|
if (P1 == P2)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Does P1 subsume P2, e.g. GE subsumes GT.
|
|
|
|
if (P1 == PPC::PRED_LE &&
|
|
|
|
(P2 == PPC::PRED_LT || P2 == PPC::PRED_EQ))
|
|
|
|
return true;
|
|
|
|
if (P1 == PPC::PRED_GE &&
|
|
|
|
(P2 == PPC::PRED_GT || P2 == PPC::PRED_EQ))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool PPCInstrInfo::DefinesPredicate(MachineInstr *MI,
|
|
|
|
std::vector<MachineOperand> &Pred) const {
|
|
|
|
// Note: At the present time, the contents of Pred from this function is
|
|
|
|
// unused by IfConversion. This implementation follows ARM by pushing the
|
|
|
|
// CR-defining operand. Because the 'DZ' and 'DNZ' count as types of
|
|
|
|
// predicate, instructions defining CTR or CTR8 are also included as
|
|
|
|
// predicate-defining instructions.
|
|
|
|
|
|
|
|
const TargetRegisterClass *RCs[] =
|
|
|
|
{ &PPC::CRRCRegClass, &PPC::CRBITRCRegClass,
|
|
|
|
&PPC::CTRRCRegClass, &PPC::CTRRC8RegClass };
|
|
|
|
|
|
|
|
bool Found = false;
|
|
|
|
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
|
|
|
|
const MachineOperand &MO = MI->getOperand(i);
|
2013-04-10 07:17:47 +00:00
|
|
|
for (unsigned c = 0; c < array_lengthof(RCs) && !Found; ++c) {
|
2013-04-09 22:58:37 +00:00
|
|
|
const TargetRegisterClass *RC = RCs[c];
|
2013-04-10 07:17:47 +00:00
|
|
|
if (MO.isReg()) {
|
|
|
|
if (MO.isDef() && RC->contains(MO.getReg())) {
|
2013-04-09 22:58:37 +00:00
|
|
|
Pred.push_back(MO);
|
|
|
|
Found = true;
|
|
|
|
}
|
2013-04-10 07:17:47 +00:00
|
|
|
} else if (MO.isRegMask()) {
|
|
|
|
for (TargetRegisterClass::iterator I = RC->begin(),
|
|
|
|
IE = RC->end(); I != IE; ++I)
|
|
|
|
if (MO.clobbersPhysReg(*I)) {
|
|
|
|
Pred.push_back(MO);
|
|
|
|
Found = true;
|
|
|
|
}
|
2013-04-09 22:58:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return Found;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool PPCInstrInfo::isPredicable(MachineInstr *MI) const {
|
|
|
|
unsigned OpC = MI->getOpcode();
|
|
|
|
switch (OpC) {
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
case PPC::B:
|
|
|
|
case PPC::BLR:
|
PPC: Prep for if conversion of bctr[l]
This adds in-principle support for if-converting the bctr[l] instructions.
These instructions are used for indirect branching. It seems, however, that the
current if converter will never actually predicate these. To do so, it would
need the ability to hoist a few setup insts. out of the conditionally-executed
block. For example, code like this:
void foo(int a, int (*bar)()) { if (a != 0) bar(); }
becomes:
...
beq 0, .LBB0_2
std 2, 40(1)
mr 12, 4
ld 3, 0(4)
ld 11, 16(4)
ld 2, 8(4)
mtctr 3
bctrl
ld 2, 40(1)
.LBB0_2:
...
and it would be safe to do all of this unconditionally with a predicated
beqctrl instruction.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179156 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-10 06:42:34 +00:00
|
|
|
case PPC::BCTR:
|
|
|
|
case PPC::BCTR8:
|
|
|
|
case PPC::BCTRL:
|
|
|
|
case PPC::BCTRL8:
|
2013-04-09 22:58:37 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-18 22:15:08 +00:00
|
|
|
bool PPCInstrInfo::analyzeCompare(const MachineInstr *MI,
|
|
|
|
unsigned &SrcReg, unsigned &SrcReg2,
|
|
|
|
int &Mask, int &Value) const {
|
|
|
|
unsigned Opc = MI->getOpcode();
|
|
|
|
|
|
|
|
switch (Opc) {
|
|
|
|
default: return false;
|
|
|
|
case PPC::CMPWI:
|
|
|
|
case PPC::CMPLWI:
|
|
|
|
case PPC::CMPDI:
|
|
|
|
case PPC::CMPLDI:
|
|
|
|
SrcReg = MI->getOperand(1).getReg();
|
|
|
|
SrcReg2 = 0;
|
|
|
|
Value = MI->getOperand(2).getImm();
|
|
|
|
Mask = 0xFFFF;
|
|
|
|
return true;
|
|
|
|
case PPC::CMPW:
|
|
|
|
case PPC::CMPLW:
|
|
|
|
case PPC::CMPD:
|
|
|
|
case PPC::CMPLD:
|
|
|
|
case PPC::FCMPUS:
|
|
|
|
case PPC::FCMPUD:
|
|
|
|
SrcReg = MI->getOperand(1).getReg();
|
|
|
|
SrcReg2 = MI->getOperand(2).getReg();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2013-04-19 22:08:38 +00:00
|
|
|
|
2013-04-18 22:15:08 +00:00
|
|
|
bool PPCInstrInfo::optimizeCompareInstr(MachineInstr *CmpInstr,
|
|
|
|
unsigned SrcReg, unsigned SrcReg2,
|
|
|
|
int Mask, int Value,
|
|
|
|
const MachineRegisterInfo *MRI) const {
|
2013-04-18 22:54:25 +00:00
|
|
|
if (DisableCmpOpt)
|
|
|
|
return false;
|
|
|
|
|
2013-04-18 22:15:08 +00:00
|
|
|
int OpC = CmpInstr->getOpcode();
|
|
|
|
unsigned CRReg = CmpInstr->getOperand(0).getReg();
|
2013-05-08 12:16:14 +00:00
|
|
|
|
|
|
|
// FP record forms set CR1 based on the execption status bits, not a
|
|
|
|
// comparison with zero.
|
|
|
|
if (OpC == PPC::FCMPUS || OpC == PPC::FCMPUD)
|
|
|
|
return false;
|
2013-04-18 22:15:08 +00:00
|
|
|
|
|
|
|
// The record forms set the condition register based on a signed comparison
|
|
|
|
// with zero (so says the ISA manual). This is not as straightforward as it
|
|
|
|
// seems, however, because this is always a 64-bit comparison on PPC64, even
|
|
|
|
// for instructions that are 32-bit in nature (like slw for example).
|
|
|
|
// So, on PPC32, for unsigned comparisons, we can use the record forms only
|
|
|
|
// for equality checks (as those don't depend on the sign). On PPC64,
|
|
|
|
// we are restricted to equality for unsigned 64-bit comparisons and for
|
|
|
|
// signed 32-bit comparisons the applicability is more restricted.
|
2014-06-12 21:48:52 +00:00
|
|
|
bool isPPC64 = Subtarget.isPPC64();
|
2013-04-18 22:15:08 +00:00
|
|
|
bool is32BitSignedCompare = OpC == PPC::CMPWI || OpC == PPC::CMPW;
|
|
|
|
bool is32BitUnsignedCompare = OpC == PPC::CMPLWI || OpC == PPC::CMPLW;
|
|
|
|
bool is64BitUnsignedCompare = OpC == PPC::CMPLDI || OpC == PPC::CMPLD;
|
|
|
|
|
|
|
|
// Get the unique definition of SrcReg.
|
|
|
|
MachineInstr *MI = MRI->getUniqueVRegDef(SrcReg);
|
|
|
|
if (!MI) return false;
|
|
|
|
int MIOpC = MI->getOpcode();
|
|
|
|
|
|
|
|
bool equalityOnly = false;
|
|
|
|
bool noSub = false;
|
|
|
|
if (isPPC64) {
|
|
|
|
if (is32BitSignedCompare) {
|
|
|
|
// We can perform this optimization only if MI is sign-extending.
|
|
|
|
if (MIOpC == PPC::SRAW || MIOpC == PPC::SRAWo ||
|
|
|
|
MIOpC == PPC::SRAWI || MIOpC == PPC::SRAWIo ||
|
|
|
|
MIOpC == PPC::EXTSB || MIOpC == PPC::EXTSBo ||
|
|
|
|
MIOpC == PPC::EXTSH || MIOpC == PPC::EXTSHo ||
|
|
|
|
MIOpC == PPC::EXTSW || MIOpC == PPC::EXTSWo) {
|
|
|
|
noSub = true;
|
|
|
|
} else
|
|
|
|
return false;
|
|
|
|
} else if (is32BitUnsignedCompare) {
|
|
|
|
// We can perform this optimization, equality only, if MI is
|
|
|
|
// zero-extending.
|
|
|
|
if (MIOpC == PPC::CNTLZW || MIOpC == PPC::CNTLZWo ||
|
|
|
|
MIOpC == PPC::SLW || MIOpC == PPC::SLWo ||
|
|
|
|
MIOpC == PPC::SRW || MIOpC == PPC::SRWo) {
|
|
|
|
noSub = true;
|
|
|
|
equalityOnly = true;
|
|
|
|
} else
|
|
|
|
return false;
|
2013-05-08 12:16:14 +00:00
|
|
|
} else
|
2013-04-18 22:15:08 +00:00
|
|
|
equalityOnly = is64BitUnsignedCompare;
|
2013-05-08 12:16:14 +00:00
|
|
|
} else
|
2013-04-18 22:15:08 +00:00
|
|
|
equalityOnly = is32BitUnsignedCompare;
|
|
|
|
|
|
|
|
if (equalityOnly) {
|
|
|
|
// We need to check the uses of the condition register in order to reject
|
|
|
|
// non-equality comparisons.
|
2014-03-13 23:12:04 +00:00
|
|
|
for (MachineRegisterInfo::use_instr_iterator I =MRI->use_instr_begin(CRReg),
|
|
|
|
IE = MRI->use_instr_end(); I != IE; ++I) {
|
2013-04-18 22:15:08 +00:00
|
|
|
MachineInstr *UseMI = &*I;
|
|
|
|
if (UseMI->getOpcode() == PPC::BCC) {
|
|
|
|
unsigned Pred = UseMI->getOperand(0).getImm();
|
2013-05-07 17:49:55 +00:00
|
|
|
if (Pred != PPC::PRED_EQ && Pred != PPC::PRED_NE)
|
|
|
|
return false;
|
2013-04-18 22:15:08 +00:00
|
|
|
} else if (UseMI->getOpcode() == PPC::ISEL ||
|
|
|
|
UseMI->getOpcode() == PPC::ISEL8) {
|
|
|
|
unsigned SubIdx = UseMI->getOperand(3).getSubReg();
|
2013-05-07 17:49:55 +00:00
|
|
|
if (SubIdx != PPC::sub_eq)
|
|
|
|
return false;
|
2013-04-18 22:15:08 +00:00
|
|
|
} else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-07 17:49:55 +00:00
|
|
|
MachineBasicBlock::iterator I = CmpInstr;
|
2013-04-18 22:15:08 +00:00
|
|
|
|
|
|
|
// Scan forward to find the first use of the compare.
|
|
|
|
for (MachineBasicBlock::iterator EL = CmpInstr->getParent()->end();
|
|
|
|
I != EL; ++I) {
|
|
|
|
bool FoundUse = false;
|
2014-03-13 23:12:04 +00:00
|
|
|
for (MachineRegisterInfo::use_instr_iterator J =MRI->use_instr_begin(CRReg),
|
|
|
|
JE = MRI->use_instr_end(); J != JE; ++J)
|
2013-04-18 22:15:08 +00:00
|
|
|
if (&*J == &*I) {
|
|
|
|
FoundUse = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (FoundUse)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// There are two possible candidates which can be changed to set CR[01].
|
|
|
|
// One is MI, the other is a SUB instruction.
|
|
|
|
// For CMPrr(r1,r2), we are looking for SUB(r1,r2) or SUB(r2,r1).
|
2014-04-25 05:30:21 +00:00
|
|
|
MachineInstr *Sub = nullptr;
|
2013-04-18 22:15:08 +00:00
|
|
|
if (SrcReg2 != 0)
|
|
|
|
// MI is not a candidate for CMPrr.
|
2014-04-25 05:30:21 +00:00
|
|
|
MI = nullptr;
|
2013-04-18 22:15:08 +00:00
|
|
|
// FIXME: Conservatively refuse to convert an instruction which isn't in the
|
|
|
|
// same BB as the comparison. This is to allow the check below to avoid calls
|
|
|
|
// (and other explicit clobbers); instead we should really check for these
|
|
|
|
// more explicitly (in at least a few predecessors).
|
|
|
|
else if (MI->getParent() != CmpInstr->getParent() || Value != 0) {
|
|
|
|
// PPC does not have a record-form SUBri.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Search for Sub.
|
|
|
|
const TargetRegisterInfo *TRI = &getRegisterInfo();
|
|
|
|
--I;
|
2013-05-07 17:49:55 +00:00
|
|
|
|
|
|
|
// Get ready to iterate backward from CmpInstr.
|
|
|
|
MachineBasicBlock::iterator E = MI,
|
|
|
|
B = CmpInstr->getParent()->begin();
|
|
|
|
|
2013-04-18 22:15:08 +00:00
|
|
|
for (; I != E && !noSub; --I) {
|
|
|
|
const MachineInstr &Instr = *I;
|
|
|
|
unsigned IOpC = Instr.getOpcode();
|
|
|
|
|
|
|
|
if (&*I != CmpInstr && (
|
2013-05-08 12:16:14 +00:00
|
|
|
Instr.modifiesRegister(PPC::CR0, TRI) ||
|
|
|
|
Instr.readsRegister(PPC::CR0, TRI)))
|
2013-04-18 22:15:08 +00:00
|
|
|
// This instruction modifies or uses the record condition register after
|
|
|
|
// the one we want to change. While we could do this transformation, it
|
|
|
|
// would likely not be profitable. This transformation removes one
|
|
|
|
// instruction, and so even forcing RA to generate one move probably
|
|
|
|
// makes it unprofitable.
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Check whether CmpInstr can be made redundant by the current instruction.
|
|
|
|
if ((OpC == PPC::CMPW || OpC == PPC::CMPLW ||
|
|
|
|
OpC == PPC::CMPD || OpC == PPC::CMPLD) &&
|
|
|
|
(IOpC == PPC::SUBF || IOpC == PPC::SUBF8) &&
|
|
|
|
((Instr.getOperand(1).getReg() == SrcReg &&
|
|
|
|
Instr.getOperand(2).getReg() == SrcReg2) ||
|
|
|
|
(Instr.getOperand(1).getReg() == SrcReg2 &&
|
|
|
|
Instr.getOperand(2).getReg() == SrcReg))) {
|
|
|
|
Sub = &*I;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (I == B)
|
|
|
|
// The 'and' is below the comparison instruction.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return false if no candidates exist.
|
|
|
|
if (!MI && !Sub)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// The single candidate is called MI.
|
|
|
|
if (!MI) MI = Sub;
|
|
|
|
|
|
|
|
int NewOpC = -1;
|
|
|
|
MIOpC = MI->getOpcode();
|
|
|
|
if (MIOpC == PPC::ANDIo || MIOpC == PPC::ANDIo8)
|
|
|
|
NewOpC = MIOpC;
|
|
|
|
else {
|
|
|
|
NewOpC = PPC::getRecordFormOpcode(MIOpC);
|
|
|
|
if (NewOpC == -1 && PPC::getNonRecordFormOpcode(MIOpC) != -1)
|
|
|
|
NewOpC = MIOpC;
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: On the non-embedded POWER architectures, only some of the record
|
|
|
|
// forms are fast, and we should use only the fast ones.
|
|
|
|
|
|
|
|
// The defining instruction has a record form (or is already a record
|
|
|
|
// form). It is possible, however, that we'll need to reverse the condition
|
|
|
|
// code of the users.
|
|
|
|
if (NewOpC == -1)
|
|
|
|
return false;
|
|
|
|
|
2013-04-19 22:08:38 +00:00
|
|
|
SmallVector<std::pair<MachineOperand*, PPC::Predicate>, 4> PredsToUpdate;
|
|
|
|
SmallVector<std::pair<MachineOperand*, unsigned>, 4> SubRegsToUpdate;
|
2013-04-18 22:15:08 +00:00
|
|
|
|
|
|
|
// If we have SUB(r1, r2) and CMP(r2, r1), the condition code based on CMP
|
|
|
|
// needs to be updated to be based on SUB. Push the condition code
|
|
|
|
// operands to OperandsToUpdate. If it is safe to remove CmpInstr, the
|
|
|
|
// condition code of these operands will be modified.
|
|
|
|
bool ShouldSwap = false;
|
|
|
|
if (Sub) {
|
|
|
|
ShouldSwap = SrcReg2 != 0 && Sub->getOperand(1).getReg() == SrcReg2 &&
|
|
|
|
Sub->getOperand(2).getReg() == SrcReg;
|
|
|
|
|
|
|
|
// The operands to subf are the opposite of sub, so only in the fixed-point
|
|
|
|
// case, invert the order.
|
2013-05-08 12:16:14 +00:00
|
|
|
ShouldSwap = !ShouldSwap;
|
2013-04-18 22:15:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (ShouldSwap)
|
2014-03-13 23:12:04 +00:00
|
|
|
for (MachineRegisterInfo::use_instr_iterator
|
|
|
|
I = MRI->use_instr_begin(CRReg), IE = MRI->use_instr_end();
|
|
|
|
I != IE; ++I) {
|
2013-04-18 22:15:08 +00:00
|
|
|
MachineInstr *UseMI = &*I;
|
|
|
|
if (UseMI->getOpcode() == PPC::BCC) {
|
|
|
|
PPC::Predicate Pred = (PPC::Predicate) UseMI->getOperand(0).getImm();
|
2013-04-19 22:08:38 +00:00
|
|
|
assert((!equalityOnly ||
|
|
|
|
Pred == PPC::PRED_EQ || Pred == PPC::PRED_NE) &&
|
|
|
|
"Invalid predicate for equality-only optimization");
|
2014-03-13 23:12:04 +00:00
|
|
|
PredsToUpdate.push_back(std::make_pair(&(UseMI->getOperand(0)),
|
2013-04-20 05:16:26 +00:00
|
|
|
PPC::getSwappedPredicate(Pred)));
|
2013-04-18 22:15:08 +00:00
|
|
|
} else if (UseMI->getOpcode() == PPC::ISEL ||
|
|
|
|
UseMI->getOpcode() == PPC::ISEL8) {
|
2013-04-19 22:08:38 +00:00
|
|
|
unsigned NewSubReg = UseMI->getOperand(3).getSubReg();
|
|
|
|
assert((!equalityOnly || NewSubReg == PPC::sub_eq) &&
|
|
|
|
"Invalid CR bit for equality-only optimization");
|
|
|
|
|
|
|
|
if (NewSubReg == PPC::sub_lt)
|
|
|
|
NewSubReg = PPC::sub_gt;
|
|
|
|
else if (NewSubReg == PPC::sub_gt)
|
|
|
|
NewSubReg = PPC::sub_lt;
|
|
|
|
|
2014-03-13 23:12:04 +00:00
|
|
|
SubRegsToUpdate.push_back(std::make_pair(&(UseMI->getOperand(3)),
|
2013-04-19 22:08:38 +00:00
|
|
|
NewSubReg));
|
2013-04-18 22:15:08 +00:00
|
|
|
} else // We need to abort on a user we don't understand.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create a new virtual register to hold the value of the CR set by the
|
|
|
|
// record-form instruction. If the instruction was not previously in
|
|
|
|
// record form, then set the kill flag on the CR.
|
|
|
|
CmpInstr->eraseFromParent();
|
|
|
|
|
|
|
|
MachineBasicBlock::iterator MII = MI;
|
2014-03-02 12:27:27 +00:00
|
|
|
BuildMI(*MI->getParent(), std::next(MII), MI->getDebugLoc(),
|
2013-04-18 22:15:08 +00:00
|
|
|
get(TargetOpcode::COPY), CRReg)
|
2013-05-08 12:16:14 +00:00
|
|
|
.addReg(PPC::CR0, MIOpC != NewOpC ? RegState::Kill : 0);
|
2013-04-18 22:15:08 +00:00
|
|
|
|
|
|
|
if (MIOpC != NewOpC) {
|
|
|
|
// We need to be careful here: we're replacing one instruction with
|
|
|
|
// another, and we need to make sure that we get all of the right
|
|
|
|
// implicit uses and defs. On the other hand, the caller may be holding
|
|
|
|
// an iterator to this instruction, and so we can't delete it (this is
|
|
|
|
// specifically the case if this is the instruction directly after the
|
|
|
|
// compare).
|
|
|
|
|
|
|
|
const MCInstrDesc &NewDesc = get(NewOpC);
|
|
|
|
MI->setDesc(NewDesc);
|
|
|
|
|
|
|
|
if (NewDesc.ImplicitDefs)
|
|
|
|
for (const uint16_t *ImpDefs = NewDesc.getImplicitDefs();
|
|
|
|
*ImpDefs; ++ImpDefs)
|
|
|
|
if (!MI->definesRegister(*ImpDefs))
|
|
|
|
MI->addOperand(*MI->getParent()->getParent(),
|
|
|
|
MachineOperand::CreateReg(*ImpDefs, true, true));
|
|
|
|
if (NewDesc.ImplicitUses)
|
|
|
|
for (const uint16_t *ImpUses = NewDesc.getImplicitUses();
|
|
|
|
*ImpUses; ++ImpUses)
|
|
|
|
if (!MI->readsRegister(*ImpUses))
|
|
|
|
MI->addOperand(*MI->getParent()->getParent(),
|
|
|
|
MachineOperand::CreateReg(*ImpUses, false, true));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Modify the condition code of operands in OperandsToUpdate.
|
|
|
|
// Since we have SUB(r1, r2) and CMP(r2, r1), the condition code needs to
|
|
|
|
// be changed from r2 > r1 to r1 < r2, from r2 < r1 to r1 > r2, etc.
|
2013-04-19 22:08:38 +00:00
|
|
|
for (unsigned i = 0, e = PredsToUpdate.size(); i < e; i++)
|
|
|
|
PredsToUpdate[i].first->setImm(PredsToUpdate[i].second);
|
2013-04-18 22:15:08 +00:00
|
|
|
|
2013-04-19 22:08:38 +00:00
|
|
|
for (unsigned i = 0, e = SubRegsToUpdate.size(); i < e; i++)
|
|
|
|
SubRegsToUpdate[i].first->setSubReg(SubRegsToUpdate[i].second);
|
2013-04-18 22:15:08 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2008-04-16 20:10:13 +00:00
|
|
|
/// GetInstSize - Return the number of bytes of code the specified
|
|
|
|
/// instruction may be. This returns the maximum number of bytes.
|
|
|
|
///
|
|
|
|
unsigned PPCInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const {
|
2014-02-02 06:12:27 +00:00
|
|
|
unsigned Opcode = MI->getOpcode();
|
|
|
|
|
|
|
|
if (Opcode == PPC::INLINEASM) {
|
2008-04-16 20:10:13 +00:00
|
|
|
const MachineFunction *MF = MI->getParent()->getParent();
|
|
|
|
const char *AsmStr = MI->getOperand(0).getSymbolName();
|
2009-08-22 20:48:53 +00:00
|
|
|
return getInlineAsmLength(AsmStr, *MF->getTarget().getMCAsmInfo());
|
2014-02-02 06:12:27 +00:00
|
|
|
} else {
|
|
|
|
const MCInstrDesc &Desc = get(Opcode);
|
|
|
|
return Desc.getSize();
|
2008-04-16 20:10:13 +00:00
|
|
|
}
|
|
|
|
}
|
2013-04-08 16:24:03 +00:00
|
|
|
|
[PowerPC] Select between VSX A-type and M-type FMA instructions just before RA
The VSX instruction set has two types of FMA instructions: A-type (where the
addend is taken from the output register) and M-type (where one of the product
operands is taken from the output register). This adds a small pass that runs
just after MI scheduling (and, thus, just before register allocation) that
mutates A-type instructions (that are created during isel) into M-type
instructions when:
1. This will eliminate an otherwise-necessary copy of the addend
2. One of the product operands is killed by the instruction
The "right" moment to make this decision is in between scheduling and register
allocation, because only there do we know whether or not one of the product
operands is killed by any particular instruction. Unfortunately, this also
makes the implementation somewhat complicated, because the MIs are not in SSA
form and we need to preserve the LiveIntervals analysis.
As a simple example, if we have:
%vreg5<def> = COPY %vreg9; VSLRC:%vreg5,%vreg9
%vreg5<def,tied1> = XSMADDADP %vreg5<tied0>, %vreg17, %vreg16,
%RM<imp-use>; VSLRC:%vreg5,%vreg17,%vreg16
...
%vreg9<def,tied1> = XSMADDADP %vreg9<tied0>, %vreg17, %vreg19,
%RM<imp-use>; VSLRC:%vreg9,%vreg17,%vreg19
...
We can eliminate the copy by changing from the A-type to the
M-type instruction. This means:
%vreg5<def,tied1> = XSMADDADP %vreg5<tied0>, %vreg17, %vreg16,
%RM<imp-use>; VSLRC:%vreg5,%vreg17,%vreg16
is replaced by:
%vreg16<def,tied1> = XSMADDMDP %vreg16<tied0>, %vreg18, %vreg9,
%RM<imp-use>; VSLRC:%vreg16,%vreg18,%vreg9
and we remove: %vreg5<def> = COPY %vreg9; VSLRC:%vreg5,%vreg9
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204768 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-25 23:29:21 +00:00
|
|
|
#undef DEBUG_TYPE
|
|
|
|
#define DEBUG_TYPE "ppc-vsx-fma-mutate"
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
// PPCVSXFMAMutate pass - For copies between VSX registers and non-VSX registers
|
|
|
|
// (Altivec and scalar floating-point registers), we need to transform the
|
|
|
|
// copies into subregister copies with other restrictions.
|
|
|
|
struct PPCVSXFMAMutate : public MachineFunctionPass {
|
|
|
|
static char ID;
|
|
|
|
PPCVSXFMAMutate() : MachineFunctionPass(ID) {
|
|
|
|
initializePPCVSXFMAMutatePass(*PassRegistry::getPassRegistry());
|
|
|
|
}
|
|
|
|
|
|
|
|
LiveIntervals *LIS;
|
|
|
|
|
|
|
|
const PPCTargetMachine *TM;
|
|
|
|
const PPCInstrInfo *TII;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
bool processBlock(MachineBasicBlock &MBB) {
|
|
|
|
bool Changed = false;
|
|
|
|
|
|
|
|
MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
|
|
|
|
for (MachineBasicBlock::iterator I = MBB.begin(), IE = MBB.end();
|
|
|
|
I != IE; ++I) {
|
|
|
|
MachineInstr *MI = I;
|
|
|
|
|
|
|
|
// The default (A-type) VSX FMA form kills the addend (it is taken from
|
|
|
|
// the target register, which is then updated to reflect the result of
|
|
|
|
// the FMA). If the instruction, however, kills one of the registers
|
|
|
|
// used for the product, then we can use the M-form instruction (which
|
|
|
|
// will take that value from the to-be-defined register).
|
|
|
|
|
|
|
|
int AltOpc = PPC::getAltVSXFMAOpcode(MI->getOpcode());
|
|
|
|
if (AltOpc == -1)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// This pass is run after register coalescing, and so we're looking for
|
|
|
|
// a situation like this:
|
|
|
|
// ...
|
|
|
|
// %vreg5<def> = COPY %vreg9; VSLRC:%vreg5,%vreg9
|
|
|
|
// %vreg5<def,tied1> = XSMADDADP %vreg5<tied0>, %vreg17, %vreg16,
|
|
|
|
// %RM<imp-use>; VSLRC:%vreg5,%vreg17,%vreg16
|
|
|
|
// ...
|
|
|
|
// %vreg9<def,tied1> = XSMADDADP %vreg9<tied0>, %vreg17, %vreg19,
|
|
|
|
// %RM<imp-use>; VSLRC:%vreg9,%vreg17,%vreg19
|
|
|
|
// ...
|
|
|
|
// Where we can eliminate the copy by changing from the A-type to the
|
|
|
|
// M-type instruction. Specifically, for this example, this means:
|
|
|
|
// %vreg5<def,tied1> = XSMADDADP %vreg5<tied0>, %vreg17, %vreg16,
|
|
|
|
// %RM<imp-use>; VSLRC:%vreg5,%vreg17,%vreg16
|
|
|
|
// is replaced by:
|
|
|
|
// %vreg16<def,tied1> = XSMADDMDP %vreg16<tied0>, %vreg18, %vreg9,
|
|
|
|
// %RM<imp-use>; VSLRC:%vreg16,%vreg18,%vreg9
|
|
|
|
// and we remove: %vreg5<def> = COPY %vreg9; VSLRC:%vreg5,%vreg9
|
|
|
|
|
|
|
|
SlotIndex FMAIdx = LIS->getInstructionIndex(MI);
|
|
|
|
|
|
|
|
VNInfo *AddendValNo =
|
|
|
|
LIS->getInterval(MI->getOperand(1).getReg()).Query(FMAIdx).valueIn();
|
|
|
|
MachineInstr *AddendMI = LIS->getInstructionFromIndex(AddendValNo->def);
|
|
|
|
|
|
|
|
// The addend and this instruction must be in the same block.
|
|
|
|
|
2014-03-29 05:29:01 +00:00
|
|
|
if (!AddendMI || AddendMI->getParent() != MI->getParent())
|
[PowerPC] Select between VSX A-type and M-type FMA instructions just before RA
The VSX instruction set has two types of FMA instructions: A-type (where the
addend is taken from the output register) and M-type (where one of the product
operands is taken from the output register). This adds a small pass that runs
just after MI scheduling (and, thus, just before register allocation) that
mutates A-type instructions (that are created during isel) into M-type
instructions when:
1. This will eliminate an otherwise-necessary copy of the addend
2. One of the product operands is killed by the instruction
The "right" moment to make this decision is in between scheduling and register
allocation, because only there do we know whether or not one of the product
operands is killed by any particular instruction. Unfortunately, this also
makes the implementation somewhat complicated, because the MIs are not in SSA
form and we need to preserve the LiveIntervals analysis.
As a simple example, if we have:
%vreg5<def> = COPY %vreg9; VSLRC:%vreg5,%vreg9
%vreg5<def,tied1> = XSMADDADP %vreg5<tied0>, %vreg17, %vreg16,
%RM<imp-use>; VSLRC:%vreg5,%vreg17,%vreg16
...
%vreg9<def,tied1> = XSMADDADP %vreg9<tied0>, %vreg17, %vreg19,
%RM<imp-use>; VSLRC:%vreg9,%vreg17,%vreg19
...
We can eliminate the copy by changing from the A-type to the
M-type instruction. This means:
%vreg5<def,tied1> = XSMADDADP %vreg5<tied0>, %vreg17, %vreg16,
%RM<imp-use>; VSLRC:%vreg5,%vreg17,%vreg16
is replaced by:
%vreg16<def,tied1> = XSMADDMDP %vreg16<tied0>, %vreg18, %vreg9,
%RM<imp-use>; VSLRC:%vreg16,%vreg18,%vreg9
and we remove: %vreg5<def> = COPY %vreg9; VSLRC:%vreg5,%vreg9
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204768 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-25 23:29:21 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
// The addend must be a full copy within the same register class.
|
|
|
|
|
|
|
|
if (!AddendMI->isFullCopy())
|
|
|
|
continue;
|
|
|
|
|
2014-03-29 05:29:01 +00:00
|
|
|
unsigned AddendSrcReg = AddendMI->getOperand(1).getReg();
|
|
|
|
if (TargetRegisterInfo::isVirtualRegister(AddendSrcReg)) {
|
|
|
|
if (MRI.getRegClass(AddendMI->getOperand(0).getReg()) !=
|
|
|
|
MRI.getRegClass(AddendSrcReg))
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
// If AddendSrcReg is a physical register, make sure the destination
|
|
|
|
// register class contains it.
|
|
|
|
if (!MRI.getRegClass(AddendMI->getOperand(0).getReg())
|
|
|
|
->contains(AddendSrcReg))
|
|
|
|
continue;
|
|
|
|
}
|
[PowerPC] Select between VSX A-type and M-type FMA instructions just before RA
The VSX instruction set has two types of FMA instructions: A-type (where the
addend is taken from the output register) and M-type (where one of the product
operands is taken from the output register). This adds a small pass that runs
just after MI scheduling (and, thus, just before register allocation) that
mutates A-type instructions (that are created during isel) into M-type
instructions when:
1. This will eliminate an otherwise-necessary copy of the addend
2. One of the product operands is killed by the instruction
The "right" moment to make this decision is in between scheduling and register
allocation, because only there do we know whether or not one of the product
operands is killed by any particular instruction. Unfortunately, this also
makes the implementation somewhat complicated, because the MIs are not in SSA
form and we need to preserve the LiveIntervals analysis.
As a simple example, if we have:
%vreg5<def> = COPY %vreg9; VSLRC:%vreg5,%vreg9
%vreg5<def,tied1> = XSMADDADP %vreg5<tied0>, %vreg17, %vreg16,
%RM<imp-use>; VSLRC:%vreg5,%vreg17,%vreg16
...
%vreg9<def,tied1> = XSMADDADP %vreg9<tied0>, %vreg17, %vreg19,
%RM<imp-use>; VSLRC:%vreg9,%vreg17,%vreg19
...
We can eliminate the copy by changing from the A-type to the
M-type instruction. This means:
%vreg5<def,tied1> = XSMADDADP %vreg5<tied0>, %vreg17, %vreg16,
%RM<imp-use>; VSLRC:%vreg5,%vreg17,%vreg16
is replaced by:
%vreg16<def,tied1> = XSMADDMDP %vreg16<tied0>, %vreg18, %vreg9,
%RM<imp-use>; VSLRC:%vreg16,%vreg18,%vreg9
and we remove: %vreg5<def> = COPY %vreg9; VSLRC:%vreg5,%vreg9
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204768 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-25 23:29:21 +00:00
|
|
|
|
|
|
|
// In theory, there could be other uses of the addend copy before this
|
|
|
|
// fma. We could deal with this, but that would require additional
|
|
|
|
// logic below and I suspect it will not occur in any relevant
|
|
|
|
// situations.
|
|
|
|
bool OtherUsers = false;
|
|
|
|
for (auto J = std::prev(I), JE = MachineBasicBlock::iterator(AddendMI);
|
|
|
|
J != JE; --J)
|
|
|
|
if (J->readsVirtualRegister(AddendMI->getOperand(0).getReg())) {
|
|
|
|
OtherUsers = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (OtherUsers)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Find one of the product operands that is killed by this instruction.
|
|
|
|
|
|
|
|
unsigned KilledProdOp = 0, OtherProdOp = 0;
|
|
|
|
if (LIS->getInterval(MI->getOperand(2).getReg())
|
|
|
|
.Query(FMAIdx).isKill()) {
|
|
|
|
KilledProdOp = 2;
|
|
|
|
OtherProdOp = 3;
|
|
|
|
} else if (LIS->getInterval(MI->getOperand(3).getReg())
|
|
|
|
.Query(FMAIdx).isKill()) {
|
|
|
|
KilledProdOp = 3;
|
|
|
|
OtherProdOp = 2;
|
|
|
|
}
|
|
|
|
|
2014-03-29 05:29:01 +00:00
|
|
|
// If there are no killed product operands, then this transformation is
|
|
|
|
// likely not profitable.
|
[PowerPC] Select between VSX A-type and M-type FMA instructions just before RA
The VSX instruction set has two types of FMA instructions: A-type (where the
addend is taken from the output register) and M-type (where one of the product
operands is taken from the output register). This adds a small pass that runs
just after MI scheduling (and, thus, just before register allocation) that
mutates A-type instructions (that are created during isel) into M-type
instructions when:
1. This will eliminate an otherwise-necessary copy of the addend
2. One of the product operands is killed by the instruction
The "right" moment to make this decision is in between scheduling and register
allocation, because only there do we know whether or not one of the product
operands is killed by any particular instruction. Unfortunately, this also
makes the implementation somewhat complicated, because the MIs are not in SSA
form and we need to preserve the LiveIntervals analysis.
As a simple example, if we have:
%vreg5<def> = COPY %vreg9; VSLRC:%vreg5,%vreg9
%vreg5<def,tied1> = XSMADDADP %vreg5<tied0>, %vreg17, %vreg16,
%RM<imp-use>; VSLRC:%vreg5,%vreg17,%vreg16
...
%vreg9<def,tied1> = XSMADDADP %vreg9<tied0>, %vreg17, %vreg19,
%RM<imp-use>; VSLRC:%vreg9,%vreg17,%vreg19
...
We can eliminate the copy by changing from the A-type to the
M-type instruction. This means:
%vreg5<def,tied1> = XSMADDADP %vreg5<tied0>, %vreg17, %vreg16,
%RM<imp-use>; VSLRC:%vreg5,%vreg17,%vreg16
is replaced by:
%vreg16<def,tied1> = XSMADDMDP %vreg16<tied0>, %vreg18, %vreg9,
%RM<imp-use>; VSLRC:%vreg16,%vreg18,%vreg9
and we remove: %vreg5<def> = COPY %vreg9; VSLRC:%vreg5,%vreg9
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204768 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-25 23:29:21 +00:00
|
|
|
if (!KilledProdOp)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// In order to replace the addend here with the source of the copy,
|
|
|
|
// it must still be live here.
|
|
|
|
if (!LIS->getInterval(AddendMI->getOperand(1).getReg()).liveAt(FMAIdx))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Transform: (O2 * O3) + O1 -> (O2 * O1) + O3.
|
|
|
|
|
|
|
|
unsigned AddReg = AddendMI->getOperand(1).getReg();
|
|
|
|
unsigned KilledProdReg = MI->getOperand(KilledProdOp).getReg();
|
|
|
|
unsigned OtherProdReg = MI->getOperand(OtherProdOp).getReg();
|
|
|
|
|
|
|
|
unsigned AddSubReg = AddendMI->getOperand(1).getSubReg();
|
|
|
|
unsigned KilledProdSubReg = MI->getOperand(KilledProdOp).getSubReg();
|
|
|
|
unsigned OtherProdSubReg = MI->getOperand(OtherProdOp).getSubReg();
|
|
|
|
|
|
|
|
bool AddRegKill = AddendMI->getOperand(1).isKill();
|
|
|
|
bool KilledProdRegKill = MI->getOperand(KilledProdOp).isKill();
|
|
|
|
bool OtherProdRegKill = MI->getOperand(OtherProdOp).isKill();
|
|
|
|
|
|
|
|
bool AddRegUndef = AddendMI->getOperand(1).isUndef();
|
|
|
|
bool KilledProdRegUndef = MI->getOperand(KilledProdOp).isUndef();
|
|
|
|
bool OtherProdRegUndef = MI->getOperand(OtherProdOp).isUndef();
|
|
|
|
|
|
|
|
unsigned OldFMAReg = MI->getOperand(0).getReg();
|
|
|
|
|
|
|
|
assert(OldFMAReg == AddendMI->getOperand(0).getReg() &&
|
|
|
|
"Addend copy not tied to old FMA output!");
|
|
|
|
|
|
|
|
DEBUG(dbgs() << "VSX FMA Mutation:\n " << *MI;);
|
|
|
|
|
|
|
|
MI->getOperand(0).setReg(KilledProdReg);
|
|
|
|
MI->getOperand(1).setReg(KilledProdReg);
|
|
|
|
MI->getOperand(3).setReg(AddReg);
|
|
|
|
MI->getOperand(2).setReg(OtherProdReg);
|
|
|
|
|
|
|
|
MI->getOperand(0).setSubReg(KilledProdSubReg);
|
|
|
|
MI->getOperand(1).setSubReg(KilledProdSubReg);
|
|
|
|
MI->getOperand(3).setSubReg(AddSubReg);
|
|
|
|
MI->getOperand(2).setSubReg(OtherProdSubReg);
|
|
|
|
|
|
|
|
MI->getOperand(1).setIsKill(KilledProdRegKill);
|
|
|
|
MI->getOperand(3).setIsKill(AddRegKill);
|
|
|
|
MI->getOperand(2).setIsKill(OtherProdRegKill);
|
|
|
|
|
|
|
|
MI->getOperand(1).setIsUndef(KilledProdRegUndef);
|
|
|
|
MI->getOperand(3).setIsUndef(AddRegUndef);
|
|
|
|
MI->getOperand(2).setIsUndef(OtherProdRegUndef);
|
|
|
|
|
|
|
|
MI->setDesc(TII->get(AltOpc));
|
|
|
|
|
|
|
|
DEBUG(dbgs() << " -> " << *MI);
|
|
|
|
|
|
|
|
// The killed product operand was killed here, so we can reuse it now
|
|
|
|
// for the result of the fma.
|
|
|
|
|
|
|
|
LiveInterval &FMAInt = LIS->getInterval(OldFMAReg);
|
|
|
|
VNInfo *FMAValNo = FMAInt.getVNInfoAt(FMAIdx.getRegSlot());
|
|
|
|
for (auto UI = MRI.reg_nodbg_begin(OldFMAReg), UE = MRI.reg_nodbg_end();
|
|
|
|
UI != UE;) {
|
|
|
|
MachineOperand &UseMO = *UI;
|
|
|
|
MachineInstr *UseMI = UseMO.getParent();
|
|
|
|
++UI;
|
|
|
|
|
|
|
|
// Don't replace the result register of the copy we're about to erase.
|
|
|
|
if (UseMI == AddendMI)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
UseMO.setReg(KilledProdReg);
|
|
|
|
UseMO.setSubReg(KilledProdSubReg);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Extend the live intervals of the killed product operand to hold the
|
|
|
|
// fma result.
|
|
|
|
|
|
|
|
LiveInterval &NewFMAInt = LIS->getInterval(KilledProdReg);
|
|
|
|
for (LiveInterval::iterator AI = FMAInt.begin(), AE = FMAInt.end();
|
|
|
|
AI != AE; ++AI) {
|
|
|
|
// Don't add the segment that corresponds to the original copy.
|
|
|
|
if (AI->valno == AddendValNo)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
VNInfo *NewFMAValNo =
|
|
|
|
NewFMAInt.getNextValue(AI->start,
|
|
|
|
LIS->getVNInfoAllocator());
|
|
|
|
|
|
|
|
NewFMAInt.addSegment(LiveInterval::Segment(AI->start, AI->end,
|
|
|
|
NewFMAValNo));
|
|
|
|
}
|
|
|
|
DEBUG(dbgs() << " extended: " << NewFMAInt << '\n');
|
|
|
|
|
|
|
|
FMAInt.removeValNo(FMAValNo);
|
|
|
|
DEBUG(dbgs() << " trimmed: " << FMAInt << '\n');
|
|
|
|
|
|
|
|
// Remove the (now unused) copy.
|
|
|
|
|
|
|
|
DEBUG(dbgs() << " removing: " << *AddendMI << '\n');
|
|
|
|
LIS->RemoveMachineInstrFromMaps(AddendMI);
|
|
|
|
AddendMI->eraseFromParent();
|
|
|
|
|
|
|
|
Changed = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Changed;
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
2014-04-29 07:57:37 +00:00
|
|
|
bool runOnMachineFunction(MachineFunction &MF) override {
|
2014-05-22 01:21:35 +00:00
|
|
|
TM = static_cast<const PPCTargetMachine *>(&MF.getTarget());
|
|
|
|
// If we don't have VSX then go ahead and return without doing
|
|
|
|
// anything.
|
|
|
|
if (!TM->getSubtargetImpl()->hasVSX())
|
|
|
|
return false;
|
|
|
|
|
[PowerPC] Select between VSX A-type and M-type FMA instructions just before RA
The VSX instruction set has two types of FMA instructions: A-type (where the
addend is taken from the output register) and M-type (where one of the product
operands is taken from the output register). This adds a small pass that runs
just after MI scheduling (and, thus, just before register allocation) that
mutates A-type instructions (that are created during isel) into M-type
instructions when:
1. This will eliminate an otherwise-necessary copy of the addend
2. One of the product operands is killed by the instruction
The "right" moment to make this decision is in between scheduling and register
allocation, because only there do we know whether or not one of the product
operands is killed by any particular instruction. Unfortunately, this also
makes the implementation somewhat complicated, because the MIs are not in SSA
form and we need to preserve the LiveIntervals analysis.
As a simple example, if we have:
%vreg5<def> = COPY %vreg9; VSLRC:%vreg5,%vreg9
%vreg5<def,tied1> = XSMADDADP %vreg5<tied0>, %vreg17, %vreg16,
%RM<imp-use>; VSLRC:%vreg5,%vreg17,%vreg16
...
%vreg9<def,tied1> = XSMADDADP %vreg9<tied0>, %vreg17, %vreg19,
%RM<imp-use>; VSLRC:%vreg9,%vreg17,%vreg19
...
We can eliminate the copy by changing from the A-type to the
M-type instruction. This means:
%vreg5<def,tied1> = XSMADDADP %vreg5<tied0>, %vreg17, %vreg16,
%RM<imp-use>; VSLRC:%vreg5,%vreg17,%vreg16
is replaced by:
%vreg16<def,tied1> = XSMADDMDP %vreg16<tied0>, %vreg18, %vreg9,
%RM<imp-use>; VSLRC:%vreg16,%vreg18,%vreg9
and we remove: %vreg5<def> = COPY %vreg9; VSLRC:%vreg5,%vreg9
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204768 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-25 23:29:21 +00:00
|
|
|
LIS = &getAnalysis<LiveIntervals>();
|
|
|
|
|
|
|
|
TII = TM->getInstrInfo();
|
|
|
|
|
|
|
|
bool Changed = false;
|
|
|
|
|
|
|
|
if (DisableVSXFMAMutate)
|
|
|
|
return Changed;
|
|
|
|
|
|
|
|
for (MachineFunction::iterator I = MF.begin(); I != MF.end();) {
|
|
|
|
MachineBasicBlock &B = *I++;
|
|
|
|
if (processBlock(B))
|
|
|
|
Changed = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Changed;
|
|
|
|
}
|
|
|
|
|
2014-04-29 07:57:37 +00:00
|
|
|
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
[PowerPC] Select between VSX A-type and M-type FMA instructions just before RA
The VSX instruction set has two types of FMA instructions: A-type (where the
addend is taken from the output register) and M-type (where one of the product
operands is taken from the output register). This adds a small pass that runs
just after MI scheduling (and, thus, just before register allocation) that
mutates A-type instructions (that are created during isel) into M-type
instructions when:
1. This will eliminate an otherwise-necessary copy of the addend
2. One of the product operands is killed by the instruction
The "right" moment to make this decision is in between scheduling and register
allocation, because only there do we know whether or not one of the product
operands is killed by any particular instruction. Unfortunately, this also
makes the implementation somewhat complicated, because the MIs are not in SSA
form and we need to preserve the LiveIntervals analysis.
As a simple example, if we have:
%vreg5<def> = COPY %vreg9; VSLRC:%vreg5,%vreg9
%vreg5<def,tied1> = XSMADDADP %vreg5<tied0>, %vreg17, %vreg16,
%RM<imp-use>; VSLRC:%vreg5,%vreg17,%vreg16
...
%vreg9<def,tied1> = XSMADDADP %vreg9<tied0>, %vreg17, %vreg19,
%RM<imp-use>; VSLRC:%vreg9,%vreg17,%vreg19
...
We can eliminate the copy by changing from the A-type to the
M-type instruction. This means:
%vreg5<def,tied1> = XSMADDADP %vreg5<tied0>, %vreg17, %vreg16,
%RM<imp-use>; VSLRC:%vreg5,%vreg17,%vreg16
is replaced by:
%vreg16<def,tied1> = XSMADDMDP %vreg16<tied0>, %vreg18, %vreg9,
%RM<imp-use>; VSLRC:%vreg16,%vreg18,%vreg9
and we remove: %vreg5<def> = COPY %vreg9; VSLRC:%vreg5,%vreg9
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204768 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-25 23:29:21 +00:00
|
|
|
AU.addRequired<LiveIntervals>();
|
|
|
|
AU.addPreserved<LiveIntervals>();
|
|
|
|
AU.addRequired<SlotIndexes>();
|
|
|
|
AU.addPreserved<SlotIndexes>();
|
|
|
|
MachineFunctionPass::getAnalysisUsage(AU);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
INITIALIZE_PASS_BEGIN(PPCVSXFMAMutate, DEBUG_TYPE,
|
|
|
|
"PowerPC VSX FMA Mutation", false, false)
|
|
|
|
INITIALIZE_PASS_DEPENDENCY(LiveIntervals)
|
|
|
|
INITIALIZE_PASS_DEPENDENCY(SlotIndexes)
|
|
|
|
INITIALIZE_PASS_END(PPCVSXFMAMutate, DEBUG_TYPE,
|
|
|
|
"PowerPC VSX FMA Mutation", false, false)
|
|
|
|
|
|
|
|
char &llvm::PPCVSXFMAMutateID = PPCVSXFMAMutate::ID;
|
|
|
|
|
|
|
|
char PPCVSXFMAMutate::ID = 0;
|
|
|
|
FunctionPass*
|
|
|
|
llvm::createPPCVSXFMAMutatePass() { return new PPCVSXFMAMutate(); }
|
[PowerPC] Initial support for the VSX instruction set
VSX is an ISA extension supported on the POWER7 and later cores that enhances
floating-point vector and scalar capabilities. Among other things, this adds
<2 x double> support and generally helps to reduce register pressure.
The interesting part of this ISA feature is the register configuration: there
are 64 new 128-bit vector registers, the 32 of which are super-registers of the
existing 32 scalar floating-point registers, and the second 32 of which overlap
with the 32 Altivec vector registers. This makes things like vector insertion
and extraction tricky: this can be free but only if we force a restriction to
the right register subclass when needed. A new "minipass" PPCVSXCopy takes care
of this (although it could do a more-optimal job of it; see the comment about
unnecessary copies below).
Please note that, currently, VSX is not enabled by default when targeting
anything because it is not yet ready for that. The assembler and disassembler
are fully implemented and tested. However:
- CodeGen support causes miscompiles; test-suite runtime failures:
MultiSource/Benchmarks/FreeBench/distray/distray
MultiSource/Benchmarks/McCat/08-main/main
MultiSource/Benchmarks/Olden/voronoi/voronoi
MultiSource/Benchmarks/mafft/pairlocalalign
MultiSource/Benchmarks/tramp3d-v4/tramp3d-v4
SingleSource/Benchmarks/CoyoteBench/almabench
SingleSource/Benchmarks/Misc/matmul_f64_4x4
- The lowering currently falls back to using Altivec instructions far more
than it should. Worse, there are some things that are scalarized through the
stack that shouldn't be.
- A lot of unnecessary copies make it past the optimizers, and this needs to
be fixed.
- Many more regression tests are needed.
Normally, I'd fix these things prior to committing, but there are some
students and other contributors who would like to work this, and so it makes
sense to move this development process upstream where it can be subject to the
regular code-review procedures.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203768 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-13 07:58:58 +00:00
|
|
|
|
|
|
|
#undef DEBUG_TYPE
|
|
|
|
#define DEBUG_TYPE "ppc-vsx-copy"
|
|
|
|
|
|
|
|
namespace llvm {
|
|
|
|
void initializePPCVSXCopyPass(PassRegistry&);
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
// PPCVSXCopy pass - For copies between VSX registers and non-VSX registers
|
|
|
|
// (Altivec and scalar floating-point registers), we need to transform the
|
|
|
|
// copies into subregister copies with other restrictions.
|
|
|
|
struct PPCVSXCopy : public MachineFunctionPass {
|
|
|
|
static char ID;
|
|
|
|
PPCVSXCopy() : MachineFunctionPass(ID) {
|
|
|
|
initializePPCVSXCopyPass(*PassRegistry::getPassRegistry());
|
|
|
|
}
|
|
|
|
|
|
|
|
const PPCTargetMachine *TM;
|
|
|
|
const PPCInstrInfo *TII;
|
|
|
|
|
|
|
|
bool IsRegInClass(unsigned Reg, const TargetRegisterClass *RC,
|
|
|
|
MachineRegisterInfo &MRI) {
|
|
|
|
if (TargetRegisterInfo::isVirtualRegister(Reg)) {
|
|
|
|
return RC->hasSubClassEq(MRI.getRegClass(Reg));
|
|
|
|
} else if (RC->contains(Reg)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsVSReg(unsigned Reg, MachineRegisterInfo &MRI) {
|
|
|
|
return IsRegInClass(Reg, &PPC::VSRCRegClass, MRI);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsVRReg(unsigned Reg, MachineRegisterInfo &MRI) {
|
|
|
|
return IsRegInClass(Reg, &PPC::VRRCRegClass, MRI);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsF8Reg(unsigned Reg, MachineRegisterInfo &MRI) {
|
|
|
|
return IsRegInClass(Reg, &PPC::F8RCRegClass, MRI);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
bool processBlock(MachineBasicBlock &MBB) {
|
|
|
|
bool Changed = false;
|
|
|
|
|
|
|
|
MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
|
|
|
|
for (MachineBasicBlock::iterator I = MBB.begin(), IE = MBB.end();
|
|
|
|
I != IE; ++I) {
|
|
|
|
MachineInstr *MI = I;
|
|
|
|
if (!MI->isFullCopy())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
MachineOperand &DstMO = MI->getOperand(0);
|
|
|
|
MachineOperand &SrcMO = MI->getOperand(1);
|
|
|
|
|
|
|
|
if ( IsVSReg(DstMO.getReg(), MRI) &&
|
|
|
|
!IsVSReg(SrcMO.getReg(), MRI)) {
|
|
|
|
// This is a copy *to* a VSX register from a non-VSX register.
|
|
|
|
Changed = true;
|
|
|
|
|
|
|
|
const TargetRegisterClass *SrcRC =
|
|
|
|
IsVRReg(SrcMO.getReg(), MRI) ? &PPC::VSHRCRegClass :
|
|
|
|
&PPC::VSLRCRegClass;
|
|
|
|
assert((IsF8Reg(SrcMO.getReg(), MRI) ||
|
|
|
|
IsVRReg(SrcMO.getReg(), MRI)) &&
|
|
|
|
"Unknown source for a VSX copy");
|
|
|
|
|
|
|
|
unsigned NewVReg = MRI.createVirtualRegister(SrcRC);
|
|
|
|
BuildMI(MBB, MI, MI->getDebugLoc(),
|
|
|
|
TII->get(TargetOpcode::SUBREG_TO_REG), NewVReg)
|
|
|
|
.addImm(1) // add 1, not 0, because there is no implicit clearing
|
|
|
|
// of the high bits.
|
|
|
|
.addOperand(SrcMO)
|
|
|
|
.addImm(IsVRReg(SrcMO.getReg(), MRI) ? PPC::sub_128 :
|
|
|
|
PPC::sub_64);
|
|
|
|
|
|
|
|
// The source of the original copy is now the new virtual register.
|
|
|
|
SrcMO.setReg(NewVReg);
|
|
|
|
} else if (!IsVSReg(DstMO.getReg(), MRI) &&
|
|
|
|
IsVSReg(SrcMO.getReg(), MRI)) {
|
|
|
|
// This is a copy *from* a VSX register to a non-VSX register.
|
|
|
|
Changed = true;
|
|
|
|
|
|
|
|
const TargetRegisterClass *DstRC =
|
|
|
|
IsVRReg(DstMO.getReg(), MRI) ? &PPC::VSHRCRegClass :
|
|
|
|
&PPC::VSLRCRegClass;
|
|
|
|
assert((IsF8Reg(DstMO.getReg(), MRI) ||
|
|
|
|
IsVRReg(DstMO.getReg(), MRI)) &&
|
|
|
|
"Unknown destination for a VSX copy");
|
|
|
|
|
|
|
|
// Copy the VSX value into a new VSX register of the correct subclass.
|
|
|
|
unsigned NewVReg = MRI.createVirtualRegister(DstRC);
|
|
|
|
BuildMI(MBB, MI, MI->getDebugLoc(),
|
|
|
|
TII->get(TargetOpcode::COPY), NewVReg)
|
|
|
|
.addOperand(SrcMO);
|
|
|
|
|
|
|
|
// Transform the original copy into a subregister extraction copy.
|
|
|
|
SrcMO.setReg(NewVReg);
|
|
|
|
SrcMO.setSubReg(IsVRReg(DstMO.getReg(), MRI) ? PPC::sub_128 :
|
|
|
|
PPC::sub_64);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return Changed;
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
2014-04-29 07:57:37 +00:00
|
|
|
bool runOnMachineFunction(MachineFunction &MF) override {
|
[PowerPC] Initial support for the VSX instruction set
VSX is an ISA extension supported on the POWER7 and later cores that enhances
floating-point vector and scalar capabilities. Among other things, this adds
<2 x double> support and generally helps to reduce register pressure.
The interesting part of this ISA feature is the register configuration: there
are 64 new 128-bit vector registers, the 32 of which are super-registers of the
existing 32 scalar floating-point registers, and the second 32 of which overlap
with the 32 Altivec vector registers. This makes things like vector insertion
and extraction tricky: this can be free but only if we force a restriction to
the right register subclass when needed. A new "minipass" PPCVSXCopy takes care
of this (although it could do a more-optimal job of it; see the comment about
unnecessary copies below).
Please note that, currently, VSX is not enabled by default when targeting
anything because it is not yet ready for that. The assembler and disassembler
are fully implemented and tested. However:
- CodeGen support causes miscompiles; test-suite runtime failures:
MultiSource/Benchmarks/FreeBench/distray/distray
MultiSource/Benchmarks/McCat/08-main/main
MultiSource/Benchmarks/Olden/voronoi/voronoi
MultiSource/Benchmarks/mafft/pairlocalalign
MultiSource/Benchmarks/tramp3d-v4/tramp3d-v4
SingleSource/Benchmarks/CoyoteBench/almabench
SingleSource/Benchmarks/Misc/matmul_f64_4x4
- The lowering currently falls back to using Altivec instructions far more
than it should. Worse, there are some things that are scalarized through the
stack that shouldn't be.
- A lot of unnecessary copies make it past the optimizers, and this needs to
be fixed.
- Many more regression tests are needed.
Normally, I'd fix these things prior to committing, but there are some
students and other contributors who would like to work this, and so it makes
sense to move this development process upstream where it can be subject to the
regular code-review procedures.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203768 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-13 07:58:58 +00:00
|
|
|
TM = static_cast<const PPCTargetMachine *>(&MF.getTarget());
|
2014-05-22 01:21:35 +00:00
|
|
|
// If we don't have VSX on the subtarget, don't do anything.
|
|
|
|
if (!TM->getSubtargetImpl()->hasVSX())
|
|
|
|
return false;
|
[PowerPC] Initial support for the VSX instruction set
VSX is an ISA extension supported on the POWER7 and later cores that enhances
floating-point vector and scalar capabilities. Among other things, this adds
<2 x double> support and generally helps to reduce register pressure.
The interesting part of this ISA feature is the register configuration: there
are 64 new 128-bit vector registers, the 32 of which are super-registers of the
existing 32 scalar floating-point registers, and the second 32 of which overlap
with the 32 Altivec vector registers. This makes things like vector insertion
and extraction tricky: this can be free but only if we force a restriction to
the right register subclass when needed. A new "minipass" PPCVSXCopy takes care
of this (although it could do a more-optimal job of it; see the comment about
unnecessary copies below).
Please note that, currently, VSX is not enabled by default when targeting
anything because it is not yet ready for that. The assembler and disassembler
are fully implemented and tested. However:
- CodeGen support causes miscompiles; test-suite runtime failures:
MultiSource/Benchmarks/FreeBench/distray/distray
MultiSource/Benchmarks/McCat/08-main/main
MultiSource/Benchmarks/Olden/voronoi/voronoi
MultiSource/Benchmarks/mafft/pairlocalalign
MultiSource/Benchmarks/tramp3d-v4/tramp3d-v4
SingleSource/Benchmarks/CoyoteBench/almabench
SingleSource/Benchmarks/Misc/matmul_f64_4x4
- The lowering currently falls back to using Altivec instructions far more
than it should. Worse, there are some things that are scalarized through the
stack that shouldn't be.
- A lot of unnecessary copies make it past the optimizers, and this needs to
be fixed.
- Many more regression tests are needed.
Normally, I'd fix these things prior to committing, but there are some
students and other contributors who would like to work this, and so it makes
sense to move this development process upstream where it can be subject to the
regular code-review procedures.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203768 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-13 07:58:58 +00:00
|
|
|
TII = TM->getInstrInfo();
|
|
|
|
|
|
|
|
bool Changed = false;
|
|
|
|
|
|
|
|
for (MachineFunction::iterator I = MF.begin(); I != MF.end();) {
|
|
|
|
MachineBasicBlock &B = *I++;
|
|
|
|
if (processBlock(B))
|
|
|
|
Changed = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Changed;
|
|
|
|
}
|
|
|
|
|
2014-04-29 07:57:37 +00:00
|
|
|
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
[PowerPC] Initial support for the VSX instruction set
VSX is an ISA extension supported on the POWER7 and later cores that enhances
floating-point vector and scalar capabilities. Among other things, this adds
<2 x double> support and generally helps to reduce register pressure.
The interesting part of this ISA feature is the register configuration: there
are 64 new 128-bit vector registers, the 32 of which are super-registers of the
existing 32 scalar floating-point registers, and the second 32 of which overlap
with the 32 Altivec vector registers. This makes things like vector insertion
and extraction tricky: this can be free but only if we force a restriction to
the right register subclass when needed. A new "minipass" PPCVSXCopy takes care
of this (although it could do a more-optimal job of it; see the comment about
unnecessary copies below).
Please note that, currently, VSX is not enabled by default when targeting
anything because it is not yet ready for that. The assembler and disassembler
are fully implemented and tested. However:
- CodeGen support causes miscompiles; test-suite runtime failures:
MultiSource/Benchmarks/FreeBench/distray/distray
MultiSource/Benchmarks/McCat/08-main/main
MultiSource/Benchmarks/Olden/voronoi/voronoi
MultiSource/Benchmarks/mafft/pairlocalalign
MultiSource/Benchmarks/tramp3d-v4/tramp3d-v4
SingleSource/Benchmarks/CoyoteBench/almabench
SingleSource/Benchmarks/Misc/matmul_f64_4x4
- The lowering currently falls back to using Altivec instructions far more
than it should. Worse, there are some things that are scalarized through the
stack that shouldn't be.
- A lot of unnecessary copies make it past the optimizers, and this needs to
be fixed.
- Many more regression tests are needed.
Normally, I'd fix these things prior to committing, but there are some
students and other contributors who would like to work this, and so it makes
sense to move this development process upstream where it can be subject to the
regular code-review procedures.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203768 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-13 07:58:58 +00:00
|
|
|
MachineFunctionPass::getAnalysisUsage(AU);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
INITIALIZE_PASS(PPCVSXCopy, DEBUG_TYPE,
|
|
|
|
"PowerPC VSX Copy Legalization", false, false)
|
|
|
|
|
|
|
|
char PPCVSXCopy::ID = 0;
|
|
|
|
FunctionPass*
|
|
|
|
llvm::createPPCVSXCopyPass() { return new PPCVSXCopy(); }
|
|
|
|
|
2014-03-27 23:12:31 +00:00
|
|
|
#undef DEBUG_TYPE
|
|
|
|
#define DEBUG_TYPE "ppc-vsx-copy-cleanup"
|
|
|
|
|
|
|
|
namespace llvm {
|
|
|
|
void initializePPCVSXCopyCleanupPass(PassRegistry&);
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
// PPCVSXCopyCleanup pass - We sometimes end up generating self copies of VSX
|
|
|
|
// registers (mostly because the ABI code still places all values into the
|
|
|
|
// "traditional" floating-point and vector registers). Remove them here.
|
|
|
|
struct PPCVSXCopyCleanup : public MachineFunctionPass {
|
|
|
|
static char ID;
|
|
|
|
PPCVSXCopyCleanup() : MachineFunctionPass(ID) {
|
|
|
|
initializePPCVSXCopyCleanupPass(*PassRegistry::getPassRegistry());
|
|
|
|
}
|
|
|
|
|
|
|
|
const PPCTargetMachine *TM;
|
|
|
|
const PPCInstrInfo *TII;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
bool processBlock(MachineBasicBlock &MBB) {
|
|
|
|
bool Changed = false;
|
|
|
|
|
|
|
|
SmallVector<MachineInstr *, 4> ToDelete;
|
|
|
|
for (MachineBasicBlock::iterator I = MBB.begin(), IE = MBB.end();
|
|
|
|
I != IE; ++I) {
|
|
|
|
MachineInstr *MI = I;
|
|
|
|
if (MI->getOpcode() == PPC::XXLOR &&
|
|
|
|
MI->getOperand(0).getReg() == MI->getOperand(1).getReg() &&
|
|
|
|
MI->getOperand(0).getReg() == MI->getOperand(2).getReg())
|
|
|
|
ToDelete.push_back(MI);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ToDelete.empty())
|
|
|
|
Changed = true;
|
|
|
|
|
|
|
|
for (unsigned i = 0, ie = ToDelete.size(); i != ie; ++i) {
|
|
|
|
DEBUG(dbgs() << "Removing VSX self-copy: " << *ToDelete[i]);
|
|
|
|
ToDelete[i]->eraseFromParent();
|
|
|
|
}
|
|
|
|
|
|
|
|
return Changed;
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
2014-04-29 07:57:37 +00:00
|
|
|
bool runOnMachineFunction(MachineFunction &MF) override {
|
2014-03-27 23:12:31 +00:00
|
|
|
TM = static_cast<const PPCTargetMachine *>(&MF.getTarget());
|
2014-05-22 01:21:35 +00:00
|
|
|
// If we don't have VSX don't bother doing anything here.
|
|
|
|
if (!TM->getSubtargetImpl()->hasVSX())
|
|
|
|
return false;
|
2014-03-27 23:12:31 +00:00
|
|
|
TII = TM->getInstrInfo();
|
|
|
|
|
|
|
|
bool Changed = false;
|
|
|
|
|
|
|
|
for (MachineFunction::iterator I = MF.begin(); I != MF.end();) {
|
|
|
|
MachineBasicBlock &B = *I++;
|
|
|
|
if (processBlock(B))
|
|
|
|
Changed = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Changed;
|
|
|
|
}
|
|
|
|
|
2014-04-29 07:57:37 +00:00
|
|
|
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
2014-03-27 23:12:31 +00:00
|
|
|
MachineFunctionPass::getAnalysisUsage(AU);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
INITIALIZE_PASS(PPCVSXCopyCleanup, DEBUG_TYPE,
|
|
|
|
"PowerPC VSX Copy Cleanup", false, false)
|
|
|
|
|
|
|
|
char PPCVSXCopyCleanup::ID = 0;
|
|
|
|
FunctionPass*
|
|
|
|
llvm::createPPCVSXCopyCleanupPass() { return new PPCVSXCopyCleanup(); }
|
|
|
|
|
2013-04-08 16:24:03 +00:00
|
|
|
#undef DEBUG_TYPE
|
|
|
|
#define DEBUG_TYPE "ppc-early-ret"
|
|
|
|
STATISTIC(NumBCLR, "Number of early conditional returns");
|
|
|
|
STATISTIC(NumBLR, "Number of early returns");
|
|
|
|
|
|
|
|
namespace llvm {
|
|
|
|
void initializePPCEarlyReturnPass(PassRegistry&);
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
// PPCEarlyReturn pass - For simple functions without epilogue code, move
|
|
|
|
// returns up, and create conditional returns, to avoid unnecessary
|
|
|
|
// branch-to-blr sequences.
|
|
|
|
struct PPCEarlyReturn : public MachineFunctionPass {
|
|
|
|
static char ID;
|
|
|
|
PPCEarlyReturn() : MachineFunctionPass(ID) {
|
|
|
|
initializePPCEarlyReturnPass(*PassRegistry::getPassRegistry());
|
|
|
|
}
|
|
|
|
|
|
|
|
const PPCTargetMachine *TM;
|
|
|
|
const PPCInstrInfo *TII;
|
|
|
|
|
|
|
|
protected:
|
2013-04-09 18:25:18 +00:00
|
|
|
bool processBlock(MachineBasicBlock &ReturnMBB) {
|
2013-04-08 16:24:03 +00:00
|
|
|
bool Changed = false;
|
|
|
|
|
2013-04-09 18:25:18 +00:00
|
|
|
MachineBasicBlock::iterator I = ReturnMBB.begin();
|
|
|
|
I = ReturnMBB.SkipPHIsAndLabels(I);
|
2013-04-08 16:24:03 +00:00
|
|
|
|
|
|
|
// The block must be essentially empty except for the blr.
|
2013-04-09 18:25:18 +00:00
|
|
|
if (I == ReturnMBB.end() || I->getOpcode() != PPC::BLR ||
|
|
|
|
I != ReturnMBB.getLastNonDebugInstr())
|
2013-04-08 16:24:03 +00:00
|
|
|
return Changed;
|
|
|
|
|
|
|
|
SmallVector<MachineBasicBlock*, 8> PredToRemove;
|
2013-04-09 18:25:18 +00:00
|
|
|
for (MachineBasicBlock::pred_iterator PI = ReturnMBB.pred_begin(),
|
|
|
|
PIE = ReturnMBB.pred_end(); PI != PIE; ++PI) {
|
2013-04-08 16:24:03 +00:00
|
|
|
bool OtherReference = false, BlockChanged = false;
|
2013-04-09 18:25:18 +00:00
|
|
|
for (MachineBasicBlock::iterator J = (*PI)->getLastNonDebugInstr();;) {
|
2013-04-08 16:24:03 +00:00
|
|
|
if (J->getOpcode() == PPC::B) {
|
2013-04-09 18:25:18 +00:00
|
|
|
if (J->getOperand(0).getMBB() == &ReturnMBB) {
|
2013-04-08 16:24:03 +00:00
|
|
|
// This is an unconditional branch to the return. Replace the
|
2013-12-17 04:50:40 +00:00
|
|
|
// branch with a blr.
|
2013-04-08 16:24:03 +00:00
|
|
|
BuildMI(**PI, J, J->getDebugLoc(), TII->get(PPC::BLR));
|
2013-04-09 18:25:18 +00:00
|
|
|
MachineBasicBlock::iterator K = J--;
|
2013-04-08 16:24:03 +00:00
|
|
|
K->eraseFromParent();
|
|
|
|
BlockChanged = true;
|
|
|
|
++NumBLR;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
} else if (J->getOpcode() == PPC::BCC) {
|
2013-04-09 18:25:18 +00:00
|
|
|
if (J->getOperand(2).getMBB() == &ReturnMBB) {
|
2013-04-08 16:24:03 +00:00
|
|
|
// This is a conditional branch to the return. Replace the branch
|
|
|
|
// with a bclr.
|
Add CR-bit tracking to the PowerPC backend for i1 values
This change enables tracking i1 values in the PowerPC backend using the
condition register bits. These bits can be treated on PowerPC as separate
registers; individual bit operations (and, or, xor, etc.) are supported.
Tracking booleans in CR bits has several advantages:
- Reduction in register pressure (because we no longer need GPRs to store
boolean values).
- Logical operations on booleans can be handled more efficiently; we used to
have to move all results from comparisons into GPRs, perform promoted
logical operations in GPRs, and then move the result back into condition
register bits to be used by conditional branches. This can be very
inefficient, because the throughput of these CR <-> GPR moves have high
latency and low throughput (especially when other associated instructions
are accounted for).
- On the POWER7 and similar cores, we can increase total throughput by using
the CR bits. CR bit operations have a dedicated functional unit.
Most of this is more-or-less mechanical: Adjustments were needed in the
calling-convention code, support was added for spilling/restoring individual
condition-register bits, and conditional branch instruction definitions taking
specific CR bits were added (plus patterns and code for generating bit-level
operations).
This is enabled by default when running at -O2 and higher. For -O0 and -O1,
where the ability to debug is more important, this feature is disabled by
default. Individual CR bits do not have assigned DWARF register numbers,
and storing values in CR bits makes them invisible to the debugger.
It is critical, however, that we don't move i1 values that have been promoted
to larger values (such as those passed as function arguments) into bit
registers only to quickly turn around and move the values back into GPRs (such
as happens when values are returned by functions). A pair of target-specific
DAG combines are added to remove the trunc/extends in:
trunc(binary-ops(binary-ops(zext(x), zext(y)), ...)
and:
zext(binary-ops(binary-ops(trunc(x), trunc(y)), ...)
In short, we only want to use CR bits where some of the i1 values come from
comparisons or are used by conditional branches or selects. To put it another
way, if we can do the entire i1 computation in GPRs, then we probably should
(on the POWER7, the GPR-operation throughput is higher, and for all cores, the
CR <-> GPR moves are expensive).
POWER7 test-suite performance results (from 10 runs in each configuration):
SingleSource/Benchmarks/Misc/mandel-2: 35% speedup
MultiSource/Benchmarks/Prolangs-C++/city/city: 21% speedup
MultiSource/Benchmarks/MiBench/automotive-susan: 23% speedup
SingleSource/Benchmarks/CoyoteBench/huffbench: 13% speedup
SingleSource/Benchmarks/Misc-C++/Large/sphereflake: 13% speedup
SingleSource/Benchmarks/Misc-C++/mandel-text: 10% speedup
SingleSource/Benchmarks/Misc-C++-EH/spirit: 10% slowdown
MultiSource/Applications/lemon/lemon: 8% slowdown
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202451 91177308-0d34-0410-b5e6-96231b3b80d8
2014-02-28 00:27:01 +00:00
|
|
|
BuildMI(**PI, J, J->getDebugLoc(), TII->get(PPC::BCCLR))
|
2013-04-08 16:24:03 +00:00
|
|
|
.addImm(J->getOperand(0).getImm())
|
|
|
|
.addReg(J->getOperand(1).getReg());
|
2013-04-09 18:25:18 +00:00
|
|
|
MachineBasicBlock::iterator K = J--;
|
2013-04-08 16:24:03 +00:00
|
|
|
K->eraseFromParent();
|
|
|
|
BlockChanged = true;
|
|
|
|
++NumBCLR;
|
|
|
|
continue;
|
|
|
|
}
|
Add CR-bit tracking to the PowerPC backend for i1 values
This change enables tracking i1 values in the PowerPC backend using the
condition register bits. These bits can be treated on PowerPC as separate
registers; individual bit operations (and, or, xor, etc.) are supported.
Tracking booleans in CR bits has several advantages:
- Reduction in register pressure (because we no longer need GPRs to store
boolean values).
- Logical operations on booleans can be handled more efficiently; we used to
have to move all results from comparisons into GPRs, perform promoted
logical operations in GPRs, and then move the result back into condition
register bits to be used by conditional branches. This can be very
inefficient, because the throughput of these CR <-> GPR moves have high
latency and low throughput (especially when other associated instructions
are accounted for).
- On the POWER7 and similar cores, we can increase total throughput by using
the CR bits. CR bit operations have a dedicated functional unit.
Most of this is more-or-less mechanical: Adjustments were needed in the
calling-convention code, support was added for spilling/restoring individual
condition-register bits, and conditional branch instruction definitions taking
specific CR bits were added (plus patterns and code for generating bit-level
operations).
This is enabled by default when running at -O2 and higher. For -O0 and -O1,
where the ability to debug is more important, this feature is disabled by
default. Individual CR bits do not have assigned DWARF register numbers,
and storing values in CR bits makes them invisible to the debugger.
It is critical, however, that we don't move i1 values that have been promoted
to larger values (such as those passed as function arguments) into bit
registers only to quickly turn around and move the values back into GPRs (such
as happens when values are returned by functions). A pair of target-specific
DAG combines are added to remove the trunc/extends in:
trunc(binary-ops(binary-ops(zext(x), zext(y)), ...)
and:
zext(binary-ops(binary-ops(trunc(x), trunc(y)), ...)
In short, we only want to use CR bits where some of the i1 values come from
comparisons or are used by conditional branches or selects. To put it another
way, if we can do the entire i1 computation in GPRs, then we probably should
(on the POWER7, the GPR-operation throughput is higher, and for all cores, the
CR <-> GPR moves are expensive).
POWER7 test-suite performance results (from 10 runs in each configuration):
SingleSource/Benchmarks/Misc/mandel-2: 35% speedup
MultiSource/Benchmarks/Prolangs-C++/city/city: 21% speedup
MultiSource/Benchmarks/MiBench/automotive-susan: 23% speedup
SingleSource/Benchmarks/CoyoteBench/huffbench: 13% speedup
SingleSource/Benchmarks/Misc-C++/Large/sphereflake: 13% speedup
SingleSource/Benchmarks/Misc-C++/mandel-text: 10% speedup
SingleSource/Benchmarks/Misc-C++-EH/spirit: 10% slowdown
MultiSource/Applications/lemon/lemon: 8% slowdown
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202451 91177308-0d34-0410-b5e6-96231b3b80d8
2014-02-28 00:27:01 +00:00
|
|
|
} else if (J->getOpcode() == PPC::BC || J->getOpcode() == PPC::BCn) {
|
|
|
|
if (J->getOperand(1).getMBB() == &ReturnMBB) {
|
|
|
|
// This is a conditional branch to the return. Replace the branch
|
|
|
|
// with a bclr.
|
|
|
|
BuildMI(**PI, J, J->getDebugLoc(),
|
|
|
|
TII->get(J->getOpcode() == PPC::BC ?
|
|
|
|
PPC::BCLR : PPC::BCLRn))
|
|
|
|
.addReg(J->getOperand(0).getReg());
|
|
|
|
MachineBasicBlock::iterator K = J--;
|
|
|
|
K->eraseFromParent();
|
|
|
|
BlockChanged = true;
|
|
|
|
++NumBCLR;
|
|
|
|
continue;
|
|
|
|
}
|
2013-04-08 16:24:03 +00:00
|
|
|
} else if (J->isBranch()) {
|
|
|
|
if (J->isIndirectBranch()) {
|
2013-04-09 18:25:18 +00:00
|
|
|
if (ReturnMBB.hasAddressTaken())
|
2013-04-08 16:24:03 +00:00
|
|
|
OtherReference = true;
|
|
|
|
} else
|
|
|
|
for (unsigned i = 0; i < J->getNumOperands(); ++i)
|
|
|
|
if (J->getOperand(i).isMBB() &&
|
2013-04-09 18:25:18 +00:00
|
|
|
J->getOperand(i).getMBB() == &ReturnMBB)
|
2013-04-08 16:24:03 +00:00
|
|
|
OtherReference = true;
|
2013-04-09 18:25:18 +00:00
|
|
|
} else if (!J->isTerminator() && !J->isDebugValue())
|
|
|
|
break;
|
2013-04-08 16:24:03 +00:00
|
|
|
|
2013-04-09 18:25:18 +00:00
|
|
|
if (J == (*PI)->begin())
|
|
|
|
break;
|
|
|
|
|
|
|
|
--J;
|
2013-04-08 16:24:03 +00:00
|
|
|
}
|
|
|
|
|
2013-04-09 18:25:18 +00:00
|
|
|
if ((*PI)->canFallThrough() && (*PI)->isLayoutSuccessor(&ReturnMBB))
|
2013-04-08 16:24:03 +00:00
|
|
|
OtherReference = true;
|
|
|
|
|
2013-12-17 04:50:40 +00:00
|
|
|
// Predecessors are stored in a vector and can't be removed here.
|
2013-04-08 16:24:03 +00:00
|
|
|
if (!OtherReference && BlockChanged) {
|
|
|
|
PredToRemove.push_back(*PI);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (BlockChanged)
|
|
|
|
Changed = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (unsigned i = 0, ie = PredToRemove.size(); i != ie; ++i)
|
2013-04-09 18:25:18 +00:00
|
|
|
PredToRemove[i]->removeSuccessor(&ReturnMBB);
|
2013-04-08 16:24:03 +00:00
|
|
|
|
2013-04-09 18:25:18 +00:00
|
|
|
if (Changed && !ReturnMBB.hasAddressTaken()) {
|
2013-04-08 16:24:03 +00:00
|
|
|
// We now might be able to merge this blr-only block into its
|
|
|
|
// by-layout predecessor.
|
2013-04-09 18:25:18 +00:00
|
|
|
if (ReturnMBB.pred_size() == 1 &&
|
|
|
|
(*ReturnMBB.pred_begin())->isLayoutSuccessor(&ReturnMBB)) {
|
2013-04-08 16:24:03 +00:00
|
|
|
// Move the blr into the preceding block.
|
2013-04-09 18:25:18 +00:00
|
|
|
MachineBasicBlock &PrevMBB = **ReturnMBB.pred_begin();
|
|
|
|
PrevMBB.splice(PrevMBB.end(), &ReturnMBB, I);
|
|
|
|
PrevMBB.removeSuccessor(&ReturnMBB);
|
2013-04-08 16:24:03 +00:00
|
|
|
}
|
|
|
|
|
2013-04-09 18:25:18 +00:00
|
|
|
if (ReturnMBB.pred_empty())
|
|
|
|
ReturnMBB.eraseFromParent();
|
2013-04-08 16:24:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return Changed;
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
2014-04-29 07:57:37 +00:00
|
|
|
bool runOnMachineFunction(MachineFunction &MF) override {
|
2013-04-08 16:24:03 +00:00
|
|
|
TM = static_cast<const PPCTargetMachine *>(&MF.getTarget());
|
|
|
|
TII = TM->getInstrInfo();
|
|
|
|
|
|
|
|
bool Changed = false;
|
|
|
|
|
2013-04-09 18:25:18 +00:00
|
|
|
// If the function does not have at least two blocks, then there is
|
2013-04-08 16:24:03 +00:00
|
|
|
// nothing to do.
|
|
|
|
if (MF.size() < 2)
|
|
|
|
return Changed;
|
|
|
|
|
|
|
|
for (MachineFunction::iterator I = MF.begin(); I != MF.end();) {
|
2013-12-17 04:50:40 +00:00
|
|
|
MachineBasicBlock &B = *I++;
|
2013-04-08 16:24:03 +00:00
|
|
|
if (processBlock(B))
|
|
|
|
Changed = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Changed;
|
|
|
|
}
|
|
|
|
|
2014-04-29 07:57:37 +00:00
|
|
|
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
2013-04-08 16:24:03 +00:00
|
|
|
MachineFunctionPass::getAnalysisUsage(AU);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
INITIALIZE_PASS(PPCEarlyReturn, DEBUG_TYPE,
|
|
|
|
"PowerPC Early-Return Creation", false, false)
|
|
|
|
|
|
|
|
char PPCEarlyReturn::ID = 0;
|
|
|
|
FunctionPass*
|
|
|
|
llvm::createPPCEarlyReturnPass() { return new PPCEarlyReturn(); }
|