The MIR code coming out of ``-stop-after``/``-stop-before`` is very verbose;
Tests are more accessible and future proof when simplified:
+- Use the ``-simplify-mir`` option with llc.
+
- Machine function attributes often have default values or the test works just
as well with default values. Typical candidates for this are: `alignment:`,
`exposesReturnsTwice`, `legalized`, `regBankSelected`, `selected`.
namespace llvm {
+class MachineBasicBlock;
class MachineFunction;
class Module;
class raw_ostream;
+template <typename T> class SmallVectorImpl;
/// Print LLVM IR using the MIR serialization format to the given output stream.
void printMIR(raw_ostream &OS, const Module &M);
/// output stream.
void printMIR(raw_ostream &OS, const MachineFunction &MF);
+/// Determine a possible list of successors of a basic block based on the
+/// basic block machine operand being used inside the block. This should give
+/// you the correct list of successor blocks in most cases except for things
+/// like jump tables where the basic block references can't easily be found.
+/// The MIRPRinter will skip printing successors if they match the result of
+/// this funciton and the parser will use this function to construct a list if
+/// it is missing.
+void guessSuccessors(const MachineBasicBlock &MBB,
+ SmallVectorImpl<MachineBasicBlock*> &Successors,
+ bool &IsFallthrough);
+
} // end namespace llvm
#endif
//===----------------------------------------------------------------------===//
#include "MIParser.h"
+
#include "MILexer.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/AsmParser/Parser.h"
#include "llvm/AsmParser/SlotMapping.h"
+#include "llvm/CodeGen/MIRPrinter.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
bool
parseBasicBlockDefinition(DenseMap<unsigned, MachineBasicBlock *> &MBBSlots);
- bool parseBasicBlock(MachineBasicBlock &MBB);
+ bool parseBasicBlock(MachineBasicBlock &MBB,
+ MachineBasicBlock *&AddFalthroughFrom);
bool parseBasicBlockLiveins(MachineBasicBlock &MBB);
bool parseBasicBlockSuccessors(MachineBasicBlock &MBB);
return false;
}
-bool MIParser::parseBasicBlock(MachineBasicBlock &MBB) {
+bool MIParser::parseBasicBlock(MachineBasicBlock &MBB,
+ MachineBasicBlock *&AddFalthroughFrom) {
// Skip the definition.
assert(Token.is(MIToken::MachineBasicBlockLabel));
lex();
//
// is equivalent to
// liveins: %edi, %esi
+ bool ExplicitSuccesors = false;
while (true) {
if (Token.is(MIToken::kw_successors)) {
if (parseBasicBlockSuccessors(MBB))
return true;
+ ExplicitSuccesors = true;
} else if (Token.is(MIToken::kw_liveins)) {
if (parseBasicBlockLiveins(MBB))
return true;
// Parse the instructions.
bool IsInBundle = false;
MachineInstr *PrevMI = nullptr;
- while (true) {
- if (Token.is(MIToken::MachineBasicBlockLabel) || Token.is(MIToken::Eof))
- return false;
- else if (consumeIfPresent(MIToken::Newline))
+ while (!Token.is(MIToken::MachineBasicBlockLabel) &&
+ !Token.is(MIToken::Eof)) {
+ if (consumeIfPresent(MIToken::Newline))
continue;
if (consumeIfPresent(MIToken::rbrace)) {
// The first parsing pass should verify that all closing '}' have an
assert(Token.isNewlineOrEOF() && "MI is not fully parsed");
lex();
}
+
+ // Construct successor list by searching for basic block machine operands.
+ if (!ExplicitSuccesors) {
+ SmallVector<MachineBasicBlock*,4> Successors;
+ bool IsFallthrough;
+ guessSuccessors(MBB, Successors, IsFallthrough);
+ for (MachineBasicBlock *Succ : Successors)
+ MBB.addSuccessor(Succ);
+
+ if (IsFallthrough) {
+ AddFalthroughFrom = &MBB;
+ } else {
+ MBB.normalizeSuccProbs();
+ }
+ }
+
return false;
}
// The first parsing pass should have verified that this token is a MBB label
// in the 'parseBasicBlockDefinitions' method.
assert(Token.is(MIToken::MachineBasicBlockLabel));
+ MachineBasicBlock *AddFalthroughFrom = nullptr;
do {
MachineBasicBlock *MBB = nullptr;
if (parseMBBReference(MBB))
return true;
- if (parseBasicBlock(*MBB))
+ if (AddFalthroughFrom) {
+ if (!AddFalthroughFrom->isSuccessor(MBB))
+ AddFalthroughFrom->addSuccessor(MBB);
+ AddFalthroughFrom->normalizeSuccProbs();
+ AddFalthroughFrom = nullptr;
+ }
+ if (parseBasicBlock(*MBB, AddFalthroughFrom))
return true;
// The method 'parseBasicBlock' should parse the whole block until the next
// block or the end of file.
//
//===----------------------------------------------------------------------===//
-#include "MIRPrinter.h"
+#include "llvm/CodeGen/MIRPrinter.h"
+
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallBitVector.h"
#include "llvm/CodeGen/GlobalISel/RegisterBank.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Options.h"
#include "llvm/Support/YAMLTraits.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetInstrInfo.h"
using namespace llvm;
+static cl::opt<bool> SimplifyMIR("simplify-mir",
+ cl::desc("Leave out unnecessary information when printing MIR"));
+
namespace {
/// This structure describes how to print out stack object references.
const DenseMap<const uint32_t *, unsigned> &RegisterMaskIds;
const DenseMap<int, FrameIndexOperand> &StackObjectOperandMapping;
+ bool canPredictBranchProbabilities(const MachineBasicBlock &MBB) const;
+ bool canPredictSuccessors(const MachineBasicBlock &MBB) const;
+
public:
MIPrinter(raw_ostream &OS, ModuleSlotTracker &MST,
const DenseMap<const uint32_t *, unsigned> &RegisterMaskIds,
RegisterMaskIds.insert(std::make_pair(Mask, I++));
}
+void llvm::guessSuccessors(const MachineBasicBlock &MBB,
+ SmallVectorImpl<MachineBasicBlock*> &Result,
+ bool &IsFallthrough) {
+ SmallPtrSet<MachineBasicBlock*,8> Seen;
+
+ for (const MachineInstr &MI : MBB) {
+ if (MI.isPHI())
+ continue;
+ for (const MachineOperand &MO : MI.operands()) {
+ if (!MO.isMBB())
+ continue;
+ MachineBasicBlock *Succ = MO.getMBB();
+ auto RP = Seen.insert(Succ);
+ if (RP.second)
+ Result.push_back(Succ);
+ }
+ }
+ MachineBasicBlock::const_iterator I = MBB.getLastNonDebugInstr();
+ IsFallthrough = I == MBB.end() || !I->isBarrier();
+}
+
+bool
+MIPrinter::canPredictBranchProbabilities(const MachineBasicBlock &MBB) const {
+ if (MBB.succ_size() <= 1)
+ return true;
+ if (!MBB.hasSuccessorProbabilities())
+ return true;
+
+ SmallVector<BranchProbability,8> Normalized(MBB.Probs.begin(),
+ MBB.Probs.end());
+ BranchProbability::normalizeProbabilities(Normalized.begin(),
+ Normalized.end());
+ SmallVector<BranchProbability,8> Equal(Normalized.size());
+ BranchProbability::normalizeProbabilities(Equal.begin(), Equal.end());
+
+ return std::equal(Normalized.begin(), Normalized.end(), Equal.begin());
+}
+
+bool MIPrinter::canPredictSuccessors(const MachineBasicBlock &MBB) const {
+ SmallVector<MachineBasicBlock*,8> GuessedSuccs;
+ bool GuessedFallthrough;
+ guessSuccessors(MBB, GuessedSuccs, GuessedFallthrough);
+ if (GuessedFallthrough) {
+ const MachineFunction &MF = *MBB.getParent();
+ MachineFunction::const_iterator NextI = std::next(MBB.getIterator());
+ if (NextI != MF.end()) {
+ MachineBasicBlock *Next = const_cast<MachineBasicBlock*>(&*NextI);
+ if (!is_contained(GuessedSuccs, Next))
+ GuessedSuccs.push_back(Next);
+ }
+ }
+ if (GuessedSuccs.size() != MBB.succ_size())
+ return false;
+ return std::equal(MBB.succ_begin(), MBB.succ_end(), GuessedSuccs.begin());
+}
+
+
void MIPrinter::print(const MachineBasicBlock &MBB) {
assert(MBB.getNumber() >= 0 && "Invalid MBB number");
OS << "bb." << MBB.getNumber();
bool HasLineAttributes = false;
// Print the successors
- if (!MBB.succ_empty()) {
+ bool canPredictProbs = canPredictBranchProbabilities(MBB);
+ if (!MBB.succ_empty() && (!SimplifyMIR || !canPredictProbs ||
+ !canPredictSuccessors(MBB))) {
OS.indent(2) << "successors: ";
for (auto I = MBB.succ_begin(), E = MBB.succ_end(); I != E; ++I) {
if (I != MBB.succ_begin())
OS << ", ";
printMBBReference(**I);
- if (MBB.hasSuccessorProbabilities())
+ if (!SimplifyMIR || !canPredictProbs)
OS << '('
<< format("0x%08" PRIx32, MBB.getSuccProbability(I).getNumerator())
<< ')';
//
//===----------------------------------------------------------------------===//
-#include "MIRPrinter.h"
+#include "llvm/CodeGen/MIRPrinter.h"
+
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MIRYamlMapping.h"
%x9 = ADRP target-flags(aarch64-page, aarch64-got) @g5
bb.13:
- successors: %bb.14
; Cannot produce a LOH for multiple users
; CHECK-NOT: MCLOH_AdrpAdd
%x10 = ADRP target-flags(aarch64-page) @g0
tracksRegLiveness: true
body: |
bb.0:
- successors: %bb.1, %bb.2
liveins: %x0, %x1
%x0 = COPY %x1
CBNZX %x1, %bb.2
bb.1:
- successors: %bb.3
-
%x0 = COPY %xzr
B %bb.3
bb.2:
- successors: %bb.3
liveins: %x1
%x0 = LDRXui %x1, 0
tracksRegLiveness: true
body: |
bb.0:
- successors: %bb.1, %bb.2
liveins: %x0, %x1
%x1 = COPY %x0
CBNZX %x1, %bb.2
bb.1:
- successors: %bb.3
-
%x0 = COPY %xzr
B %bb.3
bb.2:
- successors: %bb.3
liveins: %x1
%x0 = LDRXui %x1, 0
tracksRegLiveness: true
body: |
bb.0:
- successors: %bb.1, %bb.2
liveins: %x0, %x1, %x2
%x0 = COPY %x1
CBNZX %x1, %bb.2
bb.1:
- successors: %bb.3
-
%x0 = COPY %xzr
B %bb.3
bb.2:
- successors: %bb.3
liveins: %x1
%x0 = LDRXui %x1, 0
tracksRegLiveness: true
body: |
bb.0:
- successors: %bb.1, %bb.2
liveins: %x0, %x1, %x2
%x1 = COPY %x0
CBNZX %x1, %bb.2
bb.1:
- successors: %bb.3
-
%x0 = COPY %xzr
B %bb.3
bb.2:
- successors: %bb.3
liveins: %x1
%x0 = LDRXui %x1, 0
tracksRegLiveness: true
body: |
bb.0:
- successors: %bb.1, %bb.2
liveins: %x0, %x1, %x2
%x1 = COPY %x0
CBNZX %x1, %bb.2
bb.1:
- successors: %bb.3
-
%x0 = COPY %xzr
B %bb.3
bb.2:
- successors: %bb.3
liveins: %x1
%x0 = LDRXui %x1, 0
tracksRegLiveness: true
body: |
bb.0:
- successors: %bb.1, %bb.2
liveins: %x0, %x1, %x2
%x2 = COPY %x0
CBNZX %x1, %bb.2
bb.1:
- successors: %bb.3
-
%x0 = COPY %xzr
B %bb.3
bb.2:
- successors: %bb.3
liveins: %x1
%x0 = LDRXui %x1, 0
tracksRegLiveness: true
body: |
bb.0:
- successors: %bb.1, %bb.2
liveins: %x0, %x1, %x2
%x2 = COPY %x0
CBNZX %x1, %bb.2
bb.1:
- successors: %bb.3
-
%x0 = COPY %xzr
B %bb.3
bb.2:
- successors: %bb.3
liveins: %x1
%x0 = LDRXui %x1, 0
tracksRegLiveness: true
body: |
bb.0:
- successors: %bb.1, %bb.2
liveins: %x0, %x1
%x1 = COPY %x0
CBNZX %x1, %bb.2
bb.1:
- successors: %bb.3
liveins: %x0, %x2
%x0, %x1 = LDPXi %x2, 0
B %bb.3
bb.2:
- successors: %bb.3
liveins: %x1
%x0 = LDRXui %x1, 0
tracksRegLiveness: true
body: |
bb.0:
- successors: %bb.1, %bb.2
liveins: %x0, %x1
CBNZX %x0, %bb.2
bb.1:
- successors: %bb.3
liveins: %x0, %x2
%x0 = COPY %xzr
B %bb.3
bb.2:
- successors: %bb.1, %bb.3
liveins: %x1
%x0 = LDRXui %x1, 0
tracksRegLiveness: true
body: |
bb.0.entry:
- successors: %bb.1, %bb.2
liveins: %w0, %x1
dead %wzr = SUBSWri killed %w0, 7, 0, implicit-def %nzcv
B %bb.1
bb.1:
- successors: %bb.2
liveins: %x1
%w0 = MOVi32imm 7
tracksRegLiveness: true
body: |
bb.0.entry:
- successors: %bb.1, %bb.2
liveins: %x0, %x1
dead %xzr = SUBSXri killed %x0, 7, 0, implicit-def %nzcv
B %bb.1
bb.1:
- successors: %bb.2
liveins: %x1
%w0 = MOVi32imm 7, implicit-def %x0
tracksRegLiveness: true
body: |
bb.0.entry:
- successors: %bb.1, %bb.2
liveins: %x0, %x1
dead %xzr = SUBSXri killed %x0, 7, 0, implicit-def %nzcv
B %bb.1
bb.1:
- successors: %bb.2
liveins: %x1
%w0 = MOVi32imm 7
tracksRegLiveness: true
body: |
bb.0.entry:
- successors: %bb.1, %bb.2
liveins: %w0, %x1
dead %wzr = SUBSWri killed %w0, 7, 0, implicit-def %nzcv
B %bb.1
bb.1:
- successors: %bb.2
liveins: %x1
%w0 = MOVi32imm 7, implicit-def %x0
tracksRegLiveness: true
body: |
bb.0.entry:
- successors: %bb.1, %bb.2
liveins: %w0, %x1, %x2
dead %wzr = SUBSWri killed %w0, 7, 0, implicit-def %nzcv
B %bb.1
bb.1:
- successors: %bb.2
liveins: %x1
%w0 = MOVi32imm 7
tracksRegLiveness: true
body: |
bb.0.entry:
- successors: %bb.1, %bb.2
liveins: %w0, %x1, %x2
dead %wzr = SUBSWri killed %w0, 7, 0, implicit-def %nzcv
B %bb.1
bb.1:
- successors: %bb.2
liveins: %x1, %x2
%w0 = LDRWui %x1, 0
tracksRegLiveness: true
body: |
bb.0.entry:
- successors: %bb.1, %bb.2
liveins: %w0, %x1
dead %wzr = SUBSWri %w0, 7, 0, implicit-def %nzcv
B %bb.1
bb.1:
- successors: %bb.2
liveins: %x1
%w2 = MOVi32imm 7
tracksRegLiveness: true
body: |
bb.0.entry:
- successors: %bb.1, %bb.2
liveins: %w0, %x1
dead %w0 = SUBSWri killed %w0, 7, 0, implicit-def %nzcv
B %bb.1
bb.1:
- successors: %bb.2
liveins: %x1
%w0 = MOVi32imm 7
tracksRegLiveness: true
body: |
bb.0.entry:
- successors: %bb.1, %bb.2
liveins: %x0, %x1
CBNZX killed %x0, %bb.2
B %bb.1
bb.1:
- successors: %bb.2
liveins: %x1
%x0 = MOVi64imm 4252017623040
tracksRegLiveness: true
body: |
bb.0.entry:
- successors: %bb.1, %bb.2
liveins: %w0, %x1
dead %wzr = ADDSWri killed %w0, 1, 0, implicit-def %nzcv
B %bb.1
bb.1:
- successors: %bb.2
liveins: %x1
%w0 = MOVi32imm -1
tracksRegLiveness: true
body: |
bb.0:
- successors: %bb.1, %bb.2
liveins: %x0, %x1
dead %xzr = ADDSXri killed %x0, 1, 0, implicit-def %nzcv
B %bb.1
bb.1:
- successors: %bb.2
liveins: %x1
%x0 = MOVi64imm -1
tracksRegLiveness: true
body: |
bb.0.entry:
- successors: %bb.1, %bb.2
liveins: %x0, %x1
dead %xzr = ADDSXri killed %x0, 1, 0, implicit-def %nzcv
B %bb.1
bb.1:
- successors: %bb.2
liveins: %x1
%w0 = MOVi32imm -1
tracksRegLiveness: true
body: |
bb.0.entry:
- successors: %bb.1, %bb.2
liveins: %w0, %x1
dead %wzr = ADDSWri killed %w0, 1, 0, implicit-def %nzcv
B %bb.1
bb.1:
- successors: %bb.2
liveins: %x1
%x0 = MOVi64imm -1
tracksRegLiveness: true
body: |
bb.0.entry:
- successors: %bb.1, %bb.2
liveins: %w0, %x1
dead %wzr = SUBSWri killed %w0, 1, 12, implicit-def %nzcv
B %bb.1
bb.1:
- successors: %bb.2
liveins: %x1
%w0 = MOVi32imm 4096
; CHECK-LABEL: bb.0:
; CHECK-NOT: COPY %wzr
bb.0:
- successors: %bb.3, %bb.1
liveins: %w0
%0 = COPY %w0
; CHECK: COPY %wzr
bb.1:
- successors: %bb.2
-
B %bb.2
bb.2:
- successors: %bb.3, %bb.2
-
%2 = PHI %0, %bb.1, %4, %bb.2
%w0 = COPY %1
%3 = SUBSWri %2, 1, 0, implicit-def dead %nzcv
name: func1
body: |
bb.0:
- successors: %bb.1, %bb.2
; Cannot coalesce physreg because we have reads on other CFG paths (we
; currently abort for any control flow)
; CHECK-NOT: %fp = SUBXri
name: func2
body: |
bb.0:
- successors: %bb.1, %bb.2
; We can coalesce copies from physreg to vreg across multiple blocks.
; CHECK-NOT: COPY
; CHECK: CBZX undef %x0, %bb.1
- { id: 5, class: sreg_128 }
body: |
bb.0:
- successors: %bb.1
S_NOP 0, implicit-def %0
S_NOP 0, implicit-def %1
S_NOP 0, implicit-def %2
S_BRANCH %bb.1
bb.1:
- successors: %bb.1, %bb.2
%4 = PHI %3, %bb.0, %5, %bb.1
; let's swiffle some lanes around for fun...
- { id: 6, class: sreg_128 }
body: |
bb.0:
- successors: %bb.1
S_NOP 0, implicit-def %0
S_NOP 0, implicit-def %1
S_NOP 0, implicit-def dead %2
S_BRANCH %bb.1
bb.1:
- successors: %bb.1, %bb.2
%5 = PHI %4, %bb.0, %6, %bb.1
; rotate lanes, but skip sub2 lane...
- { id: 3, class: sreg_128 }
body: |
bb.0:
- successors: %bb.1
S_NOP 0, implicit-def %0
%1 = REG_SEQUENCE %0, %subreg.sub0
S_BRANCH %bb.1
bb.1:
- successors: %bb.1, %bb.2
%2 = PHI %1, %bb.0, %3, %bb.1
; rotate subreg lanes, skipping sub1
body: |
bb.0:
- successors: %bb.1
%vcc = S_MOV_B64 0
%vgpr0 = V_DIV_FMAS_F32 0, %vgpr1, 0, %vgpr2, 0, %vgpr3, 0, 0, implicit %vcc, implicit %exec
S_BRANCH %bb.1
bb.1:
- successors: %bb.2
implicit %vcc = V_CMP_EQ_I32_e32 %vgpr1, %vgpr2, implicit %exec
%vgpr0 = V_DIV_FMAS_F32 0, %vgpr1, 0, %vgpr2, 0, %vgpr3, 0, 0, implicit %vcc, implicit %exec
S_BRANCH %bb.2
bb.2:
- successors: %bb.3
%vcc = V_CMP_EQ_I32_e64 %vgpr1, %vgpr2, implicit %exec
%vgpr0 = V_DIV_FMAS_F32 0, %vgpr1, 0, %vgpr2, 0, %vgpr3, 0, 0, implicit %vcc, implicit %exec
S_BRANCH %bb.3
body: |
bb.0:
- successors: %bb.1
S_SETREG_B32 %sgpr0, 1
%sgpr1 = S_GETREG_B32 1
S_BRANCH %bb.1
bb.1:
- successors: %bb.2
S_SETREG_IMM32_B32 0, 1
%sgpr1 = S_GETREG_B32 1
S_BRANCH %bb.2
bb.2:
- successors: %bb.3
S_SETREG_B32 %sgpr0, 1
%sgpr1 = S_MOV_B32 0
%sgpr2 = S_GETREG_B32 1
body: |
bb.0:
- successors: %bb.1
S_SETREG_B32 %sgpr0, 1
S_SETREG_B32 %sgpr1, 1
S_BRANCH %bb.1
bb.1:
- successors: %bb.2
S_SETREG_B32 %sgpr0, 64
S_SETREG_B32 %sgpr1, 128
S_BRANCH %bb.2
body: |
bb.0:
- successors: %bb.1
BUFFER_STORE_DWORD_OFFSET %vgpr3, %sgpr0_sgpr1_sgpr2_sgpr3, %sgpr4, 0, 0, 0, 0, implicit %exec
%vgpr3 = V_MOV_B32_e32 0, implicit %exec
BUFFER_STORE_DWORDX3_OFFSET %vgpr2_vgpr3_vgpr4, %sgpr0_sgpr1_sgpr2_sgpr3, 0, 0, 0, 0, 0, implicit %exec
body: |
bb.0:
- successors: %bb.1
%vgpr0,%sgpr0_sgpr1 = V_ADD_I32_e64 %vgpr1, %vgpr2, implicit %vcc, implicit %exec
%sgpr4 = V_READLANE_B32 %vgpr4, %sgpr0
S_BRANCH %bb.1
bb.1:
- successors: %bb.2
%vgpr0,%sgpr0_sgpr1 = V_ADD_I32_e64 %vgpr1, %vgpr2, implicit %vcc, implicit %exec
%vgpr4 = V_WRITELANE_B32 %sgpr0, %sgpr0
S_BRANCH %bb.2
bb.2:
- successors: %bb.3
%vgpr0,implicit %vcc = V_ADD_I32_e32 %vgpr1, %vgpr2, implicit %vcc, implicit %exec
%sgpr4 = V_READLANE_B32 %vgpr4, %vcc_lo
S_BRANCH %bb.3
body: |
bb.0:
- successors: %bb.1
S_SETREG_B32 %sgpr0, 3
S_RFE_B64 %sgpr2_sgpr3
S_BRANCH %bb.1
body: |
bb.0:
- successors: %bb.1
%sgpr0 = S_MOV_FED_B32 %sgpr0
%sgpr0 = S_MOV_B32 %sgpr0
S_BRANCH %bb.1
body: |
bb.0:
- successors: %bb.1
%m0 = S_MOV_B32 0
%sgpr0 = S_MOVRELS_B32 %sgpr0, implicit %m0
S_BRANCH %bb.1
bb.1:
- successors: %bb.2
%m0 = S_MOV_B32 0
%sgpr0_sgpr1 = S_MOVRELS_B64 %sgpr0_sgpr1, implicit %m0
S_BRANCH %bb.2
bb.2:
- successors: %bb.3
%m0 = S_MOV_B32 0
%sgpr0 = S_MOVRELD_B32 %sgpr0, implicit %m0
S_BRANCH %bb.3
body: |
bb.0:
- successors: %bb.1
%m0 = S_MOV_B32 0
%vgpr0 = V_INTERP_P1_F32 %vgpr0, 0, 0, implicit %m0, implicit %exec
S_BRANCH %bb.1
bb.1:
- successors: %bb.2
%m0 = S_MOV_B32 0
%vgpr0 = V_INTERP_P2_F32 %vgpr0, %vgpr1, 0, 0, implicit %m0, implicit %exec
S_BRANCH %bb.2
bb.2:
- successors: %bb.3
%m0 = S_MOV_B32 0
%vgpr0 = V_INTERP_P1_F32_16bank %vgpr0, 0, 0, implicit %m0, implicit %exec
S_BRANCH %bb.3
hasMustTailInVarArgFunc: false
body: |
bb.0.entry:
- successors: %bb.2.if, %bb.1.else
liveins: %sgpr0_sgpr1
%sgpr0_sgpr1 = S_LOAD_DWORDX2_IMM killed %sgpr0_sgpr1, 11, 0 :: (non-temporal dereferenceable invariant load 8 from `i64 addrspace(2)* undef`)
S_CBRANCH_VCCNZ %bb.2.if, implicit undef %vcc
bb.1.else:
- successors: %bb.3.done
liveins: %sgpr6, %sgpr7, %sgpr0_sgpr1_sgpr2_sgpr3:0x00000003
%vgpr0 = V_MOV_B32_e32 100, implicit %exec
S_BRANCH %bb.3.done
bb.2.if:
- successors: %bb.3.done
liveins: %sgpr6, %sgpr7, %sgpr0_sgpr1_sgpr2_sgpr3:0x00000003
%vgpr0 = V_MOV_B32_e32 9, implicit %exec
- { id: 0, class: sreg_64 }
body: |
bb.0:
- successors: %bb.1, %bb.2
S_NOP 0, implicit-def undef %0.sub0
S_CBRANCH_VCCNZ %bb.1, implicit undef %vcc
S_BRANCH %bb.2
bb.1:
- successors: %bb.2
S_NOP 0, implicit-def %0.sub1
S_NOP 0, implicit %0.sub1
S_BRANCH %bb.2
hasMustTailInVarArgFunc: false
body: |
bb.0.main_body:
- successors: %bb.1.if, %bb.2.end
liveins: %vgpr0
%sgpr0_sgpr1 = COPY %exec
S_BRANCH %bb.1.if
bb.1.if:
- successors: %bb.2.end
liveins: %sgpr0_sgpr1
%sgpr7 = S_MOV_B32 61440
hasMustTailInVarArgFunc: false
body: |
bb.0.main_body:
- successors: %bb.1.if, %bb.2.end
liveins: %vgpr0
%sgpr0_sgpr1 = COPY %exec
S_BRANCH %bb.1.if
bb.1.if:
- successors: %bb.2.end
liveins: %sgpr0_sgpr1
%sgpr7 = S_MOV_B32 61440
hasMustTailInVarArgFunc: false
body: |
bb.0.main_body:
- successors: %bb.1.if, %bb.2.end
liveins: %vgpr0
%sgpr0_sgpr1 = COPY %exec
S_BRANCH %bb.1.if
bb.1.if:
- successors: %bb.2.end
liveins: %sgpr0_sgpr1
%sgpr7 = S_MOV_B32 61440
hasMustTailInVarArgFunc: false
body: |
bb.0.main_body:
- successors: %bb.1.if, %bb.2.end
liveins: %vgpr0
%sgpr0_sgpr1 = COPY %exec
S_BRANCH %bb.1.if
bb.1.if:
- successors: %bb.2.end
liveins: %sgpr0_sgpr1
%sgpr7 = S_MOV_B32 61440
hasMustTailInVarArgFunc: false
body: |
bb.0.main_body:
- successors: %bb.1.if, %bb.2.end
liveins: %vgpr0
%sgpr6 = S_MOV_B32 -1
S_BRANCH %bb.1.if
bb.1.if:
- successors: %bb.2.end
liveins: %sgpr0_sgpr1 , %sgpr4_sgpr5_sgpr6_sgpr7
%vgpr0 = BUFFER_LOAD_DWORD_OFFSET %sgpr4_sgpr5_sgpr6_sgpr7, 0, 0, 0, 0, 0, implicit %exec :: (volatile load 4 from `i32 addrspace(1)* undef`)
hasMustTailInVarArgFunc: false
body: |
bb.0.main_body:
- successors: %bb.1.if, %bb.2.end
liveins: %vgpr0
%sgpr0_sgpr1 = COPY %exec
S_BRANCH %bb.1.if
bb.1.if:
- successors: %bb.2.end
liveins: %sgpr0_sgpr1
%sgpr7 = S_MOV_B32 61440
hasMustTailInVarArgFunc: false
body: |
bb.0.main_body:
- successors: %bb.1.if, %bb.2.end
liveins: %vgpr0
%sgpr0_sgpr1 = COPY %exec
S_BRANCH %bb.1.if
bb.1.if:
- successors: %bb.2.end
liveins: %sgpr0_sgpr1, %sgpr2_sgpr3
S_SLEEP 0, implicit %sgpr2_sgpr3
%sgpr7 = S_MOV_B32 61440
hasMustTailInVarArgFunc: false
body: |
bb.0.main_body:
- successors: %bb.1.if, %bb.2.end
liveins: %vgpr0
%sgpr0_sgpr1 = COPY %exec
S_BRANCH %bb.1.if
bb.1.if:
- successors: %bb.2.end
liveins: %sgpr0_sgpr1
%sgpr7 = S_MOV_B32 61440
hasMustTailInVarArgFunc: false
body: |
bb.0.main_body:
- successors: %bb.1.if, %bb.2.end
liveins: %vgpr0
%sgpr0_sgpr1 = COPY %exec
S_BRANCH %bb.1.if
bb.1.if:
- successors: %bb.2.end
liveins: %sgpr0_sgpr1
%sgpr7 = S_MOV_B32 61440
hasMustTailInVarArgFunc: false
body: |
bb.0.main_body:
- successors: %bb.1.if, %bb.2.end
liveins: %vgpr0
%sgpr0_sgpr1 = COPY %exec
S_BRANCH %bb.1.if
bb.1.if:
- successors: %bb.2.end
liveins: %sgpr0_sgpr1
%sgpr7 = S_MOV_B32 61440
- { id: 1, class: sreg_128 }
body: |
bb.0:
- successors: %bb.1, %bb.2
S_NOP 0, implicit-def undef %0.sub2
S_CBRANCH_VCCNZ %bb.1, implicit undef %vcc
S_BRANCH %bb.2
; GCN: V_ADD_I32
bb.0:
liveins: %vgpr0
- successors: %bb.1
%7 = COPY %vgpr0
%8 = S_MOV_B32 0
bb.1:
- successors: %bb.1, %bb.2
%0 = PHI %8, %bb.0, %0, %bb.1, %2, %bb.2
%9 = V_MOV_B32_e32 9, implicit %exec
%10 = V_CMP_EQ_U32_e64 %7, %9, implicit %exec
S_BRANCH %bb.1
bb.2:
- successors: %bb.1
SI_END_CF %1, implicit-def %exec, implicit-def %scc, implicit %exec
%11 = S_MOV_B32 1
%2 = S_ADD_I32 %0, %11, implicit-def %scc
- { id: 0, class: sreg_64 }
body: |
bb.0:
- successors: %bb.1, %bb.2
S_CBRANCH_VCCNZ %bb.1, implicit undef %vcc
S_BRANCH %bb.2
bb.1:
- successors: %bb.3
S_NOP 0, implicit-def undef %0.sub0
S_BRANCH %bb.3
bb.2:
- successors: %bb.3
S_NOP 0, implicit-def %0
S_BRANCH %bb.3
hasMustTailInVarArgFunc: false
body: |
bb.0.entry:
- successors: %bb.2.if, %bb.1.else
liveins: %sgpr0_sgpr1
%sgpr2 = S_LOAD_DWORD_IMM %sgpr0_sgpr1, 9, 0 :: (non-temporal dereferenceable invariant load 4 from `float addrspace(2)* undef`)
S_CBRANCH_VCCZ %bb.1.else, implicit killed %vcc
bb.2.if:
- successors: %bb.3.done
liveins: %sgpr6, %sgpr7, %sgpr0_sgpr1_sgpr2_sgpr3:0x00000003
%vgpr0 = V_MOV_B32_e32 9, implicit %exec
S_BRANCH %bb.3.done
bb.1.else:
- successors: %bb.3.done
liveins: %sgpr6, %sgpr7, %sgpr0_sgpr1_sgpr2_sgpr3:0x00000003
%vgpr0 = V_MOV_B32_e32 100, implicit %exec
hasMustTailInVarArgFunc: false
body: |
bb.0.entry:
- successors: %bb.2.if, %bb.1.else
liveins: %sgpr0_sgpr1
%sgpr0_sgpr1 = S_LOAD_DWORDX2_IMM killed %sgpr0_sgpr1, 11, 0 :: (non-temporal dereferenceable invariant load 8 from `i64 addrspace(2)* undef`)
S_CBRANCH_VCCZ %bb.1.else, implicit undef %vcc
bb.2.if:
- successors: %bb.3.done
liveins: %sgpr6, %sgpr7, %sgpr0_sgpr1_sgpr2_sgpr3:0x00000003
%vgpr0 = V_MOV_B32_e32 9, implicit %exec
S_BRANCH %bb.3.done
bb.1.else:
- successors: %bb.3.done
liveins: %sgpr6, %sgpr7, %sgpr0_sgpr1_sgpr2_sgpr3:0x00000003
%vgpr0 = V_MOV_B32_e32 100, implicit %exec
- { id: 1, type: spill-slot, offset: -8, size: 4, alignment: 4, callee-saved-register: '%r7' }
body: |
bb.0.entry:
- successors: %bb.1, %bb.2.if.end
liveins: %r0, %r1, %r2, %r3, %lr, %r7
DBG_VALUE debug-use %r0, debug-use _, !18, !27, debug-location !28
# CHECK-NOT: tCMPi8
body: |
bb.0.entry:
- successors: %bb.1.entry(0x40000000), %bb.2.entry(0x40000000)
liveins: %r0, %r1
%1 = COPY %r1
tBcc %bb.2.entry, 0, %cpsr
bb.1.entry:
- successors: %bb.2.entry(0x80000000)
-
bb.2.entry:
%5 = PHI %4, %bb.1.entry, %3, %bb.0.entry
# CHECK-NEXT: tCMPi8
body: |
bb.0.entry:
- successors: %bb.1.if.then(0x40000000), %bb.2.if.end(0x40000000)
liveins: %r0, %r1
%1 = COPY %r1
tB %bb.1.if.then, 14, _
bb.1.if.then:
- successors: %bb.3.return(0x80000000)
-
%4, %cpsr = tMOVi8 42, 14, _
tSTRspi killed %4, %stack.0.retval, 0, 14, _ :: (store 4 into %ir.retval)
tB %bb.3.return, 14, _
bb.2.if.end:
- successors: %bb.3.return(0x80000000)
-
%3, %cpsr = tMOVi8 1, 14, _
tSTRspi killed %3, %stack.0.retval, 0, 14, _ :: (store 4 into %ir.retval)
- { id: 5, type: spill-slot, offset: -24, size: 4, alignment: 4, callee-saved-register: '%r4' }
body: |
bb.0.entry:
- successors: %bb.5.if.end, %bb.1.if.then
liveins: %r0, %r4, %r5, %r6, %r7, %r11, %lr
%sp = frame-setup STMDB_UPD %sp, 14, _, killed %r4, killed %r5, killed %r6, killed %r7, killed %r11, killed %lr
Bcc %bb.5.if.end, 0, killed %cpsr
bb.1.if.then:
- successors: %bb.3.for.cond
liveins: %r4, %r5
%r0 = MOVi 12, 14, _, _, debug-location !26
B %bb.3.for.cond
bb.2.for.body:
- successors: %bb.3.for.cond
liveins: %r4, %r5, %r6, %r7
%r1 = ADDrr %r5, %r7, 14, _, _, debug-location !36
DBG_VALUE debug-use %r7, debug-use _, !18, !20, debug-location !28
bb.3.for.cond:
- successors: %bb.2.for.body, %bb.4.for.cond.cleanup
liveins: %r4, %r5, %r6, %r7
DBG_VALUE debug-use %r7, debug-use _, !18, !20, debug-location !28
Bcc %bb.2.for.body, 11, killed %cpsr, debug-location !33
bb.4.for.cond.cleanup:
- successors: %bb.5.if.end
liveins: %r4, %r5, %r6
%r0 = MOVr %r5, 14, _, _, debug-location !34
+++ /dev/null
-; RUN: llc -stop-after machine-sink %s -o %t.mir
-; RUN: FileCheck %s < %t.mir
-; RUN: llc %t.mir -run-pass machine-sink
-; Check that branch probabilities are printed in a format that can then be parsed.
-; This test fails on powerpc because of an undefined physical register use in the MIR. See PR31062.
-; XFAIL: powerpc
-
-declare void @foo()
-declare void @bar()
-
-define void @test(i1 %c) {
-; CHECK-LABEL: name: test
-entry:
- br i1 %c, label %then, label %else
-
-then:
- call void @foo()
- br label %end
-; CHECK: successors: %{{[a-z0-9\-\.]+}}({{0x[0-9a-f]+}}), %{{[a-z0-9\-\.]+}}({{0x[0-9a-f]+}})
-
-else:
- call void @bar()
- br label %end
-; CHECK: successors: %{{[a-z0-9\-\.]+}}({{0x[0-9a-f]+}})
-
-end:
- ret void
-}
--- /dev/null
+# RUN: llc -o - %s -run-pass=none -verify-machineinstrs -simplify-mir | FileCheck %s
+---
+# We shouldn't need any explicit successor lists in these examples
+# CHECK-LABEL: name: func0
+# CHECK: bb.0:
+# CHECK-NOT: successors
+# CHECK: JE_1 %bb.1, implicit undef %eflags
+# CHECK: JMP_1 %bb.3
+# CHECK: bb.1:
+# CHECK-NOT: successors
+# CHECK: bb.2:
+# CHECK-NOT: successors
+# CHECK: JE_1 %bb.1, implicit undef %eflags
+# CHECK: bb.3:
+# CHECK: RETQ undef %eax
+name: func0
+body: |
+ bb.0:
+ JE_1 %bb.1, implicit undef %eflags
+ JMP_1 %bb.3
+
+ bb.1:
+
+ bb.2:
+ JE_1 %bb.1, implicit undef %eflags
+
+ bb.3:
+ JE_1 %bb.4, implicit undef %eflags ; condjump+fallthrough to same block
+
+ bb.4:
+ RETQ undef %eax
+...
+---
+# Some cases that need explicit successors:
+# CHECK-LABEL: name: func1
+name: func1
+body: |
+ bb.0:
+ ; CHECK: bb.0:
+ ; CHECK: successors: %bb.3, %bb.1
+ successors: %bb.3, %bb.1 ; different order than operands
+ JE_1 %bb.1, implicit undef %eflags
+ JMP_1 %bb.3
+
+ bb.1:
+ ; CHECK: bb.1:
+ ; CHECK: successors: %bb.2, %bb.1
+ successors: %bb.2, %bb.1 ; different order (fallthrough variant)
+ JE_1 %bb.1, implicit undef %eflags
+
+ bb.2:
+ ; CHECK: bb.2:
+ ; CHECK: successors: %bb.1(0x60000000), %bb.3(0x20000000)
+ successors: %bb.1(3), %bb.3(1) ; branch probabilities not normalized
+ JE_1 %bb.1, implicit undef %eflags
+
+ bb.3:
+ ; CHECK: bb.3:
+ ; CHECK: RETQ undef %eax
+ RETQ undef %eax
+...
--- /dev/null
+# RUN: llc -o - %s -mtriple=x86_64-- -run-pass=none | FileCheck %s
+---
+# Check that branch probabilities are printed correctly as hex numbers.
+# CHECK-LABEL: name: test
+# CHECK: bb.0:
+# CHECK-NEXT: successors: %bb.1(0x66666666), %bb.2(0x1999999a)
+name: test
+body: |
+ bb.0:
+ successors: %bb.1(4), %bb.2(1)
+ JE_1 %bb.2, implicit undef %eflags
+
+ bb.1:
+ NOOP
+
+ bb.2:
+ RETQ undef %eax
+...
name: foo
body: |
; CHECK-LABEL: bb.0.entry:
- ; CHECK: successors: %bb.1.less(0x40000000), %bb.2.exit(0x40000000)
; CHECK-LABEL: bb.1.less:
bb.0.entry:
successors: %bb.1.less, %bb.2.exit
tracksRegLiveness: true
body: |
bb.0:
- successors: %bb.1, %bb.2
JE_1 %bb.1, implicit undef %eflags
JMP_1 %bb.2
body: |
bb.0.entry:
liveins: %edi
- successors: %bb.1.false
NOOP implicit-def %al
; The bug was triggered only when LivePhysReg is used, which
body: |
bb.0.entry:
- successors: %bb.3.is_null, %bb.1.not_null
liveins: %esi, %rdi
TEST64rr %rdi, %rdi, implicit-def %eflags
JE_1 %bb.3.is_null, implicit %eflags
bb.1.not_null:
- successors: %bb.4.ret_100, %bb.2.ret_200
liveins: %esi, %rdi
%eax = MOV32ri 2200000
body: |
bb.0.entry:
- successors: %bb.3.is_null, %bb.1.not_null
liveins: %esi, %rdi, %rdx
%eax = MOV32rm killed %rdx, 1, _, 0, _ :: (volatile load 4 from %ir.ptr)
JE_1 %bb.3.is_null, implicit %eflags
bb.1.not_null:
- successors: %bb.4.ret_100, %bb.2.ret_200
liveins: %esi, %rdi
%eax = MOV32ri 2200000
JE_1 %bb.4.ret_100, implicit %eflags
bb.2.ret_200:
- successors: %bb.3.is_null
%eax = MOV32ri 200
body: |
bb.0.entry:
- successors: %bb.3.is_null, %bb.1.not_null
liveins: %esi, %rdi
TEST64rr %rdi, %rdi, implicit-def %eflags
JE_1 %bb.3.is_null, implicit %eflags
bb.1.not_null:
- successors: %bb.4.ret_100, %bb.2.ret_200
liveins: %esi, %rdi
%eax = MOV32ri 2200000
body: |
bb.0.entry:
- successors: %bb.3.is_null, %bb.1.not_null
liveins: %rsi, %rdi
TEST64rr %rdi, %rdi, implicit-def %eflags
JE_1 %bb.3.is_null, implicit %eflags
bb.1.not_null:
- successors: %bb.4.ret_100, %bb.2.ret_200
liveins: %rsi, %rdi
%rdi = MOV64ri 5000
body: |
bb.0.entry:
- successors: %bb.3.is_null, %bb.1.not_null
liveins: %rsi, %rdi, %rdx
TEST64rr %rdi, %rdi, implicit-def %eflags
JE_1 %bb.3.is_null, implicit %eflags
bb.1.not_null:
- successors: %bb.4.ret_100, %bb.2.ret_200
liveins: %rsi, %rdi, %rdx
%rbx = MOV64rr %rdx
# CHECK: CALL64pcrel32
body: |
bb.0.entry:
- successors: %bb.2.leave, %bb.1.stay
liveins: %rdi, %rbx
frame-setup PUSH64r killed %rbx, implicit-def %rsp, implicit %rsp
- { reg: '%rsi' }
body: |
bb.0.entry:
- successors: %bb.2.is_null, %bb.1.not_null
liveins: %rdi, %rsi
TEST64rr %rdi, %rdi, implicit-def %eflags
- { reg: '%rsi' }
body: |
bb.0.entry:
- successors: %bb.2.is_null, %bb.1.not_null
liveins: %rdi, %rsi
TEST64rr %rdi, %rdi, implicit-def %eflags
- { reg: '%rsi' }
body: |
bb.0.entry:
- successors: %bb.1.is_null(0x30000000), %bb.2.not_null(0x50000000)
liveins: %rsi, %rdi
TEST64rr %rdi, %rdi, implicit-def %eflags
- { reg: '%rsi' }
body: |
bb.0.entry:
- successors: %bb.1.is_null(0x30000000), %bb.2.not_null(0x50000000)
liveins: %rsi, %rdi
TEST64rr %rdi, %rdi, implicit-def %eflags
- { reg: '%rsi' }
body: |
bb.0.entry:
- successors: %bb.2.is_null, %bb.1.not_null
liveins: %rdi, %rsi
TEST64rr %rdi, %rdi, implicit-def %eflags
- { reg: '%rsi' }
body: |
bb.0.entry:
- successors: %bb.2.is_null, %bb.1.not_null
liveins: %rdi, %rsi
TEST64rr %rdi, %rdi, implicit-def %eflags
- { reg: '%rsi' }
body: |
bb.0.entry:
- successors: %bb.2.is_null, %bb.1.not_null
liveins: %rdi, %rsi
TEST64rr %rdi, %rdi, implicit-def %eflags
- { reg: '%rsi' }
body: |
bb.0.entry:
- successors: %bb.2.is_null, %bb.1.not_null
liveins: %rdi, %rsi
TEST64rr %rdi, %rdi, implicit-def %eflags
- { reg: '%rsi' }
body: |
bb.0.entry:
- successors: %bb.2.is_null, %bb.1.not_null
liveins: %rdi, %rsi
TEST64rr %rdi, %rdi, implicit-def %eflags
- { reg: '%rsi' }
body: |
bb.0.entry:
- successors: %bb.2.is_null, %bb.1.not_null
liveins: %rdi, %rsi
TEST64rr %rdi, %rdi, implicit-def %eflags
- { reg: '%rsi' }
body: |
bb.0.entry:
- successors: %bb.2.is_null, %bb.1.not_null
liveins: %rdi, %rsi
TEST64rr %rdi, %rdi, implicit-def %eflags
- { reg: '%rsi' }
body: |
bb.0.entry:
- successors: %bb.2.is_null, %bb.1.not_null
liveins: %rdi, %rsi
TEST64rr %rdi, %rdi, implicit-def %eflags
'%r14d', '%r15d', '%r12w', '%r13w', '%r14w', '%r15w' ]
body: |
bb.0.entry:
- successors: %bb.2.is_null, %bb.1.not_null
liveins: %rdi, %rbx
frame-setup PUSH64r killed %rbx, implicit-def %rsp, implicit %rsp
- { reg: '%rsi' }
body: |
bb.0.entry:
- successors: %bb.2.is_null, %bb.1.not_null
liveins: %rdi, %rsi
TEST64rr %rdi, %rdi, implicit-def %eflags
- { reg: '%rsi' }
body: |
bb.0.entry:
- successors: %bb.2.is_null, %bb.1.not_null
liveins: %rdi, %rsi
TEST64rr %rdi, %rdi, implicit-def %eflags
- { reg: '%rsi' }
body: |
bb.0.entry:
- successors: %bb.2.is_null, %bb.1.not_null
liveins: %rdi, %rsi
TEST64rr %rdi, %rdi, implicit-def %eflags
- { reg: '%rsi' }
body: |
bb.0.entry:
- successors: %bb.2.is_null, %bb.1.not_null
liveins: %rdi, %rsi
TEST64rr %rdi, %rdi, implicit-def %eflags
- { reg: '%rsi' }
body: |
bb.0.entry:
- successors: %bb.2.is_null, %bb.1.not_null
liveins: %rdi, %rsi
TEST64rr %rdi, %rdi, implicit-def %eflags
- { reg: '%rsi' }
body: |
bb.0.entry:
- successors: %bb.2.is_null, %bb.1.not_null
liveins: %rdi, %rsi
TEST64rr %rdi, %rdi, implicit-def %eflags
- { reg: '%rsi' }
body: |
bb.0.entry:
- successors: %bb.2.is_null, %bb.1.not_null
liveins: %rdi, %rsi
TEST64rr %rdi, %rdi, implicit-def %eflags
- { id: 0, class: gr32 }
body: |
bb.0:
- successors: %bb.2, %bb.3
JG_1 %bb.2, implicit %eflags
JMP_1 %bb.3
bb.2:
- successors: %bb.3
%0 = IMPLICIT_DEF
JMP_1 %bb.3
name: fun
body: |
bb.0:
- successors: %bb.1, %bb.7
-
CMP32ri8 %edi, 40, implicit-def %eflags
JNE_1 %bb.7, implicit killed %eflags
JMP_1 %bb.1
bb.1:
- successors: %bb.2, %bb.11
-
CMP32ri8 %edi, 1, implicit-def %eflags
JNE_1 %bb.11, implicit killed %eflags
JMP_1 %bb.2
bb.2:
- successors: %bb.3, %bb.5
-
CMP32ri8 %edi, 2, implicit-def %eflags
JNE_1 %bb.5, implicit killed %eflags
JMP_1 %bb.3
bb.3:
- successors: %bb.4, %bb.5
-
CMP32ri8 %edi, 90, implicit-def %eflags
JNE_1 %bb.5, implicit killed %eflags
JMP_1 %bb.4
bb.4:
- successors: %bb.5
bb.5:
- successors: %bb.6, %bb.11
-
CMP32ri8 %edi, 4, implicit-def %eflags
JNE_1 %bb.11, implicit killed %eflags
JMP_1 %bb.6
bb.6:
- successors: %bb.11
-
JMP_1 %bb.11
bb.7:
- successors: %bb.9, %bb.8
-
CMP32ri8 %edi, 5, implicit-def %eflags
JE_1 %bb.9, implicit killed %eflags
JMP_1 %bb.8
bb.8:
- successors: %bb.9
bb.9:
- successors: %bb.11, %bb.10
-
CMP32ri8 %edi, 6, implicit-def %eflags
JE_1 %bb.11, implicit killed %eflags
JMP_1 %bb.10
bb.10:
- successors: %bb.11
bb.11:
RET 0
# CHECK: Region tree:
# CHECK-NEXT: [0] BB#0 => <Function Return>
# CHECK-NEXT: [1] BB#0 => BB#11
+# CHECK-NEXT: [2] BB#7 => BB#9
+# CHECK-NEXT: [2] BB#9 => BB#11
# CHECK-NEXT: [2] BB#1 => BB#11
# CHECK-NEXT: [3] BB#2 => BB#5
# CHECK-NEXT: [4] BB#3 => BB#5
# CHECK-NEXT: [3] BB#5 => BB#11
-# CHECK-NEXT: [2] BB#7 => BB#9
-# CHECK-NEXT: [2] BB#9 => BB#11
# CHECK-NEXT: End region tree
- { id: 2, type: spill-slot, offset: -32, size: 4, alignment: 4 }
body: |
bb.0:
- successors: %bb.1
liveins: %ebp, %ebx, %edi, %esi
frame-setup PUSH32r killed %ebp, implicit-def %esp, implicit %esp
%edx = MOV32ri 6
bb.1:
- successors: %bb.3, %bb.2
liveins: %eax, %ebp, %ebx, %ecx, %edi, %edx
%ebp = SHR32rCL killed %ebp, implicit-def dead %eflags, implicit %cl
JE_1 %bb.3, implicit %eflags
bb.2:
- successors: %bb.3
liveins: %cl, %eax, %ebp, %esi
OR32mr %esp, 1, _, 8, _, killed %eax, implicit-def %eflags ; :: (store 4 into %stack.1)
hasMustTailInVarArgFunc: false
body: |
bb.0.entry:
- successors: %bb.4(0x30000000), %bb.1.while.body.preheader(0x50000000)
-
%0 = MOV64rm %rip, 1, _, @b, _ :: (dereferenceable load 8 from @b)
%12 = MOV8rm %0, 1, _, 0, _ :: (load 1 from %ir.t0)
TEST8rr %12, %12, implicit-def %eflags
JNE_1 %bb.1.while.body.preheader, implicit killed %eflags
bb.4:
- successors: %bb.3.while.end(0x80000000)
-
%10 = COPY %11
JMP_1 %bb.3.while.end
bb.1.while.body.preheader:
- successors: %bb.2.while.body(0x80000000)
bb.2.while.body:
- successors: %bb.3.while.end(0x04000000), %bb.2.while.body(0x7c000000)
-
%8 = MOVSX32rr8 %12
%10 = COPY %11
%10 = SHL32ri %10, 5, implicit-def dead %eflags