diff --git a/llvm/include/llvm/IR/Constant.h b/llvm/include/llvm/IR/Constant.h --- a/llvm/include/llvm/IR/Constant.h +++ b/llvm/include/llvm/IR/Constant.h @@ -181,6 +181,7 @@ /// void handleOperandChange(Value *, Value *); + static bool hasNullValue(Type* Ty); static Constant *getNullValue(Type* Ty); /// @returns the value for an integer or vector of integer constant of the diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp --- a/llvm/lib/IR/Constants.cpp +++ b/llvm/lib/IR/Constants.cpp @@ -29,6 +29,7 @@ #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" #include +#include using namespace llvm; using namespace PatternMatch; @@ -342,6 +343,10 @@ return false; } +bool Constant::hasNullValue(Type *Ty) { + return getNullValue(Ty) != nullptr; +} + /// Constructor to create a '0' constant of arbitrary type. Constant *Constant::getNullValue(Type *Ty) { switch (Ty->getTypeID()) { @@ -380,7 +385,7 @@ return ConstantTokenNone::get(Ty->getContext()); default: // Function, Label, or Opaque type? - llvm_unreachable("Cannot create a null constant of that type!"); + return nullptr; } } diff --git a/llvm/test/tools/llvm-reduce/no-replace-intrinsic-callee-with-undef.ll b/llvm/test/tools/llvm-reduce/no-replace-intrinsic-callee-with-undef.ll --- a/llvm/test/tools/llvm-reduce/no-replace-intrinsic-callee-with-undef.ll +++ b/llvm/test/tools/llvm-reduce/no-replace-intrinsic-callee-with-undef.ll @@ -3,11 +3,11 @@ ; not replaced. The whole call instruction can be removed by instruction ; reduction instead. -; RUN: llvm-reduce --test FileCheck --test-arg --check-prefixes=ALL,CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t 2> %t.log +; RUN: llvm-reduce --delta-passes=functions,instructions,operand-bundles --test FileCheck --test-arg --check-prefixes=ALL,CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t 2> %t.log ; RUN: FileCheck -implicit-check-not=uninteresting --check-prefixes=ALL,CHECK-FINAL %s < %t ; Check that the call is removed by instruction reduction passes -; RUN: llvm-reduce --test FileCheck --test-arg --check-prefix=ALL --test-arg %s --test-arg --input-file %s -o %t +; RUN: llvm-reduce --delta-passes=functions,instructions,operand-bundles --test FileCheck --test-arg --check-prefix=ALL --test-arg %s --test-arg --input-file %s -o %t ; RUN: FileCheck -implicit-check-not=uninteresting --check-prefixes=ALL,CHECK-NOCALL %s < %t diff --git a/llvm/test/tools/llvm-reduce/remove-all-of-multiple-args.ll b/llvm/test/tools/llvm-reduce/remove-all-of-multiple-args.ll --- a/llvm/test/tools/llvm-reduce/remove-all-of-multiple-args.ll +++ b/llvm/test/tools/llvm-reduce/remove-all-of-multiple-args.ll @@ -1,4 +1,4 @@ -; RUN: llvm-reduce --test FileCheck --test-arg --check-prefixes=CHECK-ALL,CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t +; RUN: llvm-reduce --delta-passes=arguments --test FileCheck --test-arg --check-prefixes=CHECK-ALL,CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t ; RUN: cat %t | FileCheck --check-prefixes=CHECK-ALL,CHECK-FINAL %s define i32 @t(i32 %a0, i32 %a1, i32 %a2) { diff --git a/llvm/test/tools/llvm-reduce/remove-args-used-by-ret.ll b/llvm/test/tools/llvm-reduce/remove-args-used-by-ret.ll --- a/llvm/test/tools/llvm-reduce/remove-args-used-by-ret.ll +++ b/llvm/test/tools/llvm-reduce/remove-args-used-by-ret.ll @@ -1,4 +1,4 @@ -; RUN: llvm-reduce --test FileCheck --test-arg --check-prefixes=CHECK-ALL,CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t +; RUN: llvm-reduce --delta-passes=arguments --test FileCheck --test-arg --check-prefixes=CHECK-ALL,CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t ; RUN: cat %t | FileCheck --check-prefixes=CHECK-ALL,CHECK-FINAL %s ; We can't drop arguments if they are used by terminator instructions. diff --git a/llvm/test/tools/llvm-reduce/remove-bbs-ret-nonvoid.ll b/llvm/test/tools/llvm-reduce/remove-bbs-ret-nonvoid.ll --- a/llvm/test/tools/llvm-reduce/remove-bbs-ret-nonvoid.ll +++ b/llvm/test/tools/llvm-reduce/remove-bbs-ret-nonvoid.ll @@ -1,14 +1,14 @@ ; Test that llvm-reduce inserts valid return instructions for functions with ; on-void return types. ; -; RUN: llvm-reduce --test FileCheck --test-arg --check-prefixes=CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t +; RUN: llvm-reduce --delta-passes=basic-blocks --test FileCheck --test-arg --check-prefixes=CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t ; RUN: cat %t | FileCheck %s ; CHECK-INTERESTINGNESS: interesting: ; CHECK-INTERESTINGNESS: interesting2: define i32 @main(i1 %c) { -; CHECK-LABEL: define i32 @main() { +; CHECK-LABEL: define i32 @main(i1 %c) { ; CHECK-LABEL: interesting: ; CHECK-NEXT: br label %interesting2 diff --git a/llvm/test/tools/llvm-reduce/remove-bbs-unwinded-to.ll b/llvm/test/tools/llvm-reduce/remove-bbs-unwinded-to.ll --- a/llvm/test/tools/llvm-reduce/remove-bbs-unwinded-to.ll +++ b/llvm/test/tools/llvm-reduce/remove-bbs-unwinded-to.ll @@ -1,4 +1,4 @@ -; RUN: llvm-reduce --test FileCheck --test-arg --check-prefixes=CHECK-ALL,CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t +; RUN: llvm-reduce --delta-passes=basic-blocks --test FileCheck --test-arg --check-prefixes=CHECK-ALL,CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t ; RUN: cat %t | FileCheck --check-prefixes=CHECK-ALL,CHECK-FINAL %s declare i32 @maybe_throwing_callee() diff --git a/llvm/test/tools/llvm-reduce/remove-bbs.ll b/llvm/test/tools/llvm-reduce/remove-bbs.ll --- a/llvm/test/tools/llvm-reduce/remove-bbs.ll +++ b/llvm/test/tools/llvm-reduce/remove-bbs.ll @@ -1,7 +1,7 @@ ; Test that llvm-reduce can remove uninteresting Basic Blocks, and remove them from instructions (i.e. SwitchInst, BranchInst and IndirectBrInst) ; Note: if an uninteresting BB is the default case for a switch, the instruction is removed altogether (since the default case cannot be replaced) ; -; RUN: llvm-reduce --test %python --test-arg %p/Inputs/remove-bbs.py %s -o %t +; RUN: llvm-reduce --delta-passes=basic-blocks --test %python --test-arg %p/Inputs/remove-bbs.py %s -o %t ; RUN: cat %t | FileCheck -implicit-check-not=uninteresting %s define void @main() { diff --git a/llvm/test/tools/llvm-reduce/remove-funcs.ll b/llvm/test/tools/llvm-reduce/remove-funcs.ll --- a/llvm/test/tools/llvm-reduce/remove-funcs.ll +++ b/llvm/test/tools/llvm-reduce/remove-funcs.ll @@ -1,7 +1,7 @@ ; Test that llvm-reduce can remove uninteresting functions as well as ; their InstCalls. ; -; RUN: llvm-reduce --test FileCheck --test-arg --check-prefixes=CHECK-ALL,CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t +; RUN: llvm-reduce --delta-passes=functions,instructions --test FileCheck --test-arg --check-prefixes=CHECK-ALL,CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t ; RUN: cat %t | FileCheck -implicit-check-not=uninteresting --check-prefixes=CHECK-ALL,CHECK-FINAL %s define i32 @uninteresting1() { diff --git a/llvm/test/tools/llvm-reduce/remove-global-vars.ll b/llvm/test/tools/llvm-reduce/remove-global-vars.ll --- a/llvm/test/tools/llvm-reduce/remove-global-vars.ll +++ b/llvm/test/tools/llvm-reduce/remove-global-vars.ll @@ -1,7 +1,7 @@ ; Test that llvm-reduce can remove uninteresting Global Variables as well as ; their direct uses (which in turn are replaced with 'undef'). -; RUN: llvm-reduce --test FileCheck --test-arg --check-prefixes=CHECK-ALL,CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t +; RUN: llvm-reduce --delta-passes=global-variables,global-initializers --test FileCheck --test-arg --check-prefixes=CHECK-ALL,CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t ; RUN: cat %t | FileCheck --check-prefixes=CHECK-ALL,CHECK-FINAL --implicit-check-not=uninteresting %s $interesting5 = comdat any diff --git a/llvm/test/tools/llvm-reduce/remove-invoked-functions.ll b/llvm/test/tools/llvm-reduce/remove-invoked-functions.ll --- a/llvm/test/tools/llvm-reduce/remove-invoked-functions.ll +++ b/llvm/test/tools/llvm-reduce/remove-invoked-functions.ll @@ -6,7 +6,7 @@ define i32 @maybe_throwing_callee(i32 %arg) { ; CHECK-ALL: call void @thrown() ; CHECK-INTERESTINGNESS: ret i32 -; CHECK-FINAL: ret i32 undef +; CHECK-FINAL: ret i32 0 call void @thrown() ret i32 %arg } @@ -23,7 +23,7 @@ ; CHECK-ALL: bb: bb: ; CHECK-INTERESTINGNESS: %i0 = invoke i32 -; CHECK-FINAL: %i0 = invoke i32 bitcast (i32 ()* @maybe_throwing_callee to i32 (i32)*)(i32 %arg) +; CHECK-FINAL: %i0 = invoke i32 null(i32 0) ; CHECK-ALL: to label %bb3 unwind label %bb1 %i0 = invoke i32 @maybe_throwing_callee(i32 %arg) to label %bb3 unwind label %bb1 diff --git a/llvm/test/tools/llvm-reduce/remove-operands.ll b/llvm/test/tools/llvm-reduce/remove-operands.ll new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-reduce/remove-operands.ll @@ -0,0 +1,20 @@ +; Test that llvm-reduce can reduce operands to their respective null values. +; +; RUN: llvm-reduce --delta-passes=operands --test FileCheck --test-arg --check-prefixes=CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t +; RUN: cat %t | FileCheck %s + +; CHECK-INTERESTINGNESS: ret i32 + +; CHECK-LABEL: define i32 @main() { +define i32 @main() { + +; CHECK-LABEL: lb1: +; CHECK-LABEL: br label %lb2 +lb1: + br label %lb2 + +; CHECK-LABEL: lb2: +; CHECK-NEXT: ret i32 0 +lb2: + ret i32 10 +} \ No newline at end of file diff --git a/llvm/test/tools/llvm-reduce/remove-single-arg.ll b/llvm/test/tools/llvm-reduce/remove-single-arg.ll --- a/llvm/test/tools/llvm-reduce/remove-single-arg.ll +++ b/llvm/test/tools/llvm-reduce/remove-single-arg.ll @@ -1,4 +1,4 @@ -; RUN: llvm-reduce --test FileCheck --test-arg --check-prefixes=CHECK-ALL,CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t +; RUN: llvm-reduce --delta-passes=arguments --test FileCheck --test-arg --check-prefixes=CHECK-ALL,CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t ; RUN: cat %t | FileCheck --check-prefixes=CHECK-ALL,CHECK-FINAL %s define i32 @t(i32 %a0) { diff --git a/llvm/tools/llvm-reduce/CMakeLists.txt b/llvm/tools/llvm-reduce/CMakeLists.txt --- a/llvm/tools/llvm-reduce/CMakeLists.txt +++ b/llvm/tools/llvm-reduce/CMakeLists.txt @@ -28,6 +28,7 @@ deltas/ReduceModuleData.cpp deltas/ReduceOperandBundles.cpp deltas/ReduceSpecialGlobals.cpp + deltas/ReduceOperands.cpp llvm-reduce.cpp DEPENDS diff --git a/llvm/tools/llvm-reduce/DeltaManager.cpp b/llvm/tools/llvm-reduce/DeltaManager.cpp --- a/llvm/tools/llvm-reduce/DeltaManager.cpp +++ b/llvm/tools/llvm-reduce/DeltaManager.cpp @@ -27,6 +27,7 @@ #include "deltas/ReduceMetadata.h" #include "deltas/ReduceModuleData.h" #include "deltas/ReduceOperandBundles.h" +#include "deltas/ReduceOperands.h" #include "deltas/ReduceSpecialGlobals.h" #include "llvm/Support/CommandLine.h" @@ -49,6 +50,7 @@ DELTA_PASS("metadata", reduceMetadataDeltaPass) \ DELTA_PASS("arguments", reduceArgumentsDeltaPass) \ DELTA_PASS("instructions", reduceInstructionsDeltaPass) \ + DELTA_PASS("operands", reduceOperandsDeltaPass) \ DELTA_PASS("operand-bundles", reduceOperandBundesDeltaPass) \ DELTA_PASS("attributes", reduceAttributesDeltaPass) \ DELTA_PASS("module-data", reduceModuleDataDeltaPass) diff --git a/llvm/tools/llvm-reduce/deltas/ReduceOperands.h b/llvm/tools/llvm-reduce/deltas/ReduceOperands.h new file mode 100755 --- /dev/null +++ b/llvm/tools/llvm-reduce/deltas/ReduceOperands.h @@ -0,0 +1,22 @@ +//===- ReduceOperands.h - 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 to reduce operands to their null value. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEOPERANDS_H +#define LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEOPERANDS_H + +#include "Delta.h" + +namespace llvm { +void reduceOperandsDeltaPass(TestRunner &Test); +} // namespace llvm + +#endif diff --git a/llvm/tools/llvm-reduce/deltas/ReduceOperands.cpp b/llvm/tools/llvm-reduce/deltas/ReduceOperands.cpp new file mode 100755 --- /dev/null +++ b/llvm/tools/llvm-reduce/deltas/ReduceOperands.cpp @@ -0,0 +1,72 @@ +//===- ReduceOperands.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 to reduce operands to their null value. +// +//===----------------------------------------------------------------------===// + +#include "ReduceOperands.h" +#include "llvm/IR/Constant.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/GlobalValue.h" +#include "llvm/IR/InstIterator.h" +#include "llvm/IR/ValueSymbolTable.h" + +using namespace llvm; + +/// Returns if the given operand is null. +static bool operandIsNullValue(Use &Op) { + if (auto *C = dyn_cast(Op)) + return C->isNullValue(); + return false; +} + +static bool canReduceOperand(Use &Op) { + auto *Ty = Op->getType(); + return !operandIsNullValue(Op) && Constant::hasNullValue(Ty); +} + +/// Sets Operands to their null value. +static void extractOperandsFromModule(std::vector ChunksToKeep, + Module *Program) { + Oracle O(ChunksToKeep); + + // Extract Operands from the module. + for (auto &F : Program->functions()) { + for (auto &I : instructions(&F)) { + for (auto &Op : I.operands()) { + // Filter Operands then set to default values. + if (canReduceOperand(Op) && !O.shouldKeep()) { + auto *Ty = Op->getType(); + Op.set(Constant::getNullValue(Ty)); + } + } + } + } +} + +/// Counts the amount of operands in the module that are not null. +static int countOperands(Module *Program) { + int Count = 0; + for (auto &F : Program->functions()) { + for (auto &I : instructions(&F)) { + for (auto &Op : I.operands()) { + if (canReduceOperand(Op)) { + Count++; + } + } + } + } + return Count; +} + +void llvm::reduceOperandsDeltaPass(TestRunner &Test) { + outs() << "*** Reducing Operands...\n"; + int Count = countOperands(Test.getProgram()); + runDeltaPass(Test, Count, extractOperandsFromModule); +} diff --git a/llvm/utils/gn/secondary/llvm/tools/llvm-reduce/BUILD.gn b/llvm/utils/gn/secondary/llvm/tools/llvm-reduce/BUILD.gn --- a/llvm/utils/gn/secondary/llvm/tools/llvm-reduce/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/tools/llvm-reduce/BUILD.gn @@ -26,6 +26,7 @@ "deltas/ReduceModuleData.cpp", "deltas/ReduceOperandBundles.cpp", "deltas/ReduceSpecialGlobals.cpp", + "deltas/ReduceOperands.cpp", "llvm-reduce.cpp", ] }