Commit c08d88a4 authored by Tom Stellard's avatar Tom Stellard
Browse files

Merging r237152:

------------------------------------------------------------------------
r237152 | thomas.stellard | 2015-05-12 13:13:02 -0400 (Tue, 12 May 2015) | 20 lines

R600/SI: add pass to mark CF live ranges as non-spillable

Spilling can insert instructions almost anywhere, and this can mess
up control flow lowering in a multitude of ways, due to instruction
reordering. Let's sort this out the easy way: never spill registers
involved with control flow, i.e. saved EXEC masks.

Unfortunately, this does not work at all with optimizations disabled,
as the register allocator ignores spill weights. This should be
addressed in a future commit.

The test was reduced from the "stacks" shader of [1]. Some issues
trigger the machine verifier while another one is checked manually.

[1] http://madebyevan.com/webgl-path-tracing/

v2: only insert pass with optimizations enabled, merge test runs.

Patch by: Grigori Goronzy

llvm-svn: 240282
parent a862eff9
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ FunctionPass *createSILowerI1CopiesPass();
FunctionPass *createSIShrinkInstructionsPass();
FunctionPass *createSILoadStoreOptimizerPass(TargetMachine &tm);
FunctionPass *createSILowerControlFlowPass(TargetMachine &tm);
FunctionPass *createSIFixControlFlowLiveIntervalsPass();
FunctionPass *createSIFixSGPRCopiesPass(TargetMachine &tm);
FunctionPass *createSIFixSGPRLiveRangesPass();
FunctionPass *createSICodeEmitterPass(formatted_raw_ostream &OS);
@@ -68,6 +69,9 @@ ModulePass *createAMDGPUAlwaysInlinePass();
ImmutablePass *
createAMDGPUTargetTransformInfoPass(const AMDGPUTargetMachine *TM);

void initializeSIFixControlFlowLiveIntervalsPass(PassRegistry&);
extern char &SIFixControlFlowLiveIntervalsID;

void initializeSIFixSGPRLiveRangesPass(PassRegistry&);
extern char &SIFixSGPRLiveRangesID;

+8 −1
Original line number Diff line number Diff line
@@ -170,6 +170,13 @@ void AMDGPUPassConfig::addPreRegAlloc() {
  if (ST.getGeneration() <= AMDGPUSubtarget::NORTHERN_ISLANDS) {
    addPass(createR600VectorRegMerger(*TM));
  } else {
    // This needs to be run directly before register allocation because
    // earlier passes might recompute live intervals.
    // TODO: handle CodeGenOpt::None; fast RA ignores spill weights set by the pass
    if (getOptLevel() > CodeGenOpt::None) {
      initializeSIFixControlFlowLiveIntervalsPass(*PassRegistry::getPassRegistry());
      insertPass(&MachineSchedulerID, &SIFixControlFlowLiveIntervalsID);
    }
    if (getOptLevel() > CodeGenOpt::None && ST.loadStoreOptEnabled()) {
      // Don't do this with no optimizations since it throws away debug info by
      // merging nonadjacent loads.
+1 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ add_llvm_target(R600CodeGen
  R600RegisterInfo.cpp
  R600TextureIntrinsicsReplacer.cpp
  SIAnnotateControlFlow.cpp
  SIFixControlFlowLiveIntervals.cpp
  SIFixSGPRCopies.cpp
  SIFixSGPRLiveRanges.cpp
  SIFoldOperands.cpp
+96 −0
Original line number Diff line number Diff line
//===-- SIFixControlFlowLiveIntervals.cpp - Fix CF live intervals ---------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
/// \file
/// \brief Spilling of EXEC masks used for control flow messes up control flow
/// lowering, so mark all live intervals associated with CF instructions as
/// non-spillable.
///
//===----------------------------------------------------------------------===//

#include "AMDGPU.h"
#include "SIInstrInfo.h"
#include "SIRegisterInfo.h"
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachinePostDominators.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"

using namespace llvm;

#define DEBUG_TYPE "si-fix-cf-live-intervals"

namespace {

class SIFixControlFlowLiveIntervals : public MachineFunctionPass {
public:
  static char ID;

public:
  SIFixControlFlowLiveIntervals() : MachineFunctionPass(ID) {
    initializeSIFixControlFlowLiveIntervalsPass(*PassRegistry::getPassRegistry());
  }

  bool runOnMachineFunction(MachineFunction &MF) override;

  const char *getPassName() const override {
    return "SI Fix CF Live Intervals";
  }

  void getAnalysisUsage(AnalysisUsage &AU) const override {
    AU.addRequired<LiveIntervals>();
    AU.setPreservesAll();
    MachineFunctionPass::getAnalysisUsage(AU);
  }
};

} // End anonymous namespace.

INITIALIZE_PASS_BEGIN(SIFixControlFlowLiveIntervals, DEBUG_TYPE,
                      "SI Fix CF Live Intervals", false, false)
INITIALIZE_PASS_DEPENDENCY(LiveIntervals)
INITIALIZE_PASS_END(SIFixControlFlowLiveIntervals, DEBUG_TYPE,
                    "SI Fix CF Live Intervals", false, false)

char SIFixControlFlowLiveIntervals::ID = 0;

char &llvm::SIFixControlFlowLiveIntervalsID = SIFixControlFlowLiveIntervals::ID;

FunctionPass *llvm::createSIFixControlFlowLiveIntervalsPass() {
  return new SIFixControlFlowLiveIntervals();
}

bool SIFixControlFlowLiveIntervals::runOnMachineFunction(MachineFunction &MF) {
  LiveIntervals *LIS = &getAnalysis<LiveIntervals>();

  for (const MachineBasicBlock &MBB : MF) {
    for (const MachineInstr &MI : MBB) {
      switch (MI.getOpcode()) {
        case AMDGPU::SI_IF:
        case AMDGPU::SI_ELSE:
        case AMDGPU::SI_BREAK:
        case AMDGPU::SI_IF_BREAK:
        case AMDGPU::SI_ELSE_BREAK:
        case AMDGPU::SI_END_CF: {
          unsigned Reg = MI.getOperand(0).getReg();
          LIS->getInterval(Reg).markNotSpillable();
          break;
        }
        default:
          break;
      }
    }
  }

  return false;
}
+501 −0

File added.

Preview size limit exceeded, changes collapsed.