void initializeScalarEvolutionWrapperPassPass(PassRegistry&);
void initializeScalarizeMaskedMemIntrinPass(PassRegistry&);
void initializeScalarizerPass(PassRegistry&);
+void initializeScavengerTestPass(PassRegistry&);
void initializeScopedNoAliasAAWrapperPassPass(PassRegistry&);
void initializeSeparateConstOffsetFromGEPPass(PassRegistry&);
void initializeShadowStackGCLoweringPass(PassRegistry&);
//
//===----------------------------------------------------------------------===//
+#include "llvm/CodeGen/RegisterScavenging.h"
+
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
-#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineOperand.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/PassSupport.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Target/TargetFrameLowering.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetSubtargetInfo.h"
}
}
+ MRI.clearVirtRegs();
MF.getProperties().set(MachineFunctionProperties::Property::NoVRegs);
}
+
+namespace {
+/// This class runs register scavenging independ of the PrologEpilogInserter.
+/// This is used in for testing.
+class ScavengerTest : public MachineFunctionPass {
+public:
+ static char ID;
+ ScavengerTest() : MachineFunctionPass(ID) {}
+ bool runOnMachineFunction(MachineFunction &MF) {
+ const TargetSubtargetInfo &STI = MF.getSubtarget();
+ const TargetFrameLowering &TFL = *STI.getFrameLowering();
+
+ RegScavenger RS;
+ // Let's hope that calling those outside of PrologEpilogueInserter works
+ // well enough to initialize the scavenger with some emergency spillslots
+ // for the target.
+ BitVector SavedRegs;
+ TFL.determineCalleeSaves(MF, SavedRegs, &RS);
+ TFL.processFunctionBeforeFrameFinalized(MF, &RS);
+
+ // Let's scavenge the current function
+ scavengeFrameVirtualRegs(MF, RS);
+ return true;
+ }
+};
+char ScavengerTest::ID;
+
+} // end anonymous namespace
+
+INITIALIZE_PASS(ScavengerTest, "scavenger-test",
+ "Scavenge virtual registers inside basic blocks", false, false)
--- /dev/null
+# RUN: llc -mtriple=ppc64-- -run-pass scavenger-test -verify-machineinstrs -o - %s | FileCheck %s
+---
+# CHECK-LABEL: name: noscav0
+name: noscav0
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK: [[REG0:%r[0-9]+]] = LI 42
+ ; CHECK-NEXT: NOP implicit [[REG0]]
+ %0 : gprc = LI 42
+ NOP implicit %0
+
+ ; CHECK: [[REG1:%r[0-9]+]] = LI 42
+ ; CHECK-NEXT: NOP
+ ; CHECK-NEXT: NOP implicit [[REG1]]
+ ; CHECK-NEXT: NOP
+ ; CHECK-NEXT: NOP implicit [[REG1]]
+ %1 : gprc = LI 42
+ NOP
+ NOP implicit %1
+ NOP
+ NOP implicit %1
+
+ ; CHECK: [[REG2:%r[0-9]+]] = LI 42
+ ; CHECK-NEXT: NOP implicit [[REG2]]
+ %2 : gprc = LI 42
+ NOP implicit %2
+
+ %x0 = IMPLICIT_DEF
+ %x1 = IMPLICIT_DEF
+ %x2 = IMPLICIT_DEF
+ %x3 = IMPLICIT_DEF
+ %x4 = IMPLICIT_DEF
+ %x27 = IMPLICIT_DEF
+ %x28 = IMPLICIT_DEF
+ %x29 = IMPLICIT_DEF
+ %x30 = IMPLICIT_DEF
+
+ ; CHECK-NOT: %x0 = LI 42
+ ; CHECK-NOT: %x1 = LI 42
+ ; CHECK-NOT: %x2 = LI 42
+ ; CHECK-NOT: %x3 = LI 42
+ ; CHECK-NOT: %x4 = LI 42
+ ; CHECK-NOT: %x5 = LI 42
+ ; CHECK-NOT: %x27 = LI 42
+ ; CHECK-NOT: %x28 = LI 42
+ ; CHECK-NOT: %x29 = LI 42
+ ; CHECK-NOT: %x30 = LI 42
+ ; CHECK: [[REG3:%r[0-9]+]] = LI 42
+ ; CHECK-NEXT: %x5 = IMPLICIT_DEF
+ ; CHECK-NEXT: NOP implicit [[REG2]]
+ ; CHECK-NEXT: NOP implicit [[REG3]]
+ %3 : gprc = LI 42
+ %x5 = IMPLICIT_DEF
+ NOP implicit %2
+ NOP implicit %3
+
+ NOP implicit %x0
+ NOP implicit %x1
+ NOP implicit %x2
+ NOP implicit %x3
+ NOP implicit %x4
+ NOP implicit %x5
+ NOP implicit %x27
+ NOP implicit %x28
+ NOP implicit %x29
+ NOP implicit %x30
+...
+---
+# CHECK-LABEL: name: scav0
+name: scav0
+tracksRegLiveness: true
+stack:
+ # variable-sized object should be a reason to reserve an emergency spillslot
+ # in the RegScavenger
+ - { id: 0, type: variable-sized, offset: -32, alignment: 1 }
+body: |
+ bb.0:
+ %x0 = IMPLICIT_DEF
+ %x1 = IMPLICIT_DEF
+ %x2 = IMPLICIT_DEF
+ %x3 = IMPLICIT_DEF
+ %x4 = IMPLICIT_DEF
+ %x5 = IMPLICIT_DEF
+ %x6 = IMPLICIT_DEF
+ %x7 = IMPLICIT_DEF
+ %x8 = IMPLICIT_DEF
+ %x9 = IMPLICIT_DEF
+ %x10 = IMPLICIT_DEF
+ %x11 = IMPLICIT_DEF
+ %x12 = IMPLICIT_DEF
+ %x13 = IMPLICIT_DEF
+ %x14 = IMPLICIT_DEF
+ %x15 = IMPLICIT_DEF
+ %x16 = IMPLICIT_DEF
+ %x17 = IMPLICIT_DEF
+ %x18 = IMPLICIT_DEF
+ %x19 = IMPLICIT_DEF
+ %x20 = IMPLICIT_DEF
+ %x21 = IMPLICIT_DEF
+ %x22 = IMPLICIT_DEF
+ %x23 = IMPLICIT_DEF
+ %x24 = IMPLICIT_DEF
+ %x25 = IMPLICIT_DEF
+ %x26 = IMPLICIT_DEF
+ %x27 = IMPLICIT_DEF
+ %x28 = IMPLICIT_DEF
+ %x29 = IMPLICIT_DEF
+ %x30 = IMPLICIT_DEF
+
+ ; CHECK: STD killed [[SPILLEDREG:%x[0-9]+]]
+ ; CHECK: [[SPILLEDREG]] = LI8 42
+ ; CHECK: NOP implicit [[SPILLEDREG]]
+ ; CHECK: [[SPILLEDREG]] = LD
+ %0 : g8rc = LI8 42
+ NOP implicit %0
+
+ NOP implicit %x0
+ NOP implicit %x1
+ NOP implicit %x2
+ NOP implicit %x3
+ NOP implicit %x4
+ NOP implicit %x5
+ NOP implicit %x6
+ NOP implicit %x7
+ NOP implicit %x8
+ NOP implicit %x9
+ NOP implicit %x10
+ NOP implicit %x11
+ NOP implicit %x12
+ NOP implicit %x13
+ NOP implicit %x14
+ NOP implicit %x15
+ NOP implicit %x16
+ NOP implicit %x17
+ NOP implicit %x18
+ NOP implicit %x19
+ NOP implicit %x20
+ NOP implicit %x21
+ NOP implicit %x22
+ NOP implicit %x23
+ NOP implicit %x24
+ NOP implicit %x25
+ NOP implicit %x26
+ NOP implicit %x27
+ NOP implicit %x28
+ NOP implicit %x29
+ NOP implicit %x30
+...
--- /dev/null
+# RUN: llc -mtriple=i386-- -run-pass scavenger-test -verify-machineinstrs -o - %s | FileCheck %s
+---
+# CHECK-LABEL: name: func0
+name: func0
+tracksRegLiveness: true
+body: |
+ bb.0:
+ %0 : gr32 = MOV32ri 42
+ %ebp = COPY %0
+...
+---
+# CHECK-LABEL: name: func2
+name: func2
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK-NOT: %eax = MOV32ri 42
+ ; CHECK: [[REG0:%e[a-z]+]] = MOV32ri 42
+ ; CHECK: %ebp = COPY [[REG0]]
+ %eax = MOV32ri 13
+ %0 : gr32 = MOV32ri 42
+ %ebp = COPY %0
+
+ ; CHECK: [[REG1:%e[a-z]+]] = MOV32ri 23
+ ; CHECK: [[REG2:%e[a-z]+]] = MOV32ri 7
+ ; CHECK: [[REG1]] = ADD32ri8 [[REG1]], 5, implicit-def dead %eflags
+ %1 : gr32 = MOV32ri 23
+ %2 : gr32 = MOV32ri 7
+ %1 = ADD32ri8 %1, 5, implicit-def dead %eflags
+
+ NOOP implicit %ebp
+
+ ; CHECK: NOOP implicit [[REG2]]
+ ; CHECK: NOOP implicit [[REG1]]
+ NOOP implicit %2
+ NOOP implicit %1
+ RETQ %eax
+...
+---
+# Defs without uses are currently broken
+#name: func3
+#tracksRegLiveness: true
+#body: |
+# bb.0:
+# dead %0 : gr32 = MOV32ri 42
+...
+---
+# Uses without defs are currently broken (and honestly not that useful).
+#name: func3
+#tracksRegLiveness: true
+#body: |
+# bb.0:
+# NOOP undef implicit %0 : gr32
+...
initializeScalarizeMaskedMemIntrinPass(*Registry);
initializeExpandReductionsPass(*Registry);
+ // Initialize debugging passes.
+ initializeScavengerTestPass(*Registry);
+
// Register the target printer for --version.
cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion);