Skip to content

Commit

Permalink
[SystemZ] Improve use of conditional instructions
Browse files Browse the repository at this point in the history
This patch moves formation of LOC-type instructions from (late)
IfConversion to the early if-conversion pass, and in some cases
additionally creates them directly from select instructions
during DAG instruction selection.

To make early if-conversion work, the patch implements the
canInsertSelect / insertSelect callbacks.  It also implements
the commuteInstructionImpl and FoldImmediate callbacks to
enable generation of the full range of LOC instructions.

Finally, the patch adds support for all instructions of the
load-store-on-condition-2 facility, which allows using LOC
instructions also for high registers.

Due to the use of the GRX32 register class to enable high registers,
we now also have to handle the cases where there are still no single
hardware instructions (conditional move from a low register to a high
register or vice versa).  These are converted back to a branch sequence
after register allocation.  Since the expandRAPseudos callback is not
allowed to create new basic blocks, this requires a simple new pass,
modelled after the ARM/AArch64 ExpandPseudos pass.

Overall, this patch causes significantly more LOC-type instructions
to be used, and results in a measurable performance improvement.

llvm-svn: 288028
  • Loading branch information
uweigand committed Nov 28, 2016
1 parent 79724fc commit 524f276
Show file tree
Hide file tree
Showing 26 changed files with 1,803 additions and 171 deletions.
1 change: 1 addition & 0 deletions llvm/lib/Target/SystemZ/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ add_llvm_target(SystemZCodeGen
SystemZCallingConv.cpp
SystemZConstantPoolValue.cpp
SystemZElimCompare.cpp
SystemZExpandPseudo.cpp
SystemZFrameLowering.cpp
SystemZHazardRecognizer.cpp
SystemZISelDAGToDAG.cpp
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/SystemZ/SystemZ.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ static inline bool isImmHF(uint64_t Val) {
FunctionPass *createSystemZISelDag(SystemZTargetMachine &TM,
CodeGenOpt::Level OptLevel);
FunctionPass *createSystemZElimComparePass(SystemZTargetMachine &TM);
FunctionPass *createSystemZExpandPseudoPass(SystemZTargetMachine &TM);
FunctionPass *createSystemZShortenInstPass(SystemZTargetMachine &TM);
FunctionPass *createSystemZLongBranchPass(SystemZTargetMachine &TM);
FunctionPass *createSystemZLDCleanupPass(SystemZTargetMachine &TM);
Expand Down
153 changes: 153 additions & 0 deletions llvm/lib/Target/SystemZ/SystemZExpandPseudo.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
//==-- SystemZExpandPseudo.cpp - Expand pseudo instructions -------*- C++ -*-=//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains a pass that expands pseudo instructions into target
// instructions to allow proper scheduling and other late optimizations. This
// pass should be run after register allocation but before the post-regalloc
// scheduling pass.
//
//===----------------------------------------------------------------------===//

#include "SystemZ.h"
#include "SystemZInstrInfo.h"
#include "SystemZSubtarget.h"
#include "llvm/CodeGen/LivePhysRegs.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
using namespace llvm;

#define SYSTEMZ_EXPAND_PSEUDO_NAME "SystemZ pseudo instruction expansion pass"

namespace llvm {
void initializeSystemZExpandPseudoPass(PassRegistry&);
}

namespace {
class SystemZExpandPseudo : public MachineFunctionPass {
public:
static char ID;
SystemZExpandPseudo() : MachineFunctionPass(ID) {
initializeSystemZExpandPseudoPass(*PassRegistry::getPassRegistry());
}

const SystemZInstrInfo *TII;

bool runOnMachineFunction(MachineFunction &Fn) override;

StringRef getPassName() const override { return SYSTEMZ_EXPAND_PSEUDO_NAME; }

private:
bool expandMBB(MachineBasicBlock &MBB);
bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
MachineBasicBlock::iterator &NextMBBI);
bool expandLOCRMux(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
MachineBasicBlock::iterator &NextMBBI);
};
char SystemZExpandPseudo::ID = 0;
}

INITIALIZE_PASS(SystemZExpandPseudo, "systemz-expand-pseudo",
SYSTEMZ_EXPAND_PSEUDO_NAME, false, false)

/// \brief Returns an instance of the pseudo instruction expansion pass.
FunctionPass *llvm::createSystemZExpandPseudoPass(SystemZTargetMachine &TM) {
return new SystemZExpandPseudo();
}

// MI is a load-register-on-condition pseudo instruction that could not be
// handled as a single hardware instruction. Replace it by a branch sequence.
bool SystemZExpandPseudo::expandLOCRMux(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
MachineBasicBlock::iterator &NextMBBI) {
MachineFunction &MF = *MBB.getParent();
const BasicBlock *BB = MBB.getBasicBlock();
MachineInstr &MI = *MBBI;
DebugLoc DL = MI.getDebugLoc();
unsigned DestReg = MI.getOperand(0).getReg();
unsigned SrcReg = MI.getOperand(2).getReg();
unsigned CCValid = MI.getOperand(3).getImm();
unsigned CCMask = MI.getOperand(4).getImm();

LivePhysRegs LiveRegs(&TII->getRegisterInfo());
LiveRegs.addLiveOuts(MBB);
for (auto I = std::prev(MBB.end()); I != MBBI; --I)
LiveRegs.stepBackward(*I);

// Splice MBB at MI, moving the rest of the block into RestMBB.
MachineBasicBlock *RestMBB = MF.CreateMachineBasicBlock(BB);
MF.insert(std::next(MachineFunction::iterator(MBB)), RestMBB);
RestMBB->splice(RestMBB->begin(), &MBB, MI, MBB.end());
RestMBB->transferSuccessors(&MBB);
for (auto I = LiveRegs.begin(); I != LiveRegs.end(); ++I)
RestMBB->addLiveIn(*I);

// Create a new block MoveMBB to hold the move instruction.
MachineBasicBlock *MoveMBB = MF.CreateMachineBasicBlock(BB);
MF.insert(std::next(MachineFunction::iterator(MBB)), MoveMBB);
MoveMBB->addLiveIn(SrcReg);
for (auto I = LiveRegs.begin(); I != LiveRegs.end(); ++I)
MoveMBB->addLiveIn(*I);

// At the end of MBB, create a conditional branch to RestMBB if the
// condition is false, otherwise fall through to MoveMBB.
BuildMI(&MBB, DL, TII->get(SystemZ::BRC))
.addImm(CCValid).addImm(CCMask ^ CCValid).addMBB(RestMBB);
MBB.addSuccessor(RestMBB);
MBB.addSuccessor(MoveMBB);

// In MoveMBB, emit an instruction to move SrcReg into DestReg,
// then fall through to RestMBB.
TII->copyPhysReg(*MoveMBB, MoveMBB->end(), DL, DestReg, SrcReg,
MI.getOperand(2).isKill());
MoveMBB->addSuccessor(RestMBB);

NextMBBI = MBB.end();
MI.eraseFromParent();
return true;
}

/// \brief If MBBI references a pseudo instruction that should be expanded here,
/// do the expansion and return true. Otherwise return false.
bool SystemZExpandPseudo::expandMI(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
MachineBasicBlock::iterator &NextMBBI) {
MachineInstr &MI = *MBBI;
switch (MI.getOpcode()) {
case SystemZ::LOCRMux:
return expandLOCRMux(MBB, MBBI, NextMBBI);
default:
break;
}
return false;
}

/// \brief Iterate over the instructions in basic block MBB and expand any
/// pseudo instructions. Return true if anything was modified.
bool SystemZExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
bool Modified = false;

MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
while (MBBI != E) {
MachineBasicBlock::iterator NMBBI = std::next(MBBI);
Modified |= expandMI(MBB, MBBI, NMBBI);
MBBI = NMBBI;
}

return Modified;
}

bool SystemZExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
TII = static_cast<const SystemZInstrInfo *>(MF.getSubtarget().getInstrInfo());

bool Modified = false;
for (auto &MBB : MF)
Modified |= expandMBB(MBB);
return Modified;
}

10 changes: 8 additions & 2 deletions llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1296,8 +1296,14 @@ void SystemZDAGToDAGISel::Select(SDNode *Node) {
SDValue Op0 = Node->getOperand(0);
SDValue Op1 = Node->getOperand(1);
// Prefer to put any load first, so that it can be matched as a
// conditional load.
if (Op1.getOpcode() == ISD::LOAD && Op0.getOpcode() != ISD::LOAD) {
// conditional load. Likewise for constants in range for LOCHI.
if ((Op1.getOpcode() == ISD::LOAD && Op0.getOpcode() != ISD::LOAD) ||
(Subtarget->hasLoadStoreOnCond2() &&
Node->getValueType(0).isInteger() &&
Op1.getOpcode() == ISD::Constant &&
isInt<16>(cast<ConstantSDNode>(Op1)->getSExtValue()) &&
!(Op0.getOpcode() == ISD::Constant &&
isInt<16>(cast<ConstantSDNode>(Op0)->getSExtValue())))) {
SDValue CCValid = Node->getOperand(2);
SDValue CCMask = Node->getOperand(3);
uint64_t ConstCCValid =
Expand Down
24 changes: 21 additions & 3 deletions llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5224,7 +5224,8 @@ static unsigned forceReg(MachineInstr &MI, MachineOperand &Base,
// Implement EmitInstrWithCustomInserter for pseudo Select* instruction MI.
MachineBasicBlock *
SystemZTargetLowering::emitSelect(MachineInstr &MI,
MachineBasicBlock *MBB) const {
MachineBasicBlock *MBB,
unsigned LOCROpcode) const {
const SystemZInstrInfo *TII =
static_cast<const SystemZInstrInfo *>(Subtarget.getInstrInfo());

Expand All @@ -5235,6 +5236,15 @@ SystemZTargetLowering::emitSelect(MachineInstr &MI,
unsigned CCMask = MI.getOperand(4).getImm();
DebugLoc DL = MI.getDebugLoc();

// Use LOCROpcode if possible.
if (LOCROpcode && Subtarget.hasLoadStoreOnCond()) {
BuildMI(*MBB, MI, DL, TII->get(LOCROpcode), DestReg)
.addReg(FalseReg).addReg(TrueReg)
.addImm(CCValid).addImm(CCMask);
MI.eraseFromParent();
return MBB;
}

MachineBasicBlock *StartMBB = MBB;
MachineBasicBlock *JoinMBB = splitBlockBefore(MI, MBB);
MachineBasicBlock *FalseMBB = emitBlockAfter(StartMBB);
Expand Down Expand Up @@ -6020,12 +6030,16 @@ MachineBasicBlock *SystemZTargetLowering::EmitInstrWithCustomInserter(
MachineInstr &MI, MachineBasicBlock *MBB) const {
switch (MI.getOpcode()) {
case SystemZ::Select32Mux:
return emitSelect(MI, MBB,
Subtarget.hasLoadStoreOnCond2()? SystemZ::LOCRMux : 0);
case SystemZ::Select32:
case SystemZ::SelectF32:
return emitSelect(MI, MBB, SystemZ::LOCR);
case SystemZ::Select64:
return emitSelect(MI, MBB, SystemZ::LOCGR);
case SystemZ::SelectF32:
case SystemZ::SelectF64:
case SystemZ::SelectF128:
return emitSelect(MI, MBB);
return emitSelect(MI, MBB, 0);

case SystemZ::CondStore8Mux:
return emitCondStore(MI, MBB, SystemZ::STCMux, 0, false);
Expand All @@ -6035,6 +6049,10 @@ MachineBasicBlock *SystemZTargetLowering::EmitInstrWithCustomInserter(
return emitCondStore(MI, MBB, SystemZ::STHMux, 0, false);
case SystemZ::CondStore16MuxInv:
return emitCondStore(MI, MBB, SystemZ::STHMux, 0, true);
case SystemZ::CondStore32Mux:
return emitCondStore(MI, MBB, SystemZ::STMux, SystemZ::STOCMux, false);
case SystemZ::CondStore32MuxInv:
return emitCondStore(MI, MBB, SystemZ::STMux, SystemZ::STOCMux, true);
case SystemZ::CondStore8:
return emitCondStore(MI, MBB, SystemZ::STC, 0, false);
case SystemZ::CondStore8Inv:
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/Target/SystemZ/SystemZISelLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -561,7 +561,8 @@ class SystemZTargetLowering : public TargetLowering {
MachineBasicBlock *Target) const;

// Implement EmitInstrWithCustomInserter for individual operation types.
MachineBasicBlock *emitSelect(MachineInstr &MI, MachineBasicBlock *BB) const;
MachineBasicBlock *emitSelect(MachineInstr &MI, MachineBasicBlock *BB,
unsigned LOCROpcode) const;
MachineBasicBlock *emitCondStore(MachineInstr &MI, MachineBasicBlock *BB,
unsigned StoreOpcode, unsigned STOCOpcode,
bool Invert) const;
Expand Down
Loading

0 comments on commit 524f276

Please sign in to comment.