Index: lib/Target/PowerPC/CMakeLists.txt =================================================================== --- lib/Target/PowerPC/CMakeLists.txt +++ lib/Target/PowerPC/CMakeLists.txt @@ -40,6 +40,7 @@ PPCVSXCopy.cpp PPCVSXFMAMutate.cpp PPCVSXSwapRemoval.cpp + PPCExpandISEL.cpp ) add_subdirectory(AsmParser) Index: lib/Target/PowerPC/PPC.h =================================================================== --- lib/Target/PowerPC/PPC.h +++ lib/Target/PowerPC/PPC.h @@ -45,6 +45,7 @@ FunctionPass *createPPCISelDag(PPCTargetMachine &TM); FunctionPass *createPPCTLSDynamicCallPass(); FunctionPass *createPPCBoolRetToIntPass(); + FunctionPass *createPPCExpandISELPass(); void LowerPPCMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, AsmPrinter &AP, bool isDarwin); Index: lib/Target/PowerPC/PPCExpandISEL.cpp =================================================================== --- /dev/null +++ lib/Target/PowerPC/PPCExpandISEL.cpp @@ -0,0 +1,455 @@ +//===------------- PPCExpandISEL.cpp - Expand ISEL instruction ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// A pass that expands the ISEL instruction into an if-then-else sequence +// +//===----------------------------------------------------------------------===// + +#include "PPC.h" +#include "PPCInstrInfo.h" +#include "PPCSubtarget.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +#define DEBUG_TYPE "ppc-expand-isel" + +STATISTIC(NumExpanded, "Number of ISEL instructions expanded"); +STATISTIC(NumRemoved, "Number of ISEL instructions removed"); +STATISTIC(NumFolded, "Number of ISEL instructions folded"); +STATISTIC(NumContiguous, "Number of Contiguous ISEL instructions"); +STATISTIC(NumNonContiguous, "Number of Non-Contiguous ISEL instructions"); + +// If ppc-gen-isel=false is set, it will disable generating the ISEL +// instruction on 64-bit non-Darwin PPC targets, for other targets, +// it will still generate the ISEL instructions. +static cl::opt + GenerateISEL("ppc-gen-isel", + cl::desc("Enable generating the ISEL instruction."), + cl::init(true), cl::Hidden); + +namespace llvm { +void initializePPCExpandISELPass(PassRegistry &); +} + +class PPCExpandISEL : public MachineFunctionPass { + + typedef SmallVector BlockISELList; + typedef SmallDenseMap ISELInstructionList; + + // List of ISEL instructions, sorted by MBB. + ISELInstructionList ISELInstructions; + MachineFunction *MF; + bool IsTrueBlockRequired; + bool IsFalseBlockRequired; + MachineBasicBlock *MBB; + DebugLoc dl; + MachineFunction *Fn; + MachineFunction::iterator It; + const BasicBlock *LLVM_BB; + MachineBasicBlock *TrueBlock; + MachineBasicBlock *FalseBlock; + MachineOperand *ConditionRegister; + MachineBasicBlock::iterator TrueBlockI; + MachineBasicBlock::iterator FalseBlockI; + MachineBasicBlock *NewSuccessor; + MachineBasicBlock *Successor; + + /// + /// Initialize the object + /// + void initialize(MachineFunction &MFParam); + + void setUp(BlockISELList &BIL); + void handleSpecialCases(BlockISELList &BIL); + void reorganizeBlockLayout(BlockISELList &BIL); + void populateBlocks(BlockISELList &BIL); + void expandCanMergeISELs(BlockISELList &BIL); + void expandISELInstructions(); + + bool canMerge(MachineInstr *&PrevPushedMI, MachineInstr *&MI); + + /// + /// Is this instruction an ISEL or ISEL8 + /// + bool isISEL(const MachineInstr &MI) const { + return (MI.getOpcode() == PPC::ISEL || MI.getOpcode() == PPC::ISEL8); + } + + /// + /// Collect all ISEL instructions from the current function + /// + /// Walk the current function and collect all the ISEL instructions that are + /// found. The instructions are placed in the ISELInstructions vector. + /// + /// \return true if any ISEL instructions were found, false otherwise + /// + bool collectISELInstructions(); + +public: + static char ID; + PPCExpandISEL() : MachineFunctionPass(ID) { + initializePPCExpandISELPass(*PassRegistry::getPassRegistry()); + } + + const TargetInstrInfo *TII; + + /// + /// Determine whether to generate the ISEL instruction or expand it + /// + /// Expand ISEL instructions into if-then-else sequence only when both of + /// the following two conditions hold: + /// (1) 64-bit non-Darwin PPC targets. + /// (2) -ppc-gen-isel=false + /// Otherwise, still generate ISEL instructions. + /// The -ppc-gen-isel option is set to true by default. which means the + /// ISEL insturctions are still generated by default on all platforms. + /// instruction, regardless of the architecture. + /// + /// \return true if ISEL should be expanded into if-then-else code sequence; + /// false if ISEL instruction should be generated, i.e. not expaned. + /// + static bool isExpandISELEnabled(const MachineFunction &MF); + +#ifndef NDEBUG + void DumpISELInstructions() const; +#endif + + bool runOnMachineFunction(MachineFunction &MF) override { + DEBUG(dbgs() << "Function: "; MF.dump(); dbgs() << "\n"); + if (!isExpandISELEnabled(MF)) + return false; + + initialize(MF); + + if (!collectISELInstructions()) { + DEBUG(dbgs() << "No ISEL instructions in this function\n"); + return false; + } + +#ifndef NDEBUG + DumpISELInstructions(); +#endif + + expandISELInstructions(); + + return true; + } +}; + +void PPCExpandISEL::initialize(MachineFunction &MFParam) { + MF = &MFParam; + TII = MF->getSubtarget().getInstrInfo(); + ISELInstructions.clear(); +} + +bool PPCExpandISEL::isExpandISELEnabled(const MachineFunction &MF) { + if (!GenerateISEL) + return true; + + return !MF.getSubtarget().hasISEL(); +} + +bool PPCExpandISEL::collectISELInstructions() { + for (MachineBasicBlock &MBB : *MF) { + BlockISELList thisBlockISELs; + for (MachineInstr &MI : MBB) + if (isISEL(MI)) + thisBlockISELs.push_back(&MI); + if (!thisBlockISELs.empty()) + ISELInstructions.insert(std::make_pair(MBB.getNumber(), thisBlockISELs)); + } + return !ISELInstructions.empty(); +} + +#ifndef NDEBUG +void PPCExpandISEL::DumpISELInstructions() const { + for (const auto &I : ISELInstructions) { + DEBUG(dbgs() << "BB#" << I.first << ":\n"); + for (const auto &VI : I.second) + DEBUG(dbgs() << " "; VI->print(dbgs())); + } +} +#endif + +bool PPCExpandISEL::canMerge(MachineInstr *&PrevPushedMI, MachineInstr *&MI) { + bool IsSameCR = + (PrevPushedMI->getOperand(3).getReg() == MI->getOperand(3).getReg()); + MachineBasicBlock::iterator PrevPushedMBBI = *PrevPushedMI; + MachineBasicBlock::iterator MBBI = *MI; + bool IsContiguousISELs = (std::prev(MBBI) == PrevPushedMBBI); + + if (IsSameCR) { + if (IsContiguousISELs) + NumContiguous++; + else + NumNonContiguous++; + } + + return IsSameCR && IsContiguousISELs; +} + +void PPCExpandISEL::expandISELInstructions() { + for (auto &BlockList : ISELInstructions) { + DEBUG(dbgs() << "Expanding ISEL instructions in BB#" << BlockList.first + << "\n"); + + BlockISELList &CurrentISELList = BlockList.second; + auto I = CurrentISELList.begin(); + auto E = CurrentISELList.end(); + + while (I != E) { + BlockISELList SubISELList; + + SubISELList.push_back(*I++); + + // Collect the ISELs that have the same condition. + while (I != E && canMerge(SubISELList.back(), *I)) + SubISELList.push_back(*I++); + + expandCanMergeISELs(SubISELList); + } + } +} + +void PPCExpandISEL::setUp(BlockISELList &BIL) { + // all the ISELs are in the same MBB + MBB = BIL.back()->getParent(); + Fn = MBB->getParent(); + It = MBB->getIterator(); + ++It; // Point to the successor block of MBB + LLVM_BB = MBB->getBasicBlock(); + MachineBasicBlock::iterator MBBI = (*BIL.back()); // implicit conversion + NewSuccessor = (MBBI != MBB->getLastNonDebugInstr()) ? + Fn->CreateMachineBasicBlock(LLVM_BB) : nullptr; +} + +void PPCExpandISEL::handleSpecialCases(BlockISELList &BIL) { + IsTrueBlockRequired = false; + IsFalseBlockRequired = false; + + auto MI = BIL.begin(); + while (MI != BIL.end()) { + assert(isISEL(**MI) && "Expecting an ISEL instruction"); + DEBUG(dbgs() << "**MI: " << **MI << "\n"); + + MachineOperand &Dest = (*MI)->getOperand(0); // location to store to + MachineOperand &TrueValue = (*MI)->getOperand(1); // Value to store if + // condition is true + MachineOperand &FalseValue = (*MI)->getOperand(2); // Value to store if + // condition is false + + // if at least one of the ISEL instructions satisfy the following + // condition, we need the True Block: + // The Dest Register and True Value Register are not the same or they + // are both R0 + // Similarly, if at least one of the ISEL instructions satisfy the + // following condition, we need the False Block: + // The Dest Register and False Value Register are not the same + + bool IsADDIInstRequired = + ((Dest.getReg() != TrueValue.getReg()) || (TrueValue.getReg() == 0)); + bool IsORIInstRequired = (Dest.getReg() != FalseValue.getReg()); + + // Special case 1, all the registers used by ISEL are the same one but not + // R0. + if (!IsADDIInstRequired && !IsORIInstRequired) { + DEBUG(dbgs() << "Remove redudant ISEL instruction."); + NumRemoved++; + (*MI)->eraseFromParent(); + MI = BIL.erase(MI); + continue; + } + + // Special case 2, the two input registers used by ISEL are the same and + // not R0. + if ((TrueValue.getReg() == FalseValue.getReg()) && + (TrueValue.getReg() != 0) && (BIL.size() == 1)) { + DEBUG(dbgs() << "Fold the ISEL insturction to an unconditonal copy."); + NumFolded++; + BuildMI(*MBB, (*MI), dl, TII->get(PPC::ADDI8)) + .addOperand(Dest) + .addOperand(TrueValue) + .addOperand(MachineOperand::CreateImm(0)); + (*MI)->eraseFromParent(); + MI = BIL.erase(MI); + continue; + } + + IsTrueBlockRequired |= IsADDIInstRequired; + IsFalseBlockRequired |= IsORIInstRequired; + MI++; + } +} + +void PPCExpandISEL::reorganizeBlockLayout(BlockISELList &BIL) { + if (BIL.empty()) + return; + + assert((IsTrueBlockRequired || IsFalseBlockRequired) && + "Should have been handled by special cases earlier!"); + + // If NewSuccessor is NULL then the last ISEL in this group is the last + // non-debug instruction in this block. Find the fall-through successor + // of this block to use when updating the CFG below + if (!NewSuccessor) { + assert(MBB->canFallThrough() && "This block should fall through!\n"); + for (MachineBasicBlock::succ_iterator SuccIt = MBB->succ_begin(); + SuccIt != MBB->succ_end(); SuccIt++) { + if (MBB->isLayoutSuccessor(*SuccIt)) { + Successor = *SuccIt; + break; + } + } + } else + Successor = NewSuccessor; + + // The FalseBlock and TrueBlock are inserted after the MBB block but before + // its successor conditionally. + // Note this need to be done *after* the above setting the Successor code, + // otherwise the canFallThrough assert will fail. + if (IsFalseBlockRequired) { + FalseBlock = Fn->CreateMachineBasicBlock(LLVM_BB); + Fn->insert(It, FalseBlock); + } + + if (IsTrueBlockRequired) { + TrueBlock = Fn->CreateMachineBasicBlock(LLVM_BB); + Fn->insert(It, TrueBlock); + } + + if (NewSuccessor) { + Fn->insert(It, NewSuccessor); + + // Transfer the rest of this block into the new successor block + NewSuccessor->splice( + NewSuccessor->end(), MBB, + std::next(MachineBasicBlock::iterator(BIL.back())), MBB->end()); + NewSuccessor->transferSuccessorsAndUpdatePHIs(MBB); + + // Copy the liveIn to new successor + for (MachineBasicBlock::livein_iterator LIT = MBB->livein_begin(); + LIT != MBB->livein_end(); LIT++) + NewSuccessor->addLiveIn(*LIT); + } else { + // Remove successor from MBB; + MBB->removeSuccessor(Successor); + } + + // Note that this needs to be done *after* transfering the successors from MBB + // to the NewSuccessor block, otherwise these blocks will also be transferred + // as successors! + MBB->addSuccessor(IsTrueBlockRequired ? TrueBlock : Successor); + MBB->addSuccessor(IsFalseBlockRequired ? FalseBlock : Successor); + + if (IsTrueBlockRequired) { + TrueBlockI = TrueBlock->begin(); + TrueBlock->addSuccessor(Successor); + } + + if (IsFalseBlockRequired) { + FalseBlockI = FalseBlock->begin(); + FalseBlock->addSuccessor(Successor); + } + + // Conditional branch to the TrueBlock or Successor + ConditionRegister = &BIL.back()->getOperand(3); // Condition + BuildMI(*MBB, BIL.back(), dl, TII->get(PPC::BC)) + .addOperand(*ConditionRegister) + .addMBB(IsTrueBlockRequired ? TrueBlock : Successor); + + // Jump over the true block to the new successor if the condition is false + BuildMI(*(IsFalseBlockRequired ? FalseBlock : MBB), + (IsFalseBlockRequired ? FalseBlockI : BIL.back()), dl, + TII->get(PPC::B)) + .addMBB(Successor); + + if (IsFalseBlockRequired) + FalseBlockI = FalseBlock->begin(); // get the position of PPC::B +} + +void PPCExpandISEL::populateBlocks(BlockISELList &BIL) { + for (auto MI : BIL) { + assert(isISEL(*MI) && "Expecting an ISEL instruction"); + DEBUG(dbgs() << "*MI: " << *MI << "\n"); + + MachineOperand &Dest = MI->getOperand(0); // location to store to + MachineOperand &TrueValue = MI->getOperand(1); // Value to store if + // condition is true + MachineOperand &FalseValue = MI->getOperand(2); // Value to store if + // condition is false + + // If the Dest Register and True Value Register are not the same one or they + // are both R0, we need the True Block. + bool IsADDIInstRequired = + ((Dest.getReg() != TrueValue.getReg()) || (TrueValue.getReg() == 0)); + bool IsORIInstRequired = (Dest.getReg() != FalseValue.getReg()); + + DEBUG(dbgs() << "Dest: " << Dest << "\n"); + DEBUG(dbgs() << "TrueValue: " << TrueValue << "\n"); + DEBUG(dbgs() << "FalseValue: " << FalseValue << "\n"); + DEBUG(dbgs() << "ConditionRegister: " << *ConditionRegister << "\n"); + + if (IsADDIInstRequired) { + // Copy the result into the destination if the condition is true + BuildMI(*TrueBlock, TrueBlockI, dl, TII->get(PPC::ADDI8)) + .addOperand(Dest) + .addOperand(TrueValue) + .addOperand(MachineOperand::CreateImm(0)); + + // Add the LiveIn registers required by true block. + TrueBlock->addLiveIn(Dest.getReg()); + TrueBlock->addLiveIn(TrueValue.getReg()); + } + + if (IsORIInstRequired) { + // Add the LiveIn registers required by false block. + FalseBlock->addLiveIn(Dest.getReg()); + FalseBlock->addLiveIn(FalseValue.getReg()); + } + + if (NewSuccessor) { + // Add the LiveIn registers required by NewSuccessor block. + NewSuccessor->addLiveIn(Dest.getReg()); + NewSuccessor->addLiveIn(TrueValue.getReg()); + NewSuccessor->addLiveIn(FalseValue.getReg()); + } + + // Copy the value into the destination if the condition is false + if (IsORIInstRequired) + BuildMI(*FalseBlock, FalseBlockI, dl, TII->get(PPC::ORI8)) + .addOperand(Dest) + .addOperand(FalseValue) + .addOperand(MachineOperand::CreateImm(0)); + + MI->eraseFromParent(); // remove the ISEL instruction + + NumExpanded++; + } +} + +void PPCExpandISEL::expandCanMergeISELs(BlockISELList &BIL) { + setUp(BIL); + handleSpecialCases(BIL); + reorganizeBlockLayout(BIL); + populateBlocks(BIL); +} + +INITIALIZE_PASS(PPCExpandISEL, DEBUG_TYPE, "PowerPC Expand ISEL Generation", + false, false) + +char PPCExpandISEL::ID = 0; +FunctionPass *llvm::createPPCExpandISELPass() { return new PPCExpandISEL(); } Index: lib/Target/PowerPC/PPCISelDAGToDAG.cpp =================================================================== --- lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -3515,10 +3515,6 @@ // be folded with the isel so that we don't need to materialize a register // containing zero. bool PPCDAGToDAGISel::AllUsersSelectZero(SDNode *N) { - // If we're not using isel, then this does not matter. - if (!PPCSubTarget->hasISEL()) - return false; - for (SDNode::use_iterator UI = N->use_begin(), UE = N->use_end(); UI != UE; ++UI) { SDNode *User = *UI; Index: lib/Target/PowerPC/PPCISelLowering.cpp =================================================================== --- lib/Target/PowerPC/PPCISelLowering.cpp +++ lib/Target/PowerPC/PPCISelLowering.cpp @@ -9072,10 +9072,9 @@ MachineFunction *F = BB->getParent(); - if (Subtarget.hasISEL() && - (MI.getOpcode() == PPC::SELECT_CC_I4 || + if (MI.getOpcode() == PPC::SELECT_CC_I4 || MI.getOpcode() == PPC::SELECT_CC_I8 || - MI.getOpcode() == PPC::SELECT_I4 || MI.getOpcode() == PPC::SELECT_I8)) { + MI.getOpcode() == PPC::SELECT_I4 || MI.getOpcode() == PPC::SELECT_I8) { SmallVector Cond; if (MI.getOpcode() == PPC::SELECT_CC_I4 || MI.getOpcode() == PPC::SELECT_CC_I8) Index: lib/Target/PowerPC/PPCInstrInfo.cpp =================================================================== --- lib/Target/PowerPC/PPCInstrInfo.cpp +++ lib/Target/PowerPC/PPCInstrInfo.cpp @@ -692,9 +692,6 @@ ArrayRef Cond, unsigned TrueReg, unsigned FalseReg, int &CondCycles, int &TrueCycles, int &FalseCycles) const { - if (!Subtarget.hasISEL()) - return false; - if (Cond.size() != 2) return false; @@ -736,9 +733,6 @@ assert(Cond.size() == 2 && "PPC branch conditions have two components!"); - assert(Subtarget.hasISEL() && - "Cannot insert select on target without ISEL support"); - // Get the register classes. MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo(); const TargetRegisterClass *RC = Index: lib/Target/PowerPC/PPCSubtarget.h =================================================================== --- lib/Target/PowerPC/PPCSubtarget.h +++ lib/Target/PowerPC/PPCSubtarget.h @@ -298,7 +298,7 @@ bool isSVR4ABI() const { return !isDarwinABI(); } bool isELFv2ABI() const; - bool enableEarlyIfConversion() const override { return hasISEL(); } + bool enableEarlyIfConversion() const override { return true; } // Scheduling customization. bool enableMachineScheduler() const override; Index: lib/Target/PowerPC/PPCTargetMachine.cpp =================================================================== --- lib/Target/PowerPC/PPCTargetMachine.cpp +++ lib/Target/PowerPC/PPCTargetMachine.cpp @@ -412,6 +412,8 @@ } void PPCPassConfig::addPreEmitPass() { + addPass(createPPCExpandISELPass(), false); + if (getOptLevel() != CodeGenOpt::None) addPass(createPPCEarlyReturnPass(), false); // Must run branch selection immediately preceding the asm printer. Index: test/CodeGen/PowerPC/crbit-asm.ll =================================================================== --- test/CodeGen/PowerPC/crbit-asm.ll +++ test/CodeGen/PowerPC/crbit-asm.ll @@ -1,5 +1,8 @@ ; RUN: llc -verify-machineinstrs -mcpu=pwr7 < %s | FileCheck %s ; RUN: llc -verify-machineinstrs -O1 -mcpu=pwr7 < %s | FileCheck %s +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -ppc-gen-isel=false < %s | FileCheck --check-prefix=CHECK-NO-ISEL %s +; RUN: llc -verify-machineinstrs -O1 -mcpu=pwr7 -ppc-gen-isel=false < %s | FileCheck --check-prefix=CHECK-NO-ISEL %s + target datalayout = "E-m:e-i64:64-n32:64" target triple = "powerpc64-unknown-linux-gnu" @@ -18,6 +21,10 @@ ; CHECK-DAG: crand [[REG3:[0-9]+]], [[REG2]], 1 ; CHECK-DAG: li [[REG4:[0-9]+]], 1 ; CHECK: isel 3, [[REG4]], [[REG1]], [[REG3]] +; CHECK-NO-ISEL-LABEL: @testi1 +; CHECK-NO-ISEL: bclr 12, 20, 0 +; CHECK-NO-ISEL: ori 3, 5, 0 +; CHECK-NO-ISEL-NEXT: blr ; CHECK: blr } Index: test/CodeGen/PowerPC/crbits.ll =================================================================== --- test/CodeGen/PowerPC/crbits.ll +++ test/CodeGen/PowerPC/crbits.ll @@ -1,4 +1,5 @@ ; RUN: llc -verify-machineinstrs -mcpu=pwr7 < %s | FileCheck %s +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -ppc-gen-isel=false < %s | FileCheck --check-prefix=CHECK-NO-ISEL %s target datalayout = "E-m:e-i64:64-n32:64" target triple = "powerpc64-unknown-linux-gnu" @@ -19,6 +20,11 @@ ; CHECK: crnor ; CHECK: crnand [[REG4:[0-9]+]], ; CHECK: isel 3, 0, [[REG1]], [[REG4]] +; CHECK-NO-ISEL-LABEL: @test1 +; CHECK-NO-ISEL: bc 12, 20, .LBB +; CHECK-NO-ISEL-NEXT: blr +; CHECK-NO-ISEL: addi 3, 0, 0 +; CHECK-NO-ISEL-NEXT: blr ; CHECK: blr } Index: test/CodeGen/PowerPC/expand-contiguous-isel.ll =================================================================== --- /dev/null +++ test/CodeGen/PowerPC/expand-contiguous-isel.ll @@ -0,0 +1,151 @@ +target datalayout = "e-m:e-i64:64-n32:64" +target triple = "powerpc64le-unknown-linux-gnu" +; This file mainly tests that one of the ISEL instruction in the group uses the same register for operand RT, RA, RB +; RUN: llc -verify-machineinstrs -O2 -ppc-asm-full-reg-names -mcpu=pwr7 -ppc-gen-isel=true < %s | FileCheck %s --check-prefix=CHECK-GEN-ISEL-TRUE +; RUN: llc -verify-machineinstrs -O2 -ppc-asm-full-reg-names -mcpu=pwr7 -ppc-gen-isel=false < %s | FileCheck %s --implicit-check-not isel +; Function Attrs: norecurse nounwind readnone +@.str = private unnamed_addr constant [3 x i8] c"]]\00", align 1 +@.str.1 = private unnamed_addr constant [35 x i8] c"Index < Length && \22Invalid index!\22\00", align 1 +@.str.2 = private unnamed_addr constant [50 x i8] c"/home/jtony/src/llvm/include/llvm/ADT/StringRef.h\00", align 1 +@__PRETTY_FUNCTION__._ZNK4llvm9StringRefixEm = private unnamed_addr constant [47 x i8] c"char llvm::StringRef::operator[](size_t) const\00", align 1 +@.str.3 = private unnamed_addr constant [95 x i8] c"(data || length == 0) && \22StringRef cannot be built from a NULL argument with non-null length\22\00", align 1 +@__PRETTY_FUNCTION__._ZN4llvm9StringRefC2EPKcm = private unnamed_addr constant [49 x i8] c"llvm::StringRef::StringRef(const char *, size_t)\00", align 1 +; Function Attrs: nounwind +define i64 @_Z3fn1N4llvm9StringRefE([2 x i64] %Str.coerce) local_unnamed_addr #0 { +entry: + %Str.coerce.fca.0.extract = extractvalue [2 x i64] %Str.coerce, 0 + %Str.coerce.fca.1.extract = extractvalue [2 x i64] %Str.coerce, 1 + br label %while.cond.outer +while.cond.outer: ; preds = %_ZNK4llvm9StringRef6substrEmm.exit, %entry + %Str.sroa.0.0.ph = phi i64 [ %8, %_ZNK4llvm9StringRef6substrEmm.exit ], [ %Str.coerce.fca.0.extract, %entry ] + %.sink.ph = phi i64 [ %sub.i, %_ZNK4llvm9StringRef6substrEmm.exit ], [ %Str.coerce.fca.1.extract, %entry ] + %BracketDepth.0.ph = phi i64 [ %BracketDepth.1, %_ZNK4llvm9StringRef6substrEmm.exit ], [ undef, %entry ] + %cmp65 = icmp eq i64 %BracketDepth.0.ph, 0 + br i1 %cmp65, label %while.cond.us.preheader, label %while.cond.preheader +while.cond.us.preheader: ; preds = %while.cond.outer + br label %while.cond.us +while.cond.preheader: ; preds = %while.cond.outer + %cmp.i34129 = icmp eq i64 %.sink.ph, 0 + br i1 %cmp.i34129, label %cond.false.i.loopexit135, label %_ZNK4llvm9StringRefixEm.exit.preheader +_ZNK4llvm9StringRefixEm.exit.preheader: ; preds = %while.cond.preheader + br label %_ZNK4llvm9StringRefixEm.exit +while.cond.us: ; preds = %while.cond.us.preheader, %_ZNK4llvm9StringRef6substrEmm.exit50.us + %Str.sroa.0.0.us = phi i64 [ %3, %_ZNK4llvm9StringRef6substrEmm.exit50.us ], [ %Str.sroa.0.0.ph, %while.cond.us.preheader ] + %.sink.us = phi i64 [ %sub.i41.us, %_ZNK4llvm9StringRef6substrEmm.exit50.us ], [ %.sink.ph, %while.cond.us.preheader ] + %cmp.i30.us = icmp ult i64 %.sink.us, 2 + br i1 %cmp.i30.us, label %if.end.us, label %if.end.i.i.us +if.end.i.i.us: ; preds = %while.cond.us + %0 = inttoptr i64 %Str.sroa.0.0.us to i8* + %call.i.i.us = tail call signext i32 @memcmp(i8* %0, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str, i64 0, i64 0), i64 2) #3 + %phitmp.i.us = icmp eq i32 %call.i.i.us, 0 + br i1 %phitmp.i.us, label %if.then, label %_ZNK4llvm9StringRefixEm.exit.us +if.end.us: ; preds = %while.cond.us + %cmp.i34.us = icmp eq i64 %.sink.us, 0 + br i1 %cmp.i34.us, label %cond.false.i.loopexit, label %_ZNK4llvm9StringRefixEm.exit.us +_ZNK4llvm9StringRefixEm.exit.us: ; preds = %if.end.i.i.us, %if.end.us + %1 = inttoptr i64 %Str.sroa.0.0.us to i8* + %2 = load i8, i8* %1, align 1, !tbaa !2 + switch i8 %2, label %_ZNK4llvm9StringRef6substrEmm.exit.loopexit [ + i8 92, label %if.then4.us + i8 93, label %if.then9 + ] +if.then4.us: ; preds = %_ZNK4llvm9StringRefixEm.exit.us + %.sroa.speculated12.i38.us = select i1 %cmp.i30.us, i64 %.sink.us, i64 2 + %add.ptr.i40.us = getelementptr inbounds i8, i8* %1, i64 %.sroa.speculated12.i38.us + %sub.i41.us = sub i64 %.sink.us, %.sroa.speculated12.i38.us + %tobool.i.i44.us = icmp ne i8* %add.ptr.i40.us, null + %cmp.i4.i45.us = icmp eq i64 %sub.i41.us, 0 + %or.cond.i.i46.us = or i1 %tobool.i.i44.us, %cmp.i4.i45.us + br i1 %or.cond.i.i46.us, label %_ZNK4llvm9StringRef6substrEmm.exit50.us, label %cond.false.i.i47.loopexit +_ZNK4llvm9StringRef6substrEmm.exit50.us: ; preds = %if.then4.us + %3 = ptrtoint i8* %add.ptr.i40.us to i64 + br label %while.cond.us +if.then: ; preds = %if.end.i.i.us + ret i64 undef +cond.false.i.loopexit: ; preds = %if.end.us + br label %cond.false.i +cond.false.i.loopexit134: ; preds = %_ZNK4llvm9StringRef6substrEmm.exit50 + br label %cond.false.i +cond.false.i.loopexit135: ; preds = %while.cond.preheader + br label %cond.false.i +cond.false.i: ; preds = %cond.false.i.loopexit135, %cond.false.i.loopexit134, %cond.false.i.loopexit + tail call void @__assert_fail(i8* getelementptr inbounds ([35 x i8], [35 x i8]* @.str.1, i64 0, i64 0), i8* getelementptr inbounds ([50 x i8], [50 x i8]* @.str.2, i64 0, i64 0), i32 zeroext 225, i8* getelementptr inbounds ([47 x i8], [47 x i8]* @__PRETTY_FUNCTION__._ZNK4llvm9StringRefixEm, i64 0, i64 0)) #4 + unreachable +_ZNK4llvm9StringRefixEm.exit: ; preds = %_ZNK4llvm9StringRefixEm.exit.preheader, %_ZNK4llvm9StringRef6substrEmm.exit50 + %.sink131 = phi i64 [ %sub.i41, %_ZNK4llvm9StringRef6substrEmm.exit50 ], [ %.sink.ph, %_ZNK4llvm9StringRefixEm.exit.preheader ] + %Str.sroa.0.0130 = phi i64 [ %6, %_ZNK4llvm9StringRef6substrEmm.exit50 ], [ %Str.sroa.0.0.ph, %_ZNK4llvm9StringRefixEm.exit.preheader ] + %4 = inttoptr i64 %Str.sroa.0.0130 to i8* + %5 = load i8, i8* %4, align 1, !tbaa !2 + switch i8 %5, label %_ZNK4llvm9StringRef6substrEmm.exit.loopexit132 [ + i8 92, label %if.then4 + i8 93, label %if.end10 + ] +if.then4: ; preds = %_ZNK4llvm9StringRefixEm.exit + %cmp.i.i37 = icmp ult i64 %.sink131, 2 + %.sroa.speculated12.i38 = select i1 %cmp.i.i37, i64 %.sink131, i64 2 + %add.ptr.i40 = getelementptr inbounds i8, i8* %4, i64 %.sroa.speculated12.i38 + %sub.i41 = sub i64 %.sink131, %.sroa.speculated12.i38 + %tobool.i.i44 = icmp ne i8* %add.ptr.i40, null + %cmp.i4.i45 = icmp eq i64 %sub.i41, 0 + %or.cond.i.i46 = or i1 %tobool.i.i44, %cmp.i4.i45 + br i1 %or.cond.i.i46, label %_ZNK4llvm9StringRef6substrEmm.exit50, label %cond.false.i.i47.loopexit133 +cond.false.i.i47.loopexit: ; preds = %if.then4.us + br label %cond.false.i.i47 +cond.false.i.i47.loopexit133: ; preds = %if.then4 + br label %cond.false.i.i47 +cond.false.i.i47: ; preds = %cond.false.i.i47.loopexit133, %cond.false.i.i47.loopexit + tail call void @__assert_fail(i8* getelementptr inbounds ([95 x i8], [95 x i8]* @.str.3, i64 0, i64 0), i8* getelementptr inbounds ([50 x i8], [50 x i8]* @.str.2, i64 0, i64 0), i32 zeroext 90, i8* getelementptr inbounds ([49 x i8], [49 x i8]* @__PRETTY_FUNCTION__._ZN4llvm9StringRefC2EPKcm, i64 0, i64 0)) #4 + unreachable +_ZNK4llvm9StringRef6substrEmm.exit50: ; preds = %if.then4 + %6 = ptrtoint i8* %add.ptr.i40 to i64 + %cmp.i34 = icmp eq i64 %sub.i41, 0 + br i1 %cmp.i34, label %cond.false.i.loopexit134, label %_ZNK4llvm9StringRefixEm.exit +if.then9: ; preds = %_ZNK4llvm9StringRefixEm.exit.us + tail call void @exit(i32 signext 1) #4 + unreachable +if.end10: ; preds = %_ZNK4llvm9StringRefixEm.exit + %dec = add i64 %BracketDepth.0.ph, -1 + br label %_ZNK4llvm9StringRef6substrEmm.exit +_ZNK4llvm9StringRef6substrEmm.exit.loopexit: ; preds = %_ZNK4llvm9StringRefixEm.exit.us + br label %_ZNK4llvm9StringRef6substrEmm.exit +_ZNK4llvm9StringRef6substrEmm.exit.loopexit132: ; preds = %_ZNK4llvm9StringRefixEm.exit + br label %_ZNK4llvm9StringRef6substrEmm.exit +_ZNK4llvm9StringRef6substrEmm.exit: ; preds = %_ZNK4llvm9StringRef6substrEmm.exit.loopexit132, %_ZNK4llvm9StringRef6substrEmm.exit.loopexit, %if.end10 + %.sink76 = phi i64 [ %.sink131, %if.end10 ], [ %.sink.us, %_ZNK4llvm9StringRef6substrEmm.exit.loopexit ], [ %.sink131, %_ZNK4llvm9StringRef6substrEmm.exit.loopexit132 ] + %7 = phi i8* [ %4, %if.end10 ], [ %1, %_ZNK4llvm9StringRef6substrEmm.exit.loopexit ], [ %4, %_ZNK4llvm9StringRef6substrEmm.exit.loopexit132 ] + %BracketDepth.1 = phi i64 [ %dec, %if.end10 ], [ 0, %_ZNK4llvm9StringRef6substrEmm.exit.loopexit ], [ %BracketDepth.0.ph, %_ZNK4llvm9StringRef6substrEmm.exit.loopexit132 ] + %sub.i = add i64 %.sink76, -1 + %add.ptr.i = getelementptr inbounds i8, i8* %7, i64 1 + %8 = ptrtoint i8* %add.ptr.i to i64 + br label %while.cond.outer + +; CHECK-LABEL: @_Z3fn1N4llvm9StringRefE +; CHECK-GEN-ISEL-TRUE: isel r3, r3, r3, 2 +; CHECK-GEN-ISEL-TRUE: isel r6, r7, r6, 2 +; CHECK: bc 12, 2, .LBB +; CHECK-NEXT: b .LBB +; CHECK-NEXT: .LBB +; CHECK-NEXT: addi r6, r7, 0 +; CHECK-NEXT: .LBB +} + + + +; Function Attrs: noreturn nounwind +declare void @exit(i32 signext) local_unnamed_addr #1 +; Function Attrs: nounwind readonly +declare signext i32 @memcmp(i8* nocapture, i8* nocapture, i64) local_unnamed_addr #2 +; Function Attrs: noreturn nounwind +declare void @__assert_fail(i8*, i8*, i32 zeroext, i8*) local_unnamed_addr #1 +attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="ppc64le" "target-features"="+altivec,+bpermd,+crypto,+direct-move,+extdiv,+power8-vector,+vsx,-power9-vector,-qpx" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { noreturn nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="ppc64le" "target-features"="+altivec,+bpermd,+crypto,+direct-move,+extdiv,+power8-vector,+vsx,-power9-vector,-qpx" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #2 = { nounwind readonly "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="ppc64le" "target-features"="+altivec,+bpermd,+crypto,+direct-move,+extdiv,+power8-vector,+vsx,-power9-vector,-qpx" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #3 = { nounwind readonly } +attributes #4 = { noreturn nounwind } +!llvm.module.flags = !{!0} +!llvm.ident = !{!1} +!0 = !{i32 1, !"PIC Level", i32 2} +!1 = !{!"clang version 4.0.0 (trunk 286863) (llvm/trunk 286967)"} +!2 = !{!3, !3, i64 0} +!3 = !{!"omnipotent char", !4, i64 0} +!4 = !{!"Simple C++ TBAA"} Index: test/CodeGen/PowerPC/expand-isel.ll =================================================================== --- /dev/null +++ test/CodeGen/PowerPC/expand-isel.ll @@ -0,0 +1,227 @@ +target datalayout = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v128:128:128-n32:64" +target triple = "powerpc64-unknown-linux-gnu" +; RUN: llc -verify-machineinstrs -O2 -ppc-asm-full-reg-names -mcpu=pwr7 -ppc-gen-isel=false < %s | FileCheck %s --implicit-check-not isel +; Function Attrs: norecurse nounwind readnone +define signext i32 @testExpandISELToIfElse(i32 signext %i, i32 signext %j) { +entry: + %cmp = icmp sgt i32 %i, 0 + %add = add nsw i32 %i, 1 + %cond = select i1 %cmp, i32 %add, i32 %j + ret i32 %cond + +; CHECK-LABEL: @testExpandISELToIfElse +; CHECK: addi r5, r3, 1 +; CHECK-NEXT: cmpwi cr0, r3, 0 +; CHECK-NEXT: bc 12, 1, .LBB +; CHECK: ori r3, r4, 0 +; CHECK-NEXT: b .LBB +; CHECK-NEXT: .LBB +; CHECK-NEXT: addi r3, r5, 0 +; CHECK-NEXT: .LBB +; CHECK-NEXT: extsw r3, r3 +; CHECK-NEXT: blr +} + + +; Function Attrs: norecurse nounwind readnone +define signext i32 @testExpandISELToIf(i32 signext %i, i32 signext %j) { +entry: + %cmp = icmp sgt i32 %i, 0 + %cond = select i1 %cmp, i32 %j, i32 %i + ret i32 %cond + +; CHECK-LABEL: @testExpandISELToIf +; CHECK: cmpwi r3, 0 +; CHECK-NEXT: bc 12, 1, .LBB +; CHECK-NEXT: blr +; CHECK-NEXT: .LBB +; CHECK-NEXT: addi r3, r4, 0 +; CHECK-NEXT: blr +} + +; Function Attrs: norecurse nounwind readnone +define signext i32 @testExpandISELToElse(i32 signext %i, i32 signext %j) { +entry: + %cmp = icmp sgt i32 %i, 0 + %cond = select i1 %cmp, i32 %i, i32 %j + ret i32 %cond + +; CHECK-LABEL: @testExpandISELToElse +; CHECK: cmpwi r3, 0 +; CHECK-NEXT: bclr 12, 1, 0 +; CHECK: ori r3, r4, 0 +; CHECK-NEXT: blr +} + +; Function Attrs: norecurse nounwind readnone +define signext i32 @testReplaceISELWithCopy(i32 signext %i, i32 signext %j) { +entry: + %cmp = icmp sgt i32 %i, 0 + %cond = select i1 %cmp, i32 %j, i32 %j + ret i32 %cond + +; CHECK-LABEL: @testReplaceISELWithCopy + +; Fix me should really check: addi r3, r4, 0 +; but for some reason it's optimized to mr r3, r4 +; CHECK: mr r3, r4 +; CHECK-NEXT: blr +} + +; Function Attrs: norecurse nounwind readnone +define signext i32 @testExpandISELToNull(i32 signext %i, i32 signext %j) { +entry: + %cmp = icmp sgt i32 %i, 0 + %cond = select i1 %cmp, i32 %i, i32 %i + ret i32 %cond + +; CHECK-LABEL: @testExpandISELToNull +; CHECK-NOT: b .LBB +; CHECK-NOT: bc +; CHECK: blr +} + +; Function Attrs: norecurse nounwind readnone +define signext i32 @testExpandISELsTo2ORIs2ADDIs + (i32 signext %a, i32 signext %b, i32 signext %d, + i32 signext %f, i32 signext %g) { +entry: + + %cmp = icmp sgt i32 %g, 0 + %a.b = select i1 %cmp, i32 %g, i32 %b + %d.f = select i1 %cmp, i32 %d, i32 %f + %add = add nsw i32 %a.b, %d.f + ret i32 %add + +; CHECK-LABEL: @testExpandISELsTo2ORIs2ADDIs +; CHECK: cmpwi r7, 0 +; CHECK-NEXT: bc 12, 1, .LBB +; CHECK: ori r3, r4, 0 +; CHECK-NEXT: ori r12, r6, 0 +; CHECK-NEXT: b .LBB +; CHECK-NEXT: .LBB +; CHECK-NEXT: addi r3, r7, 0 +; CHECK-NEXT: addi r12, r5, 0 +; CHECK-NEXT: .LBB +; CHECK-NEXT: add r3, r3, r12 +; CHECK-NEXT: extsw r3, r3 +; CHECK-NEXT: blr +} + +; Function Attrs: norecurse nounwind readnone +define signext i32 @testExpandISELsTo2ORIs1ADDI + (i32 signext %a, i32 signext %b, i32 signext %d, + i32 signext %f, i32 signext %g) { +entry: + %cmp = icmp sgt i32 %g, 0 + %a.b = select i1 %cmp, i32 %a, i32 %b + %d.f = select i1 %cmp, i32 %d, i32 %f + %add = add nsw i32 %a.b, %d.f + ret i32 %add + +; CHECK-LABEL: @testExpandISELsTo2ORIs1ADDI +; CHECK: cmpwi cr0, r7, 0 +; CHECK-NEXT: bc 12, 1, .LBB +; CHECK: ori r3, r4, 0 +; CHECK-NEXT: ori r12, r6, 0 +; CHECK-NEXT: b .LBB +; CHECK-NEXT: .LBB +; CHECK-NEXT: addi r12, r5, 0 +; CHECK-NEXT: .LBB +; CHECK-NEXT: add r3, r3, r12 +; CHECK-NEXT: extsw r3, r3 +; CHECK-NEXT: blr +} + +; Function Attrs: norecurse nounwind readnone +define signext i32 @testExpandISELsTo1ORI1ADDI + (i32 signext %a, i32 signext %b, i32 signext %d, + i32 signext %f, i32 signext %g) { +entry: + + %cmp = icmp sgt i32 %g, 0 + %a.b = select i1 %cmp, i32 %a, i32 %b + %d.f = select i1 %cmp, i32 %d, i32 %f + %add1 = add nsw i32 %a.b, %d.f + %add2 = add nsw i32 %a, %add1 + ret i32 %add2 + +; CHECK-LABEL: @testExpandISELsTo1ORI1ADDI +; CHECK: cmpwi cr0, r7, 0 +; CHECK-NEXT: bc 12, 1, .LBB +; CHECK: ori r5, r6, 0 +; CHECK-NEXT: b .LBB +; CHECK-NEXT: .LBB +; CHECK-NEXT: addi r4, r3, 0 +; CHECK-NEXT: .LBB +; CHECK-NEXT: add r4, r4, r5 +; CHECK-NEXT: add r3, r3, r4 +; CHECK-NEXT: extsw r3, r3 +; CHECK-NEXT: blr +} + +; Function Attrs: norecurse nounwind readnone +define signext i32 @testExpandISELsTo0ORI2ADDIs + (i32 signext %a, i32 signext %b, i32 signext %d, + i32 signext %f, i32 signext %g) { +entry: + + %cmp = icmp sgt i32 %g, 0 + %a.b = select i1 %cmp, i32 %a, i32 %b + %d.f = select i1 %cmp, i32 %d, i32 %f + %add1 = add nsw i32 %a.b, %d.f + %add2 = add nsw i32 %a, %add1 + %sub1 = sub nsw i32 %add2, %d + ret i32 %sub1 + +; CHECK-LABEL: @testExpandISELsTo0ORI2ADDIs +; CHECK: cmpwi cr0, r7, 0 +; CHECK-NEXT: bc 12, 1, .LBB +; CHECK-NEXT: b .LBB +; CHECK-NEXT: .LBB +; CHECK-NEXT: addi r4, r3, 0 +; CHECK-NEXT: addi r6, r5, 0 +; CHECK-NEXT: .LBB +; CHECK-NEXT: add r4, r4, r6 +; CHECK-NEXT: add r3, r3, r4 +; CHECK-NEXT: subf r3, r5, r3 +; CHECK-NEXT: extsw r3, r3 +; CHECK-NEXT: blr +} + + +@b = common local_unnamed_addr global i32 0, align 4 +@a = common local_unnamed_addr global i32 0, align 4 +; Function Attrs: norecurse nounwind readonly +define signext i32 @testComplexISEL() #0 { +entry: + %0 = load i32, i32* @b, align 4, !tbaa !1 + %tobool = icmp eq i32 %0, 0 + br i1 %tobool, label %if.end, label %cleanup + +if.end: + %1 = load i32, i32* @a, align 4, !tbaa !1 + %conv = sext i32 %1 to i64 + %2 = inttoptr i64 %conv to i32 (...)* + %cmp = icmp eq i32 (...)* %2, bitcast (i32 ()* @testComplexISEL to i32 (...)*) + %conv3 = zext i1 %cmp to i32 + br label %cleanup + +cleanup: + %retval.0 = phi i32 [ %conv3, %if.end ], [ 1, %entry ] + ret i32 %retval.0 + +; CHECK-LABEL: @testComplexISEL +; CHECK: bc 12, 2, .LBB +; CHECK-NEXT: b .LBB +; CHECK-NEXT: .LBB +; CHECK-NEXT: addi r3, r12, 0 +; CHECK-NEXT: .LBB +; CHECK-NEXT: clrldi r3, r3, 32 +; CHECK-NEXT: blr +} + +!1 = !{!2, !2, i64 0} +!2 = !{!"int", !3, i64 0} +!3 = !{!"omnipotent char", !4, i64 0} +!4 = !{!"Simple C/C++ TBAA"} Index: test/CodeGen/PowerPC/fold-zero.ll =================================================================== --- test/CodeGen/PowerPC/fold-zero.ll +++ test/CodeGen/PowerPC/fold-zero.ll @@ -1,5 +1,6 @@ ; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr7 -mattr=-crbits | FileCheck %s -; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr7 | FileCheck -check-prefix=CHECK-CRB %s +; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr7 | FileCheck --check-prefix=CHECK-CRB %s +; RUN: llc -verify-machineinstrs -ppc-gen-isel=false < %s -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr7 | FileCheck --check-prefix=CHECK-NO-ISEL %s target datalayout = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f128:128:128-v128:128:128-n32:64" target triple = "powerpc64-unknown-linux-gnu" @@ -7,19 +8,31 @@ %x = select i1 %a, i32 %c, i32 0 ret i32 %x -; CHECK: @test1 +; CHECK-LABEL: @test1 ; CHECK-NOT: li {{[0-9]+}}, 0 ; CHECK: isel 3, 0, ; CHECK: blr +; CHECK-NO-ISEL-LABEL: @test1 +; CHECK-NO-ISEL: li 3, 0 +; CHECK-NO-ISEL-NEXT: bc 12, 1, .LBB +; CHECK-NO-ISEL-NEXT: blr +; CHECK-NO-ISEL: addi 3, 4, 0 +; CHECK-NO-ISEL-NEXT: blr } define i32 @test2(i1 %a, i32 %c) nounwind { %x = select i1 %a, i32 0, i32 %c ret i32 %x -; CHECK-CRB: @test2 +; CHECK-CRB-LABEL: @test2 ; CHECK-CRB-NOT: li {{[0-9]+}}, 0 ; CHECK-CRB: isel 3, 0, ; CHECK-CRB: blr +; CHECK-NO-ISEL-LABEL: @test2 +; CHECK-NO-ISEL: bc 12, 1, .LBB +; CHECK-NO-ISEL: ori 3, 4, 0 +; CHECK-NO-ISEL-NEXT: blr +; CHECK-NO-ISEL: addi 3, 0, 0 +; CHECK-NO-ISEL-NEXT: blr } Index: test/CodeGen/PowerPC/i1-ext-fold.ll =================================================================== --- test/CodeGen/PowerPC/i1-ext-fold.ll +++ test/CodeGen/PowerPC/i1-ext-fold.ll @@ -1,4 +1,5 @@ ; RUN: llc -verify-machineinstrs -mcpu=pwr7 < %s | FileCheck %s +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -ppc-gen-isel=false < %s | FileCheck --check-prefix=CHECK-NO-ISEL %s target datalayout = "E-m:e-i64:64-n32:64" target triple = "powerpc64-unknown-linux-gnu" @@ -11,11 +12,18 @@ ret i32 %shl ; CHECK-LABEL: @foo +; CHECK-NO-ISEL-LABEL: @foo ; CHECK-DAG: cmpw ; CHECK-DAG: li [[REG1:[0-9]+]], 0 ; CHECK-DAG: li [[REG2:[0-9]+]], 16 ; CHECK: isel 3, [[REG2]], [[REG1]], ; CHECK: blr + +; CHECK-NO-ISEL: bc 12, 0, .LBB +; CHECK-NO-ISEL: ori 3, 5, 0 +; CHECK-NO-ISEL-NEXT: blr +; CHECK-NO-ISEL: addi 3, 12, 0 +; CHECK-NO-ISEL-NEXT: blr } ; Function Attrs: nounwind readnone @@ -28,11 +36,18 @@ ret i32 %add1 ; CHECK-LABEL: @foo2 +; CHECK-NO-ISEL-LABEL: @foo2 ; CHECK-DAG: cmpw ; CHECK-DAG: li [[REG1:[0-9]+]], 5 ; CHECK-DAG: li [[REG2:[0-9]+]], 21 ; CHECK: isel 3, [[REG2]], [[REG1]], ; CHECK: blr + +; CHECK-NO-ISEL: bc 12, 0, .LBB +; CHECK-NO-ISEL: ori 3, 5, 0 +; CHECK-NO-ISEL-NEXT: blr +; CHECK-NO-ISEL: addi 3, 12, 0 +; CHECK-NO-ISEL-NEXT: blr } ; Function Attrs: nounwind readnone @@ -44,10 +59,17 @@ ret i32 %shl ; CHECK-LABEL: @foo3 +; CHECK-NO-ISEL-LABEL: @foo3 ; CHECK-DAG: cmpw ; CHECK-DAG: li [[REG1:[0-9]+]], 16 ; CHECK: isel 3, 0, [[REG1]], ; CHECK: blr + +; CHECK-NO-ISEL: bc 12, 1, .LBB +; CHECK-NO-ISEL: ori 3, 5, 0 +; CHECK-NO-ISEL-NEXT: blr +; CHECK-NO-ISEL: addi 3, 0, 0 +; CHECK-NO-ISEL-NEXT: blr } attributes #0 = { nounwind readnone } Index: test/CodeGen/PowerPC/i1-to-double.ll =================================================================== --- test/CodeGen/PowerPC/i1-to-double.ll +++ test/CodeGen/PowerPC/i1-to-double.ll @@ -7,15 +7,13 @@ ; CHECK-LABEL: @test ; CHECK: andi. {{[0-9]+}}, 3, 1 -; CHECK: bc 12, 1, - -; CHECK: li 3, .LCP[[L1:[A-Z0-9_]+]]@l -; CHECK: addis 3, 3, .LCP[[L1]]@ha -; CHECK: lfs 1, 0(3) -; CHECK: blr - -; CHECK: li 3, .LCP[[L2:[A-Z0-9_]+]]@l -; CHECK: addis 3, 3, .LCP[[L2]]@ha -; CHECK: lfs 1, 0(3) -; CHECK: blr - +; CHECK-NEXT: addis 4, 4, .LCPI +; CHECK-NEXT: addis 5, 5, .LCPI +; CHECK-NEXT: bc 12, 1, .LBB +; CHECK: ori 3, 4, 0 +; CHECK-NEXT: b .LBB +; CHECK-NEXT: .LBB +; CHECK-NEXT: addi 3, 5, 0 +; CHECK-NEXT: .LBB +; CHECK-NEXT: lfs 1, 0(3) +; CHECK-NEXT: blr Index: test/CodeGen/PowerPC/i64_fp_round.ll =================================================================== --- test/CodeGen/PowerPC/i64_fp_round.ll +++ test/CodeGen/PowerPC/i64_fp_round.ll @@ -1,4 +1,5 @@ ; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mattr=-fpcvt < %s | FileCheck %s +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mattr=-fpcvt -ppc-gen-isel=false < %s | FileCheck %s --check-prefix=CHECK-NO-ISEL target datalayout = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v128:128:128-n32:64" target triple = "powerpc64-unknown-linux-gnu" @@ -12,10 +13,16 @@ ; Note that only parts of the sequence are checked for here, to allow ; for minor code generation differences. +;CHECK-LABEL: test +;CHECK-NO-ISEL-LABEL: test ; CHECK: sradi [[REG1:[0-9]+]], 3, 53 ; CHECK: addi [[REG2:[0-9]+]], [[REG1]], 1 ; CHECK: cmpldi [[REG2]], 1 ; CHECK: isel [[REG3:[0-9]+]], {{[0-9]+}}, 3, 1 +; CHECK-NO-ISEL: bc 12, 1, .LBB +; CHECK-NO-ISEL: ori 11, 3, 0 +; CHECK-NO-ISEL-NEXT: b .LBB +; CHECK-NO-ISEL: addi 11, 4, 0 ; CHECK: std [[REG3]], -{{[0-9]+}}(1) Index: test/CodeGen/PowerPC/ifcvt.ll =================================================================== --- test/CodeGen/PowerPC/ifcvt.ll +++ test/CodeGen/PowerPC/ifcvt.ll @@ -1,4 +1,5 @@ ; RUN: llc < %s -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr7 -verify-machineinstrs | FileCheck %s +; RUN: llc < %s -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr7 -verify-machineinstrs -ppc-gen-isel=false | FileCheck --check-prefix=CHECK-NO-ISEL %s target datalayout = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f128:128:128-v128:128:128-n32:64" target triple = "powerpc64-unknown-linux-gnu" @@ -18,10 +19,17 @@ %add37 = add nsw i32 %conv29, %a br label %cond.end -; CHECK: @test +; CHECK-LABEL: @test +; CHECK-NO-ISEL-LABEL: @test ; CHECK: add [[REG:[0-9]+]], ; CHECK: subf [[REG2:[0-9]+]], ; CHECK: isel {{[0-9]+}}, [[REG]], [[REG2]], +; CHECK-NO-ISEL: bc 12, 1, .LBB +; CHECK-NO-ISEL-NEXT: b .LBB +; CHECK-NO-ISEL: addi 5, 6, 0 +; CHECK-NO-ISEL: extsh 5, 5 +; CHECK-NO-ISEL-NEXT: add 3, 3, 5 +; CHECK-NO-ISEL-NEXT: blr cond.end: ; preds = %cond.false, %cond.true %cond = phi i32 [ %sub34, %cond.true ], [ %add37, %cond.false ] Index: test/CodeGen/PowerPC/isel.ll =================================================================== --- test/CodeGen/PowerPC/isel.ll +++ test/CodeGen/PowerPC/isel.ll @@ -2,14 +2,21 @@ target triple = "powerpc64-unknown-linux-gnu" ; RUN: llc -verify-machineinstrs -mcpu=a2 < %s | FileCheck %s ; RUN: llc -verify-machineinstrs -mcpu=pwr7 < %s | FileCheck %s +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -ppc-gen-isel=false < %s | FileCheck --check-prefix=CHECK-NO-ISEL %s define i64 @test1(i64 %a, i64 %b, i64 %c, i64 %d) { entry: %p = icmp uge i64 %a, %b %x = select i1 %p, i64 %c, i64 %d ret i64 %x -; CHECK: @test1 +; CHECK-LABEL: @test1 +; CHECK-NO-ISEL-LABEL: @test1 ; CHECK: isel +; CHECK-NO-ISEL: bc 12, 0, .LBB +; CHECK-NO-ISEL: ori 3, 5, 0 +; CHECK-NO-ISEL-NEXT: blr +; CHECK-NO-ISEL: addi 3, 6, 0 +; CHECK-NO-ISEL-NEXT: blr } define i32 @test2(i32 %a, i32 %b, i32 %c, i32 %d) { @@ -17,7 +24,13 @@ %p = icmp uge i32 %a, %b %x = select i1 %p, i32 %c, i32 %d ret i32 %x -; CHECK: @test2 +; CHECK-LABEL: @test2 +; CHECK-NO-ISEL-LABEL: @test2 ; CHECK: isel +; CHECK-NO-ISEL: bc 12, 0, .LBB +; CHECK-NO-ISEL: ori 3, 5, 0 +; CHECK-NO-ISEL-NEXT: blr +; CHECK-NO-ISEL: addi 3, 6, 0 +; CHECK-NO-ISEL-NEXT: blr } Index: test/CodeGen/PowerPC/optcmp.ll =================================================================== --- test/CodeGen/PowerPC/optcmp.ll +++ test/CodeGen/PowerPC/optcmp.ll @@ -1,4 +1,5 @@ ; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc64-unknown-linux-gnu -mcpu=a2 -mattr=-crbits -disable-ppc-cmp-opt=0 | FileCheck %s +; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc64-unknown-linux-gnu -mcpu=a2 -mattr=-crbits -disable-ppc-cmp-opt=0 -ppc-gen-isel=false | FileCheck --check-prefix=CHECK-NO-ISEL %s target datalayout = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f128:128:128-v128:128:128-n32:64" target triple = "powerpc64-unknown-linux-gnu" @@ -34,9 +35,14 @@ %cond = select i1 %cmp, i64 %a, i64 %b ret i64 %cond -; CHECK: @fool +; CHECK-LABEL: @fool +; CHECK-NO-ISEL-LABEL: @fool ; CHECK: subf. [[REG:[0-9]+]], 4, 3 ; CHECK: isel 3, 3, 4, 1 +; CHECK-NO-ISEL: bc 12, 1, .LBB +; CHECK-NO-ISEL: ori 3, 4, 0 +; CHECK-NO-ISEL: b .LBB + ; CHECK: std [[REG]], 0(5) } @@ -48,9 +54,13 @@ %cond = select i1 %cmp, i64 %a, i64 %b ret i64 %cond -; CHECK: @foolb +; CHECK-LABEL: @foolb +; CHECK-NO-ISEL-LABEL: @foolb ; CHECK: subf. [[REG:[0-9]+]], 4, 3 ; CHECK: isel 3, 4, 3, 1 +; CHECK-NO-ISEL: bc 12, 1, .LBB +; CHECK-NO-ISEL-NEXT: b .LBB +; CHECK-NO-ISEL addi: 3, 4, 0 ; CHECK: std [[REG]], 0(5) } @@ -62,9 +72,13 @@ %cond = select i1 %cmp, i64 %a, i64 %b ret i64 %cond -; CHECK: @foolc +; CHECK-LABEL: @foolc +; CHECK-NO-ISEL-LABEL: @foolc ; CHECK: subf. [[REG:[0-9]+]], 3, 4 ; CHECK: isel 3, 3, 4, 0 +; CHECK-NO-ISEL: bc 12, 0, .LBB +; CHECK-NO-ISEL: ori 3, 4, 0 +; CHECK-NO-ISEL: b .LBB ; CHECK: std [[REG]], 0(5) } @@ -76,9 +90,13 @@ %cond = select i1 %cmp, i64 %a, i64 %b ret i64 %cond -; CHECK: @foold +; CHECK-LABEL: @foold +; CHECK-NO-ISEL-LABEL: @foold ; CHECK: subf. [[REG:[0-9]+]], 3, 4 ; CHECK: isel 3, 3, 4, 1 +; CHECK-NO-ISEL: bc 12, 1, .LBB +; CHECK-NO-ISEL: ori 3, 4, 0 +; CHECK-NO-ISEL: b .LBB ; CHECK: std [[REG]], 0(5) } @@ -90,9 +108,13 @@ %cond = select i1 %cmp, i64 %a, i64 %b ret i64 %cond -; CHECK: @foold2 +; CHECK-LABEL: @foold2 +; CHECK-NO-ISEL-LABEL: @foold2 ; CHECK: subf. [[REG:[0-9]+]], 4, 3 ; CHECK: isel 3, 3, 4, 0 +; CHECK-NO-ISEL: bc 12, 0, .LBB +; CHECK-NO-ISEL: ori 3, 4, 0 +; CHECK-NO-ISEL: b .LBB ; CHECK: std [[REG]], 0(5) } Index: test/CodeGen/PowerPC/p8-isel-sched.ll =================================================================== --- test/CodeGen/PowerPC/p8-isel-sched.ll +++ test/CodeGen/PowerPC/p8-isel-sched.ll @@ -1,4 +1,5 @@ ; RUN: llc -verify-machineinstrs -mcpu=pwr8 < %s | FileCheck %s +; RUN: llc -verify-machineinstrs -mcpu=pwr8 -ppc-gen-isel=false < %s | FileCheck --check-prefix=CHECK-NO-ISEL %s target datalayout = "E-m:e-i64:64-n32:64" target triple = "powerpc64-unknown-linux-gnu" @@ -24,10 +25,18 @@ ; Make sure that we don't schedule all of the isels together, they should be ; intermixed with the adds because each isel starts a new dispatch group. ; CHECK-LABEL: @foo +; CHECK-NO-ISEL-LABEL: @foo ; CHECK: isel +; CHECK-NO-ISEL: bc 12, 2, .LBB +; CHECK-NO-ISEL: ori 7, 12, 0 +; CHECK-NO-ISEL-NEXT: b .LBB +; CHECK-NO-ISEL: addi 7, 11, 0 ; CHECK: addi ; CHECK: isel +; CHECK-NO-ISEL: bc 12, 2, .LBB +; CHECK-NO-ISEL: ori 10, 11, 0 +; CHECK-NO-ISEL-NEXT: b .LBB +; CHECK-NO-ISEL: addi 10, 12, 0 ; CHECK: blr attributes #0 = { nounwind } - Index: test/CodeGen/PowerPC/ppc-crbits-onoff.ll =================================================================== --- test/CodeGen/PowerPC/ppc-crbits-onoff.ll +++ test/CodeGen/PowerPC/ppc-crbits-onoff.ll @@ -1,4 +1,5 @@ ; RUN: llc -verify-machineinstrs -mcpu=pwr7 < %s | FileCheck %s +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -ppc-gen-isel=false < %s | FileCheck --check-prefix=CHECK-NO-ISEL %s target datalayout = "E-m:e-i64:64-n32:64" target triple = "powerpc64-unknown-linux-gnu" @@ -12,10 +13,15 @@ ret i32 %and ; CHECK-LABEL: @crbitsoff +; CHECK-NO-ISEL-LABEL: @crbitsoff ; CHECK-DAG: cmplwi {{[0-9]+}}, 3, 0 ; CHECK-DAG: li [[REG2:[0-9]+]], 1 ; CHECK-DAG: cntlzw [[REG3:[0-9]+]], ; CHECK: isel [[REG4:[0-9]+]], 0, [[REG2]] +; CHECK-NO-ISEL: bc 12, 2, .LBB +; CHECK-NO-ISEL: ori 4, 5, 0 +; CHECK-NO-ISEL-NEXT: b .LBB +; CHECK-NO-ISEL: addi 4, 0, 0 ; CHECK: and 3, [[REG4]], [[REG3]] ; CHECK: blr } @@ -29,11 +35,16 @@ ret i32 %and ; CHECK-LABEL: @crbitson +; CHECK-NO-ISEL-LABEL: @crbitson ; CHECK-DAG: cmpwi {{[0-9]+}}, 3, 0 ; CHECK-DAG: cmpwi {{[0-9]+}}, 4, 0 ; CHECK-DAG: li [[REG2:[0-9]+]], 1 ; CHECK-DAG: crorc [[REG3:[0-9]+]], ; CHECK: isel 3, 0, [[REG2]], [[REG3]] +; CHECK-NO-ISEL: bc 12, 20, .LBB +; CHECK-NO-ISEL-NEXT: blr +; CHECK-NO-ISEL: addi 3, 0, 0 +; CHECK-NO-ISEL-NEXT: blr ; CHECK: blr } Index: test/CodeGen/PowerPC/select-i1-vs-i1.ll =================================================================== --- test/CodeGen/PowerPC/select-i1-vs-i1.ll +++ test/CodeGen/PowerPC/select-i1-vs-i1.ll @@ -1,4 +1,5 @@ ; RUN: llc -verify-machineinstrs < %s | FileCheck %s +; RUN: llc -verify-machineinstrs -ppc-gen-isel=false < %s | FileCheck --check-prefix=CHECK-NO-ISEL %s target datalayout = "E-m:e-i64:64-n32:64" target triple = "powerpc64-unknown-linux-gnu" @@ -15,10 +16,16 @@ ret i32 %cond ; CHECK-LABEL: @testi32slt +; CHECK-NO-ISEL-LABEL: @testi32slt ; CHECK-DAG: cmpw {{[0-9]+}}, 5, 6 ; CHECK-DAG: cmpw {{[0-9]+}}, 3, 4 ; CHECK: crandc [[REG1:[0-9]+]], {{[0-9]+}}, {{[0-9]+}} ; CHECK: isel 3, 7, 8, [[REG1]] +; CHECK-NO-ISEL: bc 12, 20, .LBB +; CHECK-NO-ISEL: ori 3, 8, 0 +; CHECK-NO-ISEL-NEXT: blr +; CHECK-NO-ISEL: addi 3, 7, 0 +; CHECK-NO-ISEL-NEXT: blr ; CHECK: blr } @@ -30,11 +37,16 @@ %cond = select i1 %cmp3, i32 %a1, i32 %a2 ret i32 %cond -; CHECK-LABEL: @testi32ult +; CHECK-NO-ISEL-LABEL: @testi32ult ; CHECK-DAG: cmpw {{[0-9]+}}, 5, 6 ; CHECK-DAG: cmpw {{[0-9]+}}, 3, 4 ; CHECK: crandc [[REG1:[0-9]+]], {{[0-9]+}}, {{[0-9]+}} ; CHECK: isel 3, 7, 8, [[REG1]] +; CHECK-NO-ISEL: bc 12, 20, .LBB +; CHECK-NO-ISEL: ori 3, 8, 0 +; CHECK-NO-ISEL-NEXT: blr +; CHECK-NO-ISEL: addi 3, 7, 0 +; CHECK-NO-ISEL-NEXT: blr ; CHECK: blr } @@ -47,10 +59,16 @@ ret i32 %cond ; CHECK-LABEL: @testi32sle +; CHECK-NO-ISEL-LABEL: @testi32sle ; CHECK-DAG: cmpw {{[0-9]+}}, 5, 6 ; CHECK-DAG: cmpw {{[0-9]+}}, 3, 4 ; CHECK: crorc [[REG1:[0-9]+]], {{[0-9]+}}, {{[0-9]+}} ; CHECK: isel 3, 7, 8, [[REG1]] +; CHECK-NO-ISEL: bc 12, 20, .LBB +; CHECK-NO-ISEL: ori 3, 8, 0 +; CHECK-NO-ISEL-NEXT: blr +; CHECK-NO-ISEL: addi 3, 7, 0 +; CHECK-NO-ISEL-NEXT: blr ; CHECK: blr } @@ -63,10 +81,16 @@ ret i32 %cond ; CHECK-LABEL: @testi32ule +; CHECK-NO-ISEL-LABEL: @testi32ule ; CHECK-DAG: cmpw {{[0-9]+}}, 5, 6 ; CHECK-DAG: cmpw {{[0-9]+}}, 3, 4 ; CHECK: crorc [[REG1:[0-9]+]], {{[0-9]+}}, {{[0-9]+}} ; CHECK: isel 3, 7, 8, [[REG1]] +; CHECK-NO-ISEL: bc 12, 20, .LBB +; CHECK-NO-ISEL: ori 3, 8, 0 +; CHECK-NO-ISEL-NEXT: blr +; CHECK-NO-ISEL: addi 3, 7, 0 +; CHECK-NO-ISEL-NEXT: blr ; CHECK: blr } @@ -79,10 +103,16 @@ ret i32 %cond ; CHECK-LABEL: @testi32eq +; CHECK-NO-ISEL-LABEL: @testi32eq ; CHECK-DAG: cmpw {{[0-9]+}}, 5, 6 ; CHECK-DAG: cmpw {{[0-9]+}}, 3, 4 ; CHECK: creqv [[REG1:[0-9]+]], {{[0-9]+}}, {{[0-9]+}} ; CHECK: isel 3, 7, 8, [[REG1]] +; CHECK-NO-ISEL: bc 12, 20, .LBB +; CHECK-NO-ISEL: ori 3, 8, 0 +; CHECK-NO-ISEL-NEXT: blr +; CHECK-NO-ISEL: addi 3, 7, 0 +; CHECK-NO-ISEL-NEXT: blr ; CHECK: blr } @@ -95,10 +125,16 @@ ret i32 %cond ; CHECK-LABEL: @testi32sge +; CHECK-NO-ISEL-LABEL: @testi32sge ; CHECK-DAG: cmpw {{[0-9]+}}, 5, 6 ; CHECK-DAG: cmpw {{[0-9]+}}, 3, 4 ; CHECK: crorc [[REG1:[0-9]+]], {{[0-9]+}}, {{[0-9]+}} ; CHECK: isel 3, 7, 8, [[REG1]] +; CHECK-NO-ISEL: bc 12, 20, .LBB +; CHECK-NO-ISEL: ori 3, 8, 0 +; CHECK-NO-ISEL-NEXT: blr +; CHECK-NO-ISEL: addi 3, 7, 0 +; CHECK-NO-ISEL-NEXT: blr ; CHECK: blr } @@ -111,10 +147,16 @@ ret i32 %cond ; CHECK-LABEL: @testi32uge +; CHECK-NO-ISEL-LABEL: @testi32uge ; CHECK-DAG: cmpw {{[0-9]+}}, 5, 6 ; CHECK-DAG: cmpw {{[0-9]+}}, 3, 4 ; CHECK: crorc [[REG1:[0-9]+]], {{[0-9]+}}, {{[0-9]+}} ; CHECK: isel 3, 7, 8, [[REG1]] +; CHECK-NO-ISEL: bc 12, 20, .LBB +; CHECK-NO-ISEL: ori 3, 8, 0 +; CHECK-NO-ISEL-NEXT: blr +; CHECK-NO-ISEL: addi 3, 7, 0 +; CHECK-NO-ISEL-NEXT: blr ; CHECK: blr } @@ -127,10 +169,16 @@ ret i32 %cond ; CHECK-LABEL: @testi32sgt +; CHECK-NO-ISEL-LABEL: @testi32sgt ; CHECK-DAG: cmpw {{[0-9]+}}, 5, 6 ; CHECK-DAG: cmpw {{[0-9]+}}, 3, 4 ; CHECK: crandc [[REG1:[0-9]+]], {{[0-9]+}}, {{[0-9]+}} ; CHECK: isel 3, 7, 8, [[REG1]] +; CHECK-NO-ISEL: bc 12, 20, .LBB +; CHECK-NO-ISEL: ori 3, 8, 0 +; CHECK-NO-ISEL-NEXT: blr +; CHECK-NO-ISEL: addi 3, 7, 0 +; CHECK-NO-ISEL-NEXT: blr ; CHECK: blr } @@ -143,10 +191,16 @@ ret i32 %cond ; CHECK-LABEL: @testi32ugt +; CHECK-NO-ISEL-LABEL: @testi32ugt ; CHECK-DAG: cmpw {{[0-9]+}}, 5, 6 ; CHECK-DAG: cmpw {{[0-9]+}}, 3, 4 ; CHECK: crandc [[REG1:[0-9]+]], {{[0-9]+}}, {{[0-9]+}} ; CHECK: isel 3, 7, 8, [[REG1]] +; CHECK-NO-ISEL: bc 12, 20, .LBB +; CHECK-NO-ISEL: ori 3, 8, 0 +; CHECK-NO-ISEL-NEXT: blr +; CHECK-NO-ISEL: addi 3, 7, 0 +; CHECK-NO-ISEL-NEXT: blr ; CHECK: blr } @@ -159,10 +213,16 @@ ret i32 %cond ; CHECK-LABEL: @testi32ne +; CHECK-NO-ISEL-LABEL: @testi32ne ; CHECK-DAG: cmpw {{[0-9]+}}, 5, 6 ; CHECK-DAG: cmpw {{[0-9]+}}, 3, 4 ; CHECK: crxor [[REG1:[0-9]+]], {{[0-9]+}}, {{[0-9]+}} ; CHECK: isel 3, 7, 8, [[REG1]] +; CHECK-NO-ISEL: bc 12, 20, .LBB +; CHECK-NO-ISEL: ori 3, 8, 0 +; CHECK-NO-ISEL-NEXT: blr +; CHECK-NO-ISEL: addi 3, 7, 0 +; CHECK-NO-ISEL-NEXT: blr ; CHECK: blr } @@ -175,10 +235,16 @@ ret i64 %cond ; CHECK-LABEL: @testi64slt +; CHECK-NO-ISEL-LABEL: @testi64slt ; CHECK-DAG: cmpd {{([0-9]+, )?}}5, 6 ; CHECK-DAG: cmpd {{([0-9]+, )?}}3, 4 ; CHECK: crandc [[REG1:[0-9]+]], {{[0-9]+}}, {{[0-9]+}} ; CHECK: isel 3, 7, 8, [[REG1]] +; CHECK-NO-ISEL: bc 12, 20, .LBB +; CHECK-NO-ISEL: ori 3, 8, 0 +; CHECK-NO-ISEL-NEXT: blr +; CHECK-NO-ISEL: addi 3, 7, 0 +; CHECK-NO-ISEL-NEXT: blr ; CHECK: blr } @@ -191,10 +257,16 @@ ret i64 %cond ; CHECK-LABEL: @testi64ult +; CHECK-NO-ISEL-LABEL: @testi64ult ; CHECK-DAG: cmpd {{([0-9]+, )?}}5, 6 ; CHECK-DAG: cmpd {{([0-9]+, )?}}3, 4 ; CHECK: crandc [[REG1:[0-9]+]], {{[0-9]+}}, {{[0-9]+}} ; CHECK: isel 3, 7, 8, [[REG1]] +; CHECK-NO-ISEL: bc 12, 20, .LBB +; CHECK-NO-ISEL: ori 3, 8, 0 +; CHECK-NO-ISEL-NEXT: blr +; CHECK-NO-ISEL: addi 3, 7, 0 +; CHECK-NO-ISEL-NEXT: blr ; CHECK: blr } @@ -207,10 +279,16 @@ ret i64 %cond ; CHECK-LABEL: @testi64sle +; CHECK-NO-ISEL-LABEL: @testi64sle ; CHECK-DAG: cmpd {{([0-9]+, )?}}5, 6 ; CHECK-DAG: cmpd {{([0-9]+, )?}}3, 4 ; CHECK: crorc [[REG1:[0-9]+]], {{[0-9]+}}, {{[0-9]+}} ; CHECK: isel 3, 7, 8, [[REG1]] +; CHECK-NO-ISEL: bc 12, 20, .LBB +; CHECK-NO-ISEL: ori 3, 8, 0 +; CHECK-NO-ISEL-NEXT: blr +; CHECK-NO-ISEL: addi 3, 7, 0 +; CHECK-NO-ISEL-NEXT: blr ; CHECK: blr } @@ -223,10 +301,16 @@ ret i64 %cond ; CHECK-LABEL: @testi64ule +; CHECK-NO-ISEL-LABEL: @testi64ule ; CHECK-DAG: cmpd {{([0-9]+, )?}}5, 6 ; CHECK-DAG: cmpd {{([0-9]+, )?}}3, 4 ; CHECK: crorc [[REG1:[0-9]+]], {{[0-9]+}}, {{[0-9]+}} ; CHECK: isel 3, 7, 8, [[REG1]] +; CHECK-NO-ISEL: bc 12, 20, .LBB +; CHECK-NO-ISEL: ori 3, 8, 0 +; CHECK-NO-ISEL-NEXT: blr +; CHECK-NO-ISEL: addi 3, 7, 0 +; CHECK-NO-ISEL-NEXT: blr ; CHECK: blr } @@ -239,10 +323,16 @@ ret i64 %cond ; CHECK-LABEL: @testi64eq +; CHECK-NO-ISEL-LABEL: @testi64eq ; CHECK-DAG: cmpd {{([0-9]+, )?}}5, 6 ; CHECK-DAG: cmpd {{([0-9]+, )?}}3, 4 ; CHECK: creqv [[REG1:[0-9]+]], {{[0-9]+}}, {{[0-9]+}} ; CHECK: isel 3, 7, 8, [[REG1]] +; CHECK-NO-ISEL: bc 12, 20, .LBB +; CHECK-NO-ISEL: ori 3, 8, 0 +; CHECK-NO-ISEL-NEXT: blr +; CHECK-NO-ISEL: addi 3, 7, 0 +; CHECK-NO-ISEL-NEXT: blr ; CHECK: blr } @@ -255,10 +345,16 @@ ret i64 %cond ; CHECK-LABEL: @testi64sge +; CHECK-NO-ISEL-LABEL: @testi64sge ; CHECK-DAG: cmpd {{([0-9]+, )?}}5, 6 ; CHECK-DAG: cmpd {{([0-9]+, )?}}3, 4 ; CHECK: crorc [[REG1:[0-9]+]], {{[0-9]+}}, {{[0-9]+}} ; CHECK: isel 3, 7, 8, [[REG1]] +; CHECK-NO-ISEL: bc 12, 20, .LBB +; CHECK-NO-ISEL: ori 3, 8, 0 +; CHECK-NO-ISEL-NEXT: blr +; CHECK-NO-ISEL: addi 3, 7, 0 +; CHECK-NO-ISEL-NEXT: blr ; CHECK: blr } @@ -271,10 +367,16 @@ ret i64 %cond ; CHECK-LABEL: @testi64uge +; CHECK-NO-ISEL-LABEL: @testi64uge ; CHECK-DAG: cmpd {{([0-9]+, )?}}5, 6 ; CHECK-DAG: cmpd {{([0-9]+, )?}}3, 4 ; CHECK: crorc [[REG1:[0-9]+]], {{[0-9]+}}, {{[0-9]+}} ; CHECK: isel 3, 7, 8, [[REG1]] +; CHECK-NO-ISEL: bc 12, 20, .LBB +; CHECK-NO-ISEL: ori 3, 8, 0 +; CHECK-NO-ISEL-NEXT: blr +; CHECK-NO-ISEL: addi 3, 7, 0 +; CHECK-NO-ISEL-NEXT: blr ; CHECK: blr } @@ -287,10 +389,16 @@ ret i64 %cond ; CHECK-LABEL: @testi64sgt +; CHECK-NO-ISEL-LABEL: @testi64sgt ; CHECK-DAG: cmpd {{([0-9]+, )?}}5, 6 ; CHECK-DAG: cmpd {{([0-9]+, )?}}3, 4 ; CHECK: crandc [[REG1:[0-9]+]], {{[0-9]+}}, {{[0-9]+}} ; CHECK: isel 3, 7, 8, [[REG1]] +; CHECK-NO-ISEL: bc 12, 20, .LBB +; CHECK-NO-ISEL: ori 3, 8, 0 +; CHECK-NO-ISEL-NEXT: blr +; CHECK-NO-ISEL: addi 3, 7, 0 +; CHECK-NO-ISEL-NEXT: blr ; CHECK: blr } @@ -303,10 +411,16 @@ ret i64 %cond ; CHECK-LABEL: @testi64ugt +; CHECK-NO-ISEL-LABEL: @testi64ugt ; CHECK-DAG: cmpd {{([0-9]+, )?}}5, 6 ; CHECK-DAG: cmpd {{([0-9]+, )?}}3, 4 ; CHECK: crandc [[REG1:[0-9]+]], {{[0-9]+}}, {{[0-9]+}} ; CHECK: isel 3, 7, 8, [[REG1]] +; CHECK-NO-ISEL: bc 12, 20, .LBB +; CHECK-NO-ISEL: ori 3, 8, 0 +; CHECK-NO-ISEL-NEXT: blr +; CHECK-NO-ISEL: addi 3, 7, 0 +; CHECK-NO-ISEL-NEXT: blr ; CHECK: blr } @@ -319,10 +433,16 @@ ret i64 %cond ; CHECK-LABEL: @testi64ne +; CHECK-NO-ISEL-LABEL: @testi64ne ; CHECK-DAG: cmpd {{([0-9]+, )?}}5, 6 ; CHECK-DAG: cmpd {{([0-9]+, )?}}3, 4 ; CHECK: crxor [[REG1:[0-9]+]], {{[0-9]+}}, {{[0-9]+}} ; CHECK: isel 3, 7, 8, [[REG1]] +; CHECK-NO-ISEL: bc 12, 20, .LBB +; CHECK-NO-ISEL: ori 3, 8, 0 +; CHECK-NO-ISEL-NEXT: blr +; CHECK-NO-ISEL: addi 3, 7, 0 +; CHECK-NO-ISEL-NEXT: blr ; CHECK: blr } Index: test/CodeGen/PowerPC/subreg-postra-2.ll =================================================================== --- test/CodeGen/PowerPC/subreg-postra-2.ll +++ test/CodeGen/PowerPC/subreg-postra-2.ll @@ -1,4 +1,5 @@ ; RUN: llc -verify-machineinstrs -mcpu=pwr7 < %s | FileCheck %s +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -ppc-gen-isel=false < %s | FileCheck --check-prefix=CHECK-NO-ISEL %s target datalayout = "E-m:e-i64:64-n32:64" target triple = "powerpc64-unknown-linux-gnu" @@ -31,10 +32,15 @@ br i1 %tobool419, label %if.end421, label %if.then420 ; CHECK-LABEL: @jbd2_journal_commit_transaction +; CHECK-NO-ISEL-LABEL: @jbd2_journal_commit_transaction ; CHECK: andi. ; CHECK: crmove [[REG:[0-9]+]], 1 ; CHECK: stdcx. ; CHECK: isel {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}}, [[REG]] +; CHECK-NO-ISEL: bc 12, 20, .LBB +; CHECK-NO-ISEL: ori 4, 7, 0 +; CHECK-NO-ISEL-NEXT: b .LBB +; CHECK-NO-ISEL: addi 4, 3, 0 if.then420: ; preds = %while.end418 unreachable Index: test/CodeGen/PowerPC/subreg-postra.ll =================================================================== --- test/CodeGen/PowerPC/subreg-postra.ll +++ test/CodeGen/PowerPC/subreg-postra.ll @@ -1,4 +1,5 @@ ; RUN: llc -verify-machineinstrs -mcpu=pwr7 < %s | FileCheck %s +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -ppc-gen-isel=false < %s | FileCheck --check-prefix=CHECK-NO-ISEL %s target datalayout = "E-m:e-i64:64-n32:64" target triple = "powerpc64-unknown-linux-gnu" @@ -145,10 +146,15 @@ br i1 %inp8, label %while.end418, label %while.body392 ; CHECK-LABEL: @jbd2_journal_commit_transaction +; CHECK-NO-ISEL-LABEL: @jbd2_journal_commit_transaction ; CHECK: andi. ; CHECK: crmove ; CHECK: stdcx. ; CHECK: isel {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}}, +; CHECK-NO-ISEL: bc 12, 1, .LBB +; CHECK-NO-ISEL: ori 30, 3, 0 +; CHECK-NO-ISEL: b .LBB + while.end418: ; preds = %wait_on_buffer.exit1319, %do.body378 %err.4.lcssa = phi i32 [ %inp2, %do.body378 ], [ %.err.4, %wait_on_buffer.exit1319 ]