--- /dev/null
+; RUN: llvm-reduce %s -o %t --delta-passes=operands-to-args --test FileCheck --test-arg %s --test-arg --input-file
+
+; CHECK: @foo
+
+define void @foo() !dbg !7 {
+entry:
+ %a = alloca i32
+ call void @llvm.dbg.declare(metadata i32* %a, metadata !13, metadata !DIExpression()), !dbg !14
+ ret void
+}
+
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #0
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3, !4, !5, !6}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 14.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "/tmp/a.c", directory: "/")
+!2 = !{i32 7, !"Dwarf Version", i32 4}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{i32 1, !"wchar_size", i32 4}
+!5 = !{i32 7, !"uwtable", i32 1}
+!6 = !{i32 7, !"frame-pointer", i32 2}
+!7 = distinct !DISubprogram(name: "main", scope: !8, file: !8, line: 1, type: !9, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !12)
+!8 = !DIFile(filename: "/tmp/a.c", directory: "")
+!9 = !DISubroutineType(types: !10)
+!10 = !{!11}
+!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!12 = !{}
+!13 = !DILocalVariable(name: "a", scope: !7, file: !8, line: 2, type: !11)
+!14 = !DILocation(line: 2, column: 7, scope: !7)
%t = type { i32, i8 }
+declare void @llvm.foo(metadata)
+
; CHECK-LABEL: define i32 @main
define i32 @main(%t* %a, i32 %a2) {
%i2 = inttoptr i16 1 to i8*
%i3 = inttoptr i16 2 to i8*
%i4 = inttoptr i16 undef to i8*
+ call void @llvm.foo(metadata %t* %a)
br label %lb2
; CHECK-LABEL: lb2:
#include "ReduceOperands.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/InstIterator.h"
+#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/Type.h"
return C && C->isNullValue();
}
+static bool shouldReduceOperand(Use &Op) {
+ Type *Ty = Op->getType();
+ if (Ty->isLabelTy() || Ty->isMetadataTy())
+ return false;
+ // TODO: be more precise about which GEP operands we can reduce (e.g. array
+ // indexes)
+ if (isa<GEPOperator>(Op.getUser()))
+ return false;
+ if (auto *CB = dyn_cast<CallBase>(Op.getUser())) {
+ if (&CB->getCalledOperandUse() == &Op)
+ return false;
+ }
+ return true;
+}
+
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())
+ if (!shouldReduceOperand(Op))
return nullptr;
// Don't replace existing ConstantData Uses.
return isa<ConstantData>(*Op) ? nullptr : UndefValue::get(Op->getType());
errs() << "*** Reducing Operands to one...\n";
auto ReduceValue = [](Use &Op) -> Value * {
// TODO: support floats
- if (isa<GEPOperator>(Op.getUser()))
+ if (!shouldReduceOperand(Op))
return nullptr;
auto *Ty = dyn_cast<IntegerType>(Op->getType());
if (!Ty)
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())
+ if (!shouldReduceOperand(Op))
return nullptr;
// Don't replace existing zeroes.
return isZero(Op) ? nullptr : Constant::getNullValue(Op->getType());
if (!Ty->isFirstClassType())
return false;
- // Don't pass labels as arguments.
- if (Ty->isLabelTy())
+ // Don't pass labels/metadata as arguments.
+ if (Ty->isLabelTy() || Ty->isMetadataTy())
return false;
// No need to replace values that are already arguments.