mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 04:32:44 +01:00
RegisterScavenging: Add ScavengerTest pass
This pass allows to run the register scavenging independently of PrologEpilogInserter to allow targeted testing. Also adds some basic register scavenging tests. llvm-svn: 304606
This commit is contained in:
parent
0531e97657
commit
5693b1e8e8
@ -330,6 +330,7 @@ void initializeSanitizerCoverageModulePass(PassRegistry&);
|
||||
void initializeScalarEvolutionWrapperPassPass(PassRegistry&);
|
||||
void initializeScalarizeMaskedMemIntrinPass(PassRegistry&);
|
||||
void initializeScalarizerPass(PassRegistry&);
|
||||
void initializeScavengerTestPass(PassRegistry&);
|
||||
void initializeScopedNoAliasAAWrapperPassPass(PassRegistry&);
|
||||
void initializeSeparateConstOffsetFromGEPPass(PassRegistry&);
|
||||
void initializeShadowStackGCLoweringPass(PassRegistry&);
|
||||
|
@ -15,19 +15,23 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#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"
|
||||
@ -555,5 +559,37 @@ void llvm::scavengeFrameVirtualRegs(MachineFunction &MF, RegScavenger &RS) {
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
|
149
test/CodeGen/PowerPC/scavenging.mir
Normal file
149
test/CodeGen/PowerPC/scavenging.mir
Normal file
@ -0,0 +1,149 @@
|
||||
# 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
|
||||
...
|
54
test/CodeGen/X86/scavenger.mir
Normal file
54
test/CodeGen/X86/scavenger.mir
Normal file
@ -0,0 +1,54 @@
|
||||
# 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
|
||||
...
|
@ -304,6 +304,9 @@ int main(int argc, char **argv) {
|
||||
initializeScalarizeMaskedMemIntrinPass(*Registry);
|
||||
initializeExpandReductionsPass(*Registry);
|
||||
|
||||
// Initialize debugging passes.
|
||||
initializeScavengerTestPass(*Registry);
|
||||
|
||||
// Register the target printer for --version.
|
||||
cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user