forked from OSchip/llvm-project
[llvm-reduce] Add reduction passes to reduce operands to undef/1/0
Having non-undef constants in a final llvm-reduce output is nicer than having undefs. This splits the existing reduce-operands pass into three, one which does the same as the current pass of reducing to undef, and two more to reduce to the constant 1 and the constant 0. Do not reduce to undef if the operand is a ConstantData, and do not reduce 0s to 1s. Reducing GEP operands very frequently causes invalid IR (since types may not match up if we index differently into a struct), so don't touch GEPs. Reviewed By: Meinersbur Differential Revision: https://reviews.llvm.org/D111765
This commit is contained in:
parent
922bf57fc8
commit
9660563950
llvm
test/tools/llvm-reduce
tools/llvm-reduce
|
@ -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
|
||||
}
|
||||
|
|
|
@ -1,20 +1,52 @@
|
|||
; Test that llvm-reduce can reduce operands to their default values.
|
||||
; Test that llvm-reduce can reduce operands
|
||||
;
|
||||
; 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
|
||||
; RUN: llvm-reduce --abort-on-invalid-reduction --delta-passes=operands-undef --test FileCheck --test-arg --check-prefixes=CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t
|
||||
; RUN: cat %t | FileCheck %s --check-prefixes=CHECK,UNDEF
|
||||
; RUN: llvm-reduce --abort-on-invalid-reduction --delta-passes=operands-one --test FileCheck --test-arg --check-prefixes=CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t
|
||||
; RUN: cat %t | FileCheck %s --check-prefixes=CHECK,ONE
|
||||
; RUN: llvm-reduce --abort-on-invalid-reduction --delta-passes=operands-zero --test FileCheck --test-arg --check-prefixes=CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t
|
||||
; RUN: cat %t | FileCheck %s --check-prefixes=CHECK,ZERO
|
||||
; RUN: llvm-reduce --test FileCheck --test-arg --check-prefixes=CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t
|
||||
; RUN: cat %t | FileCheck %s --check-prefixes=CHECK,ZERO
|
||||
|
||||
; CHECK-INTERESTINGNESS: inttoptr
|
||||
; CHECK-INTERESTINGNESS: inttoptr
|
||||
; CHECK-INTERESTINGNESS: inttoptr
|
||||
; CHECK-INTERESTINGNESS: inttoptr
|
||||
; CHECK-INTERESTINGNESS: br label
|
||||
; CHECK-INTERESTINGNESS: ret i32
|
||||
|
||||
; CHECK-LABEL: define i32 @main() {
|
||||
define i32 @main() {
|
||||
%t = type { i32, i8 }
|
||||
|
||||
; CHECK-LABEL: define i32 @main
|
||||
define i32 @main(%t* %a, i32 %a2) {
|
||||
|
||||
; CHECK-LABEL: lb1:
|
||||
; CHECK-NEXT: br label %lb2
|
||||
; UNDEF: inttoptr i16 0
|
||||
; UNDEF: inttoptr i16 1
|
||||
; UNDEF: inttoptr i16 2
|
||||
; UNDEF: inttoptr i16 undef
|
||||
; ONE: inttoptr i16 0
|
||||
; ONE: inttoptr i16 1
|
||||
; ONE: inttoptr i16 1
|
||||
; ONE: inttoptr i16 1
|
||||
; ZERO: inttoptr i16 0
|
||||
; ZERO: inttoptr i16 0
|
||||
; ZERO: inttoptr i16 0
|
||||
; ZERO: inttoptr i16 0
|
||||
; CHECK: br label %lb2
|
||||
lb1:
|
||||
%b = getelementptr %t, %t* %a, i32 1, i32 0
|
||||
%i1 = inttoptr i16 0 to i8*
|
||||
%i2 = inttoptr i16 1 to i8*
|
||||
%i3 = inttoptr i16 2 to i8*
|
||||
%i4 = inttoptr i16 undef to i8*
|
||||
br label %lb2
|
||||
|
||||
; CHECK-LABEL: lb2:
|
||||
; CHECK-NEXT: ret i32 undef
|
||||
; UNDEF: ret i32 undef
|
||||
; ONE: ret i32 1
|
||||
; ZERO: ret i32 0
|
||||
lb2:
|
||||
ret i32 10
|
||||
ret i32 %a2
|
||||
}
|
||||
|
|
|
@ -51,7 +51,9 @@ static cl::opt<std::string>
|
|||
DELTA_PASS("metadata", reduceMetadataDeltaPass) \
|
||||
DELTA_PASS("arguments", reduceArgumentsDeltaPass) \
|
||||
DELTA_PASS("instructions", reduceInstructionsDeltaPass) \
|
||||
DELTA_PASS("operands", reduceOperandsDeltaPass) \
|
||||
DELTA_PASS("operands-zero", reduceOperandsZeroDeltaPass) \
|
||||
DELTA_PASS("operands-one", reduceOperandsOneDeltaPass) \
|
||||
DELTA_PASS("operands-undef", reduceOperandsUndefDeltaPass) \
|
||||
DELTA_PASS("operands-to-args", reduceOperandsToArgsDeltaPass) \
|
||||
DELTA_PASS("operand-bundles", reduceOperandBundesDeltaPass) \
|
||||
DELTA_PASS("attributes", reduceAttributesDeltaPass) \
|
||||
|
|
|
@ -1,71 +1,105 @@
|
|||
//===- 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 undef.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "ReduceOperands.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/InstIterator.h"
|
||||
#include "llvm/IR/Operator.h"
|
||||
#include "llvm/IR/Type.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
/// Returns if the given operand is undef.
|
||||
static bool operandIsUndefValue(Use &Op) {
|
||||
if (auto *C = dyn_cast<Constant>(Op)) {
|
||||
return isa<UndefValue>(C);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Returns if an operand can be reduced to undef.
|
||||
/// TODO: make this logic check what types are reducible rather than
|
||||
/// check what types that are not reducible.
|
||||
static bool canReduceOperand(Use &Op) {
|
||||
auto *Ty = Op->getType();
|
||||
// Can't reduce labels to undef
|
||||
return !Ty->isLabelTy() && !operandIsUndefValue(Op);
|
||||
}
|
||||
|
||||
/// Sets Operands to undef.
|
||||
static void extractOperandsFromModule(Oracle &O, Module &Program) {
|
||||
// Extract Operands from the module.
|
||||
static void
|
||||
extractOperandsFromModule(Oracle &O, Module &Program,
|
||||
function_ref<Value *(Use &)> ReduceValue) {
|
||||
for (auto &F : Program.functions()) {
|
||||
for (auto &I : instructions(&F)) {
|
||||
for (auto &Op : I.operands()) {
|
||||
// Filter Operands then set to undef.
|
||||
if (canReduceOperand(Op) && !O.shouldKeep()) {
|
||||
auto *Ty = Op->getType();
|
||||
Op.set(UndefValue::get(Ty));
|
||||
}
|
||||
Value *Reduced = ReduceValue(Op);
|
||||
if (Reduced && !O.shouldKeep())
|
||||
Op.set(Reduced);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Counts the amount of operands in the module that can be reduced.
|
||||
static int countOperands(Module &Program) {
|
||||
static int countOperands(Module &Program,
|
||||
function_ref<Value *(Use &)> ReduceValue) {
|
||||
int Count = 0;
|
||||
for (auto &F : Program.functions()) {
|
||||
for (auto &I : instructions(&F)) {
|
||||
for (auto &Op : I.operands()) {
|
||||
if (canReduceOperand(Op)) {
|
||||
if (ReduceValue(Op))
|
||||
Count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Count;
|
||||
}
|
||||
|
||||
void llvm::reduceOperandsDeltaPass(TestRunner &Test) {
|
||||
errs() << "*** Reducing Operands...\n";
|
||||
int Count = countOperands(Test.getProgram());
|
||||
runDeltaPass(Test, Count, extractOperandsFromModule);
|
||||
static bool isOne(Use &Op) {
|
||||
auto *C = dyn_cast<Constant>(Op);
|
||||
return C && C->isOneValue();
|
||||
}
|
||||
|
||||
static bool isZero(Use &Op) {
|
||||
auto *C = dyn_cast<Constant>(Op);
|
||||
return C && C->isNullValue();
|
||||
}
|
||||
|
||||
void llvm::reduceOperandsUndefDeltaPass(TestRunner &Test) {
|
||||
errs() << "*** Reducing Operands to undef...\n";
|
||||
auto ReduceValue = [](Use &Op) -> Value * {
|
||||
if (isa<GEPOperator>(Op.getUser()))
|
||||
return nullptr;
|
||||
if (Op->getType()->isLabelTy())
|
||||
return nullptr;
|
||||
// Don't replace existing ConstantData Uses.
|
||||
return isa<ConstantData>(*Op) ? nullptr : UndefValue::get(Op->getType());
|
||||
};
|
||||
int Count = countOperands(Test.getProgram(), ReduceValue);
|
||||
runDeltaPass(Test, Count, [ReduceValue](Oracle &O, Module &Program) {
|
||||
extractOperandsFromModule(O, Program, ReduceValue);
|
||||
});
|
||||
}
|
||||
|
||||
void llvm::reduceOperandsOneDeltaPass(TestRunner &Test) {
|
||||
errs() << "*** Reducing Operands to one...\n";
|
||||
auto ReduceValue = [](Use &Op) -> Value * {
|
||||
// TODO: support floats
|
||||
if (isa<GEPOperator>(Op.getUser()))
|
||||
return nullptr;
|
||||
auto *Ty = dyn_cast<IntegerType>(Op->getType());
|
||||
if (!Ty)
|
||||
return nullptr;
|
||||
// Don't replace existing ones and zeroes.
|
||||
return (isOne(Op) || isZero(Op)) ? nullptr : ConstantInt::get(Ty, 1);
|
||||
};
|
||||
int Count = countOperands(Test.getProgram(), ReduceValue);
|
||||
runDeltaPass(Test, Count, [ReduceValue](Oracle &O, Module &Program) {
|
||||
extractOperandsFromModule(O, Program, ReduceValue);
|
||||
});
|
||||
}
|
||||
|
||||
void llvm::reduceOperandsZeroDeltaPass(TestRunner &Test) {
|
||||
errs() << "*** Reducing Operands to zero...\n";
|
||||
auto ReduceValue = [](Use &Op) -> Value * {
|
||||
// TODO: be more precise about which GEP operands we can reduce (e.g. array
|
||||
// indexes)
|
||||
if (isa<GEPOperator>(Op.getUser()))
|
||||
return nullptr;
|
||||
if (Op->getType()->isLabelTy())
|
||||
return nullptr;
|
||||
// Don't replace existing zeroes.
|
||||
return isZero(Op) ? nullptr : Constant::getNullValue(Op->getType());
|
||||
};
|
||||
int Count = countOperands(Test.getProgram(), ReduceValue);
|
||||
runDeltaPass(Test, Count, [ReduceValue](Oracle &O, Module &Program) {
|
||||
extractOperandsFromModule(O, Program, ReduceValue);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,14 +1,10 @@
|
|||
//===- 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 undef.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEOPERANDS_H
|
||||
#define LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEOPERANDS_H
|
||||
|
@ -16,7 +12,9 @@
|
|||
#include "Delta.h"
|
||||
|
||||
namespace llvm {
|
||||
void reduceOperandsDeltaPass(TestRunner &Test);
|
||||
void reduceOperandsUndefDeltaPass(TestRunner &Test);
|
||||
void reduceOperandsOneDeltaPass(TestRunner &Test);
|
||||
void reduceOperandsZeroDeltaPass(TestRunner &Test);
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue