Index: llvm/include/llvm/CodeGen/MachineBasicBlock.h =================================================================== --- llvm/include/llvm/CodeGen/MachineBasicBlock.h +++ llvm/include/llvm/CodeGen/MachineBasicBlock.h @@ -204,6 +204,12 @@ /// to an LLVM basic block. const BasicBlock *getBasicBlock() const { return BB; } + /// Remove the reference to the underlying IR BasicBlock. This is for + /// reduction tools and should generally not be used. + void clearBasicBlock() { + BB = nullptr; + } + /// Return the name of the corresponding LLVM basic block, or an empty string. StringRef getName() const; Index: llvm/include/llvm/CodeGen/MachineFrameInfo.h =================================================================== --- llvm/include/llvm/CodeGen/MachineFrameInfo.h +++ llvm/include/llvm/CodeGen/MachineFrameInfo.h @@ -488,6 +488,14 @@ return Objects[ObjectIdx+NumFixedObjects].Alloca; } + /// Remove the underlying Alloca of the specified stack object if it + /// exists. This generally should not be used and is for reduction tooling. + void clearObjectAllocation(int ObjectIdx) { + assert(unsigned(ObjectIdx + NumFixedObjects) < Objects.size() && + "Invalid Object Idx!"); + Objects[ObjectIdx + NumFixedObjects].Alloca = nullptr; + } + /// Return the assigned stack offset of the specified object /// from the incoming stack pointer. int64_t getObjectOffset(int ObjectIdx) const { Index: llvm/test/tools/llvm-reduce/mir/drop-ir-references.mir =================================================================== --- /dev/null +++ llvm/test/tools/llvm-reduce/mir/drop-ir-references.mir @@ -0,0 +1,86 @@ +# REQUIRES: amdgpu-registered-target +# RUN: llvm-reduce -simplify-mir -mtriple=amdgcn-amd-amdhsa --test FileCheck --test-arg --check-prefix=CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t 2> %t.log +# RUN: FileCheck --check-prefix=RESULT %s < %t + +# CHECK-INTERESTINGNESS: G_LOAD +# CHECK-INTERESTINGNESS: G_LOAD +# CHECK-INTERESTINGNESS: G_LOAD +# CHECK-INTERESTINGNESS: G_LOAD +# CHECK-INTERESTINGNESS: G_STORE +# CHECK-INTERESTINGNESS: G_STORE +# CHECK-INTERESTINGNESS: G_STORE %{{[0-9]+}}(s32), %{{[0-9]+}}(p5) :: (store (s32) into %ir.keep.store, addrspace 5) + +# RESULT: name: func +# RESULT: stack: +# RESULT-NEXT: - { id: 0, size: 32, alignment: 8 } + +# RESULT: body: +# RESULT-NEXT: bb.0: +# RESULT: %{{[0-9]+}}:_(<2 x s16>) = G_LOAD %{{[0-9]+}}(p1) :: (load (<2 x s16>), align 32, addrspace 1) + +# RESULT: bb.1: +# RESULT-NEXT: %{{[0-9]+}}:_(<2 x s32>) = G_LOAD %{{[0-9]+}}(p1) :: (load (<2 x s32>), addrspace 3) +# RESULT-NEXT: %{{[0-9]+}}:_(<2 x s32>) = G_LOAD %{{[0-9]+}}(p1) :: (load (<2 x s32>) from unknown-address + 8, addrspace 3) +# RESULT-NEXT: %{{[0-9]+}}:_(<2 x s32>) = G_LOAD %{{[0-9]+}}(p1) :: (load (<2 x s32>) from unknown-address + 12, align 4, basealign 8, addrspace 3) + + +# RESULT: bb.2: +# RESULT-NEXT: G_STORE %{{[0-9]+}}(<2 x s32>), %{{[0-9]+}}(p5) :: (store (<2 x s32>) into %fixed-stack.0, addrspace 5) +# RESULT-NEXT: G_STORE %{{[0-9]+}}(<2 x s32>), %{{[0-9]+}}(p5) :: (store (<2 x s32>) into %stack.0, addrspace 5) + +# RESULT: bb.3: +# RESULT-NEXT: G_STORE %{{[0-9]+}}(s32), %{{[0-9]+}}(p5) :: (store (s32) into %ir.keep.store, addrspace 5) +# RESULT-NEXT: S_ENDPGM + +--- | + define void @func(<2 x i16> addrspace(1)* %argptr0, <2 x i32> addrspace(3)* %argptr1, i32 addrspace(5)* %keep.store) { + entry: + %alloca = alloca i32, addrspace(5) + br label %block.name.0 + + block.name.0: + br label %block.name.1 + + block.name.1: + br label %exit + + exit: + ret void + } + +... +--- +name: func +tracksRegLiveness: true +fixedStack: + - { id: 0, offset: 16, size: 8, alignment: 8 } +stack: + - { id: 0, size: 32, alignment: 8, name: alloca } +body: | + bb.0.entry: + S_WAITCNT 0 + S_NOP 0 + %0:_(p1) = G_IMPLICIT_DEF + %1:_(<2 x s16>) = G_LOAD %0 :: (load (<2 x s16>) from %ir.argptr0, align 32, addrspace 1) + %2:_(<2 x s32>) = G_ZEXT %1 + + bb.1.block.name.0: + %3:_(<2 x s32>) = G_LOAD %0 :: (load (<2 x s32>) from %ir.argptr1, addrspace 3) + %4:_(<2 x s32>) = G_LOAD %0 :: (load (<2 x s32>) from %ir.argptr1 + 8, addrspace 3) + %5:_(<2 x s32>) = G_LOAD %0 :: (load (<2 x s32>) from %ir.argptr1 + 12, addrspace 3) + + bb.2.block.name.0: + %6:_(<2 x s32>) = G_ADD %2, %3 + %7:_(<2 x s32>) = G_ADD %6, %4 + %8:_(<2 x s32>) = G_ADD %7, %5 + %9:_(p5) = G_IMPLICIT_DEF + G_STORE %8, %9 :: (store (<2 x s32>) into %fixed-stack.0, addrspace 5) + G_STORE %8, %9 :: (store (<2 x s32>) into %stack.0.alloca, addrspace 5) + + bb.3.exit: + %10:_(p5) = G_IMPLICIT_DEF + %11:_(s32) = G_IMPLICIT_DEF + G_STORE %11, %10 :: (store (s32) into %ir.keep.store, addrspace 5) + S_ENDPGM 0 +... + Index: llvm/test/tools/llvm-reduce/mir/preserve-frame-info.mir =================================================================== --- llvm/test/tools/llvm-reduce/mir/preserve-frame-info.mir +++ llvm/test/tools/llvm-reduce/mir/preserve-frame-info.mir @@ -1,5 +1,5 @@ # REQUIRES: amdgpu-registered-target -# RUN: llvm-reduce -simplify-mir -mtriple=amdgcn-amd-amdhsa --test FileCheck --test-arg --check-prefix=CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t 2> %t.log +# RUN: llvm-reduce -simplify-mir -mtriple=amdgcn-amd-amdhsa --delta-passes=instructions --test FileCheck --test-arg --check-prefix=CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t 2> %t.log # RUN: FileCheck --match-full-lines --check-prefix=RESULT %s < %t # CHECK-INTERESTINGNESS-COUNT-15: V_MOV_B32 Index: llvm/test/tools/llvm-reduce/mir/preserve-mem-operands.mir =================================================================== --- llvm/test/tools/llvm-reduce/mir/preserve-mem-operands.mir +++ llvm/test/tools/llvm-reduce/mir/preserve-mem-operands.mir @@ -1,5 +1,5 @@ # REQUIRES: amdgpu-registered-target -# RUN: llvm-reduce -simplify-mir -mtriple=amdgcn-amd-amdhsa --test FileCheck --test-arg --check-prefix=CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t 2> %t.log +# RUN: llvm-reduce -simplify-mir -mtriple=amdgcn-amd-amdhsa --delta-passes=instructions --test FileCheck --test-arg --check-prefix=CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t 2> %t.log # RUN: FileCheck --match-full-lines --check-prefix=RESULT %s < %t # CHECK-INTERESTINGNESS: G_LOAD Index: llvm/tools/llvm-reduce/CMakeLists.txt =================================================================== --- llvm/tools/llvm-reduce/CMakeLists.txt +++ llvm/tools/llvm-reduce/CMakeLists.txt @@ -39,6 +39,7 @@ deltas/ReduceOperandsSkip.cpp deltas/ReduceOperandsToArgs.cpp deltas/ReduceInstructionsMIR.cpp + deltas/ReduceIRReferences.cpp llvm-reduce.cpp DEPENDS Index: llvm/tools/llvm-reduce/DeltaManager.cpp =================================================================== --- llvm/tools/llvm-reduce/DeltaManager.cpp +++ llvm/tools/llvm-reduce/DeltaManager.cpp @@ -24,6 +24,7 @@ #include "deltas/ReduceGlobalValues.h" #include "deltas/ReduceGlobalVarInitializers.h" #include "deltas/ReduceGlobalVars.h" +#include "deltas/ReduceIRReferences.h" #include "deltas/ReduceInstructions.h" #include "deltas/ReduceInstructionsMIR.h" #include "deltas/ReduceMetadata.h" @@ -67,7 +68,11 @@ DELTA_PASS("module-data", reduceModuleDataDeltaPass) #define DELTA_PASSES_MIR \ - DELTA_PASS("instructions", reduceInstructionsMIRDeltaPass) + DELTA_PASS("instructions", reduceInstructionsMIRDeltaPass) \ + DELTA_PASS("ir-instruction-references", \ + reduceIRInstructionReferencesDeltaPass) \ + DELTA_PASS("ir-block-references", reduceIRBlockReferencesDeltaPass) \ + DELTA_PASS("ir-function-references", reduceIRFunctionReferencesDeltaPass) static void runAllDeltaPasses(TestRunner &Tester) { #define DELTA_PASS(NAME, FUNC) FUNC(Tester); Index: llvm/tools/llvm-reduce/deltas/ReduceIRReferences.h =================================================================== --- /dev/null +++ llvm/tools/llvm-reduce/deltas/ReduceIRReferences.h @@ -0,0 +1,31 @@ +//===- ReduceIRReferences.h - Specialized Delta Pass -----------*- c++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements a function which calls the Generic Delta pass in order +// to reduce uninteresting IR references from the MachineFunction. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEIRREFERENCES_MIR_H +#define LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEIRREFERENCES_MIR_H + +namespace llvm { +class TestRunner; + +/// Remove IR references from instructions (i.e. from memory operands) +void reduceIRInstructionReferencesDeltaPass(TestRunner &Test); + +/// Remove IR BasicBlock references (the block names) +void reduceIRBlockReferencesDeltaPass(TestRunner &Test); + +/// Remove IR references from function level fields (e.g. frame object names) +void reduceIRFunctionReferencesDeltaPass(TestRunner &Test); + +} // namespace llvm + +#endif Index: llvm/tools/llvm-reduce/deltas/ReduceIRReferences.cpp =================================================================== --- /dev/null +++ llvm/tools/llvm-reduce/deltas/ReduceIRReferences.cpp @@ -0,0 +1,82 @@ +//===- ReduceIRReferences.cpp - Specialized Delta Pass --------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements a function which calls the Generic Delta pass in order +// to remove backreferences to the IR from MIR. In particular, this will remove +// the Value references in MachineMemOperands. +// +//===----------------------------------------------------------------------===// + +#include "ReduceIRReferences.h" +#include "Delta.h" +#include "llvm/CodeGen/MachineFrameInfo.h" + +using namespace llvm; + +static void dropIRReferencesFromInstructions(Oracle &O, MachineFunction &MF) { + for (MachineBasicBlock &MBB : MF) { + for (MachineInstr &MI : MBB) { + if (!O.shouldKeep()) { + for (MachineMemOperand *MMO : MI.memoperands()) { + // Leave behind pseudo source values. + // TODO: Removing all MemOperand values is a further reduction step. + if (MMO->getPointerInfo().V.is()) + MMO->setValue(static_cast(nullptr)); + } + + // TODO: Try to remove GlobalValue references and metadata + } + } + } +} + +static void stripIRFromInstructions(Oracle &O, ReducerWorkItem &WorkItem) { + for (const Function &F : WorkItem.getModule()) { + if (auto *MF = WorkItem.MMI->getMachineFunction(F)) + dropIRReferencesFromInstructions(O, *MF); + } +} + +static void stripIRFromBlocks(Oracle &O, ReducerWorkItem &WorkItem) { + for (const Function &F : WorkItem.getModule()) { + if (auto *MF = WorkItem.MMI->getMachineFunction(F)) { + for (MachineBasicBlock &MBB : *MF) { + if (!O.shouldKeep()) + MBB.clearBasicBlock(); + } + } + } +} + +static void stripIRFromFunctions(Oracle &O, ReducerWorkItem &WorkItem) { + for (const Function &F : WorkItem.getModule()) { + if (!O.shouldKeep()) { + if (auto *MF = WorkItem.MMI->getMachineFunction(F)) { + MachineFrameInfo &MFI = MF->getFrameInfo(); + for (int I = MFI.getObjectIndexBegin(), E = MFI.getObjectIndexEnd(); + I != E; ++I) + MFI.clearObjectAllocation(I); + } + } + } +} + +void llvm::reduceIRInstructionReferencesDeltaPass(TestRunner &Test) { + outs() << "*** Reducing IR references from instructions...\n"; + runDeltaPass(Test, stripIRFromInstructions); +} + +void llvm::reduceIRBlockReferencesDeltaPass(TestRunner &Test) { + outs() << "*** Reducing IR references from blocks...\n"; + runDeltaPass(Test, stripIRFromBlocks); +} + +void llvm::reduceIRFunctionReferencesDeltaPass(TestRunner &Test) { + outs() << "*** Reducing IR references from functions...\n"; + runDeltaPass(Test, stripIRFromFunctions); +}