return nullptr;
}
-static Optional<ConstantInt *>
-getAssumedConstant(Attributor &A, const Value &V, const AbstractAttribute &AA,
- bool &UsedAssumedInformation) {
+static Optional<Constant *> getAssumedConstant(Attributor &A, const Value &V,
+ const AbstractAttribute &AA,
+ bool &UsedAssumedInformation) {
const auto &ValueSimplifyAA = A.getAAFor<AAValueSimplify>(
AA, IRPosition::value(V), /* TrackDependence */ false);
Optional<Value *> SimplifiedV = ValueSimplifyAA.getAssumedSimplifiedValue(A);
A.recordDependence(ValueSimplifyAA, AA, DepClassTy::OPTIONAL);
return llvm::None;
}
- ConstantInt *CI = dyn_cast_or_null<ConstantInt>(SimplifiedV.getValue());
+ Constant *CI = dyn_cast_or_null<Constant>(SimplifiedV.getValue());
+ if (CI && CI->getType() != V.getType()) {
+ // TODO: Check for a save conversion.
+ return nullptr;
+ }
if (CI)
A.recordDependence(ValueSimplifyAA, AA, DepClassTy::OPTIONAL);
return CI;
}
+static Optional<ConstantInt *>
+getAssumedConstantInt(Attributor &A, const Value &V,
+ const AbstractAttribute &AA,
+ bool &UsedAssumedInformation) {
+ Optional<Constant *> C = getAssumedConstant(A, V, AA, UsedAssumedInformation);
+ if (C.hasValue())
+ return dyn_cast_or_null<ConstantInt>(C.getValue());
+ return llvm::None;
+}
+
/// Get pointer operand of memory accessing instruction. If \p I is
/// not a memory accessing instruction, return nullptr. If \p AllowVolatile,
/// is set to false and the instruction is volatile, return nullptr.
return ChangeStatus::UNCHANGED;
bool UsedAssumedInformation = false;
- Optional<ConstantInt *> CI =
+ Optional<Constant *> C =
getAssumedConstant(A, V, *this, UsedAssumedInformation);
- if (CI.hasValue() && CI.getValue())
+ if (C.hasValue() && C.getValue())
return ChangeStatus::UNCHANGED;
UndefValue &UV = *UndefValue::get(V.getType());
if (BI.getNumSuccessors() == 1) {
AliveSuccessors.push_back(&BI.getSuccessor(0)->front());
} else {
- Optional<ConstantInt *> CI =
- getAssumedConstant(A, *BI.getCondition(), AA, UsedAssumedInformation);
+ Optional<ConstantInt *> CI = getAssumedConstantInt(
+ A, *BI.getCondition(), AA, UsedAssumedInformation);
if (!CI.hasValue()) {
// No value yet, assume both edges are dead.
} else if (CI.getValue()) {
SmallVectorImpl<const Instruction *> &AliveSuccessors) {
bool UsedAssumedInformation = false;
Optional<ConstantInt *> CI =
- getAssumedConstant(A, *SI.getCondition(), AA, UsedAssumedInformation);
+ getAssumedConstantInt(A, *SI.getCondition(), AA, UsedAssumedInformation);
if (!CI.hasValue()) {
// No value yet, assume all edges are dead.
} else if (CI.getValue()) {
// instead use the `follow` callback argument to look at transitive users,
// however, that should be clear from the presence of the argument.
bool UsedAssumedInformation = false;
- Optional<ConstantInt *> CI =
+ Optional<Constant *> C =
getAssumedConstant(*this, V, QueryingAA, UsedAssumedInformation);
- if (CI.hasValue() && CI.getValue()) {
+ if (C.hasValue() && C.getValue()) {
LLVM_DEBUG(dbgs() << "[Attributor] Value is simplified, uses skipped: " << V
- << " -> " << *CI.getValue() << "\n");
+ << " -> " << *C.getValue() << "\n");
return true;
}
; This test tries to convince CHECK about promoting the load from %A + 2,
; because there is a load of %A in the entry block
define internal i32 @callee(i1 %C, i32* %A) {
-; CHECK-LABEL: define {{[^@]+}}@callee
-; CHECK-SAME: (i32* noalias nocapture nofree nonnull readonly align 536870912 dereferenceable(4) [[A:%.*]])
+; CHECK-LABEL: define {{[^@]+}}@callee()
; CHECK-NEXT: entry:
; CHECK-NEXT: [[A_0:%.*]] = load i32, i32* null, align 536870912
; CHECK-NEXT: br label [[F:%.*]]
define i32 @foo() {
; CHECK-LABEL: define {{[^@]+}}@foo()
-; CHECK-NEXT: [[X:%.*]] = call i32 @callee(i32* noalias nofree readonly align 536870912 null)
+; CHECK-NEXT: [[X:%.*]] = call i32 @callee()
; CHECK-NEXT: ret i32 [[X]]
;
%X = call i32 @callee(i1 false, i32* null) ; <i32> [#uses=1]
@G2 = constant i32* @G1
define internal i32 @test(i32** %x) {
-; CHECK-LABEL: define {{[^@]+}}@test
-; CHECK-SAME: (i32** nocapture nofree nonnull readonly align 8 dereferenceable(8) [[X:%.*]])
+; CHECK-LABEL: define {{[^@]+}}@test()
; CHECK-NEXT: entry:
; CHECK-NEXT: [[Y:%.*]] = load i32*, i32** @G2, align 8
; CHECK-NEXT: [[Z:%.*]] = load i32, i32* [[Y]]
define i32 @caller() {
; CHECK-LABEL: define {{[^@]+}}@caller()
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[X:%.*]] = call i32 @test(i32** nofree nonnull readonly align 8 dereferenceable(8) @G2)
+; CHECK-NEXT: [[X:%.*]] = call i32 @test()
; CHECK-NEXT: ret i32 [[X]]
;
entry:
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
-; RUN: opt -S -basicaa -attributor -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=4 < %s | FileCheck %s --check-prefixes=CHECK,OLDPM,OLDPM_MODULE
+; RUN: opt -S -basicaa -attributor -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=7 < %s | FileCheck %s --check-prefixes=CHECK,OLDPM,OLDPM_MODULE
; RUN: opt -S -basicaa -attributor-cgscc -attributor-disable=false < %s | FileCheck %s --check-prefixes=CHECK,OLDPM,OLDPM_CGSCC
-; RUN: opt -S -passes='attributor' -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=4 < %s | FileCheck %s --check-prefixes=CHECK,NEWPM,NEWPM_MODULE
+; RUN: opt -S -passes='attributor' -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=7 < %s | FileCheck %s --check-prefixes=CHECK,NEWPM,NEWPM_MODULE
; RUN: opt -S -passes='attributor-cgscc' -aa-pipeline='basic-aa' -attributor-disable=false < %s | FileCheck %s --check-prefixes=CHECK,NEWPM,NEWPM_CGSCC
; OLDPM_MODULE-NOT: @dead
; This test is just to verify that we do not crash/assert due to mismatch in
; argument count between the caller and callee.
+; FIXME we should recognize this as UB and make it an unreachable.
+
define dso_local i16 @foo(i16 %a) {
; CHECK-LABEL: define {{[^@]+}}@foo
; CHECK-SAME: (i16 [[A:%.*]])
define internal i8* @no_side_effects(i8 %v) readonly nounwind {
; CHECK-LABEL: define {{[^@]+}}@no_side_effects
; CHECK-SAME: (i8 [[V:%.*]])
-; CHECK-NEXT: ret i8* null
+; CHECK-NEXT: ret i8* undef
;
ret i8* null
}
; CHECK-LABEL: define {{[^@]+}}@dont_zap_me
; CHECK-SAME: (i8 [[V:%.*]])
; CHECK-NEXT: [[I1:%.*]] = call i32 @external()
-; CHECK-NEXT: ret i8* null
+; CHECK-NEXT: ret i8* undef
;
%i1 = call i32 @external()
ret i8* null
; FIXME: nocapture & noalias for %alloc2 in %call3
define dso_local i32 @main() {
-; CHECK-LABEL: define {{[^@]+}}@main()
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[ALLOC1:%.*]] = alloca i8, align 8
-; CHECK-NEXT: [[ALLOC2:%.*]] = alloca i8, align 8
-; CHECK-NEXT: [[THREAD:%.*]] = alloca i64, align 8
-; CHECK-NEXT: [[CALL:%.*]] = call i32 @pthread_create(i64* nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias align 536870912 null, i8* (i8*)* nonnull @foo, i8* noalias nofree readnone align 536870912 null)
-; CHECK-NEXT: [[CALL1:%.*]] = call i32 @pthread_create(i64* nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias align 536870912 null, i8* (i8*)* nonnull @bar, i8* noalias nofree nonnull readnone align 8 dereferenceable(8) bitcast (i8** @GlobalVPtr to i8*))
-; CHECK-NEXT: [[CALL2:%.*]] = call i32 @pthread_create(i64* nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias align 536870912 null, i8* (i8*)* nonnull @baz, i8* noalias nocapture nofree nonnull readnone align 8 dereferenceable(1) [[ALLOC1]])
-; CHECK-NEXT: [[CALL3:%.*]] = call i32 @pthread_create(i64* nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias align 536870912 null, i8* (i8*)* nonnull @buz, i8* noalias nofree nonnull readnone align 8 dereferenceable(1) [[ALLOC2]])
-; CHECK-NEXT: ret i32 0
+; MODULE-LABEL: define {{[^@]+}}@main()
+; MODULE-NEXT: entry:
+; MODULE-NEXT: [[ALLOC1:%.*]] = alloca i8, align 8
+; MODULE-NEXT: [[ALLOC2:%.*]] = alloca i8, align 8
+; MODULE-NEXT: [[THREAD:%.*]] = alloca i64, align 8
+; MODULE-NEXT: [[CALL:%.*]] = call i32 @pthread_create(i64* nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias align 536870912 null, i8* (i8*)* nonnull @foo, i8* noalias nofree readnone align 536870912 undef)
+; MODULE-NEXT: [[CALL1:%.*]] = call i32 @pthread_create(i64* nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias align 536870912 null, i8* (i8*)* nonnull @bar, i8* noalias nofree nonnull readnone align 8 dereferenceable(8) undef)
+; MODULE-NEXT: [[CALL2:%.*]] = call i32 @pthread_create(i64* nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias align 536870912 null, i8* (i8*)* nonnull @baz, i8* noalias nocapture nofree nonnull readnone align 8 dereferenceable(1) [[ALLOC1]])
+; MODULE-NEXT: [[CALL3:%.*]] = call i32 @pthread_create(i64* nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias align 536870912 null, i8* (i8*)* nonnull @buz, i8* noalias nofree nonnull readnone align 8 dereferenceable(1) [[ALLOC2]])
+; MODULE-NEXT: ret i32 0
+;
+; CGSCC-LABEL: define {{[^@]+}}@main()
+; CGSCC-NEXT: entry:
+; CGSCC-NEXT: [[ALLOC1:%.*]] = alloca i8, align 8
+; CGSCC-NEXT: [[ALLOC2:%.*]] = alloca i8, align 8
+; CGSCC-NEXT: [[THREAD:%.*]] = alloca i64, align 8
+; CGSCC-NEXT: [[CALL:%.*]] = call i32 @pthread_create(i64* nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias align 536870912 null, i8* (i8*)* nonnull @foo, i8* noalias nofree readnone align 536870912 null)
+; CGSCC-NEXT: [[CALL1:%.*]] = call i32 @pthread_create(i64* nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias align 536870912 null, i8* (i8*)* nonnull @bar, i8* noalias nofree nonnull readnone align 8 dereferenceable(8) bitcast (i8** @GlobalVPtr to i8*))
+; CGSCC-NEXT: [[CALL2:%.*]] = call i32 @pthread_create(i64* nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias align 536870912 null, i8* (i8*)* nonnull @baz, i8* noalias nocapture nofree nonnull readnone align 8 dereferenceable(1) [[ALLOC1]])
+; CGSCC-NEXT: [[CALL3:%.*]] = call i32 @pthread_create(i64* nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias align 536870912 null, i8* (i8*)* nonnull @buz, i8* noalias nofree nonnull readnone align 8 dereferenceable(1) [[ALLOC2]])
+; CGSCC-NEXT: ret i32 0
;
entry:
%alloc1 = alloca i8, align 8
define dso_local void @caller() {
; CHECK-LABEL: define {{[^@]+}}@caller()
; CHECK-NEXT: entry:
-; CHECK-NEXT: call void @broker(i32* nofree nonnull readonly align 4 dereferenceable(4) @gtl, i32 (i32*, i32*)* nonnull @callee, i32* nofree nonnull readonly align 4 dereferenceable(4) @gsh)
+; CHECK-NEXT: call void @broker(i32* nofree nonnull readonly align 4 dereferenceable(4) @gtl, i32 (i32*, i32*)* nonnull @callee, i32* nofree nonnull readonly align 4 dereferenceable(4) undef)
; CHECK-NEXT: ret void
;
entry:
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --turn off
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --disable --function-signature --scrub-attributes
; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=6 -S < %s | FileCheck %s --check-prefixes=ATTRIBUTOR,ATTRIBUTOR_MODULE
; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-disable=false -attributor-annotate-decl-cs -attributor-max-iterations=6 -S < %s | FileCheck %s --check-prefixes=ATTRIBUTOR,ATTRIBUTOR_CGSCC
; RUN: opt -passes=attributor -attributor-manifest-internal -attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=6 -S < %s | FileCheck %s --check-prefixes=ATTRIBUTOR,ATTRIBUTOR_MODULE
; TEST 7
; Better than IR information
define align 4 i8* @test7() #0 {
-; ATTRIBUTOR_MODULE-LABEL: define {{[^@]+}}@test7
+; ATTRIBUTOR_MODULE-LABEL: define {{[^@]+}}@test7()
; ATTRIBUTOR_MODULE-NEXT: [[C:%.*]] = tail call i8* @f1(i8* noalias nofree nonnull readnone align 8 dereferenceable(1) @a1)
; ATTRIBUTOR_MODULE-NEXT: ret i8* [[C]]
;
-; ATTRIBUTOR_CGSCC-LABEL: define {{[^@]+}}@test7
-; ATTRIBUTOR_CGSCC-SAME: ()
+; ATTRIBUTOR_CGSCC-LABEL: define {{[^@]+}}@test7()
; ATTRIBUTOR_CGSCC-NEXT: [[C:%.*]] = tail call nonnull align 8 dereferenceable(1) i8* @f1(i8* noalias nofree nonnull readnone align 8 dereferenceable(1) @a1)
; ATTRIBUTOR_CGSCC-NEXT: ret i8* [[C]]
;
; ATTRIBUTOR_MODULE-NEXT: [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null
; ATTRIBUTOR_MODULE-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]]
; ATTRIBUTOR_MODULE: 3:
-; ATTRIBUTOR_MODULE-NEXT: [[TMP4:%.*]] = tail call align 8 i8* @f2b(i8* noalias nofree nonnull readnone align 8 dereferenceable(1) @a1)
+; ATTRIBUTOR_MODULE-NEXT: [[TMP4:%.*]] = tail call align 8 i8* @f2b()
; ATTRIBUTOR_MODULE-NEXT: [[L:%.*]] = load i8, i8* [[TMP4]], align 8
; ATTRIBUTOR_MODULE-NEXT: store i8 [[L]], i8* @a1, align 8
; ATTRIBUTOR_MODULE-NEXT: br label [[TMP5]]
; ATTRIBUTOR_CGSCC-NEXT: [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null
; ATTRIBUTOR_CGSCC-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]]
; ATTRIBUTOR_CGSCC: 3:
-; ATTRIBUTOR_CGSCC-NEXT: [[TMP4:%.*]] = tail call align 8 i8* @f2b(i8* noalias nofree nonnull readnone align 8 dereferenceable(1) @a1)
+; ATTRIBUTOR_CGSCC-NEXT: [[TMP4:%.*]] = tail call align 8 i8* @f2b()
; ATTRIBUTOR_CGSCC-NEXT: [[L:%.*]] = load i8, i8* [[TMP4]], align 8
; ATTRIBUTOR_CGSCC-NEXT: store i8 [[L]], i8* @a1, align 8
; ATTRIBUTOR_CGSCC-NEXT: br label [[TMP5]]
; Function Attrs: nounwind readnone ssp uwtable
define internal i8* @f2b(i8* readnone %0) local_unnamed_addr #0 {
;
-; ATTRIBUTOR-LABEL: define {{[^@]+}}@f2b
-; ATTRIBUTOR-SAME: (i8* noalias nofree nonnull readnone align 8 dereferenceable(1) "no-capture-maybe-returned" [[TMP0:%.*]]) local_unnamed_addr
-; ATTRIBUTOR-NEXT: [[TMP2:%.*]] = icmp eq i8* @a1, null
-; ATTRIBUTOR-NEXT: br i1 [[TMP2]], label [[TMP5:%.*]], label [[TMP3:%.*]]
-; ATTRIBUTOR: 3:
-; ATTRIBUTOR-NEXT: [[TMP4:%.*]] = tail call i8* @f1b(i8* noalias nofree nonnull readnone align 8 dereferenceable(1) "no-capture-maybe-returned" @a1)
-; ATTRIBUTOR-NEXT: br label [[TMP7:%.*]]
-; ATTRIBUTOR: 5:
-; ATTRIBUTOR-NEXT: [[TMP6:%.*]] = tail call i8* @f3b(i8* noalias nofree nonnull readnone align 16 dereferenceable(1) @a2)
-; ATTRIBUTOR-NEXT: br label [[TMP7]]
-; ATTRIBUTOR: 7:
-; ATTRIBUTOR-NEXT: [[TMP8:%.*]] = phi i8* [ [[TMP4]], [[TMP3]] ], [ [[TMP6]], [[TMP5]] ]
-; ATTRIBUTOR-NEXT: ret i8* [[TMP8]]
+; ATTRIBUTOR-LABEL: define {{[^@]+}}@f2b() local_unnamed_addr
+; ATTRIBUTOR-NEXT: [[TMP1:%.*]] = icmp eq i8* @a1, null
+; ATTRIBUTOR-NEXT: br i1 [[TMP1]], label [[TMP4:%.*]], label [[TMP2:%.*]]
+; ATTRIBUTOR: 2:
+; ATTRIBUTOR-NEXT: [[TMP3:%.*]] = tail call i8* @f1b(i8* noalias nofree nonnull readnone align 8 dereferenceable(1) "no-capture-maybe-returned" @a1)
+; ATTRIBUTOR-NEXT: br label [[TMP6:%.*]]
+; ATTRIBUTOR: 4:
+; ATTRIBUTOR-NEXT: [[TMP5:%.*]] = tail call i8* @f3b()
+; ATTRIBUTOR-NEXT: br label [[TMP6]]
+; ATTRIBUTOR: 6:
+; ATTRIBUTOR-NEXT: [[TMP7:%.*]] = phi i8* [ [[TMP3]], [[TMP2]] ], [ [[TMP5]], [[TMP4]] ]
+; ATTRIBUTOR-NEXT: ret i8* [[TMP7]]
;
%2 = icmp eq i8* %0, null
br i1 %2, label %5, label %3
; Function Attrs: nounwind readnone ssp uwtable
define internal i8* @f3b(i8* readnone %0) local_unnamed_addr #0 {
;
-; ATTRIBUTOR-LABEL: define {{[^@]+}}@f3b
-; ATTRIBUTOR-SAME: (i8* noalias nocapture nofree nonnull readnone align 16 dereferenceable(1) [[TMP0:%.*]]) local_unnamed_addr
-; ATTRIBUTOR-NEXT: [[TMP2:%.*]] = icmp eq i8* @a2, null
-; ATTRIBUTOR-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]]
-; ATTRIBUTOR: 3:
-; ATTRIBUTOR-NEXT: [[TMP4:%.*]] = tail call i8* @f1b(i8* noalias nofree nonnull readnone align 16 dereferenceable(1) @a2)
-; ATTRIBUTOR-NEXT: br label [[TMP5]]
-; ATTRIBUTOR: 5:
-; ATTRIBUTOR-NEXT: [[TMP6:%.*]] = phi i8* [ [[TMP4]], [[TMP3]] ], [ @a1, [[TMP1:%.*]] ]
-; ATTRIBUTOR-NEXT: ret i8* [[TMP6]]
+; ATTRIBUTOR-LABEL: define {{[^@]+}}@f3b() local_unnamed_addr
+; ATTRIBUTOR-NEXT: [[TMP1:%.*]] = icmp eq i8* @a2, null
+; ATTRIBUTOR-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP4:%.*]]
+; ATTRIBUTOR: 2:
+; ATTRIBUTOR-NEXT: [[TMP3:%.*]] = tail call i8* @f1b(i8* noalias nofree nonnull readnone align 16 dereferenceable(1) @a2)
+; ATTRIBUTOR-NEXT: br label [[TMP4]]
+; ATTRIBUTOR: 4:
+; ATTRIBUTOR-NEXT: [[TMP5:%.*]] = phi i8* [ [[TMP3]], [[TMP2]] ], [ @a1, [[TMP0:%.*]] ]
+; ATTRIBUTOR-NEXT: ret i8* [[TMP5]]
;
%2 = icmp eq i8* %0, null
br i1 %2, label %3, label %5
; MODULE-NEXT: call void @called_via_pointer(i32* [[A]], i32* nonnull align 128 dereferenceable(4) [[B]], i32* [[A]], i64 -1, i32** null)
; MODULE-NEXT: ret void
;
-; CGSCC-LABEL: define {{[^@]+}}@call_via_pointer_with_dead_args_internal_a
-; CGSCC-SAME: (i32* [[A:%.*]], i32* [[B:%.*]], void (i32*, i32*, i32*, i64, i32**)* nocapture nofree nonnull [[FP:%.*]])
-; CGSCC-NEXT: call void @called_via_pointer(i32* [[A]], i32* [[B]], i32* [[A]], i64 -1, i32** null)
-; CGSCC-NEXT: ret void
+; CGSCC_OLD-LABEL: define {{[^@]+}}@call_via_pointer_with_dead_args_internal_a
+; CGSCC_OLD-SAME: (i32* [[A:%.*]], i32* [[B:%.*]])
+; CGSCC_OLD-NEXT: call void @called_via_pointer(i32* [[A]], i32* [[B]], i32* [[A]], i64 -1, i32** null)
+; CGSCC_OLD-NEXT: ret void
+;
+; CGSCC_NEW-LABEL: define {{[^@]+}}@call_via_pointer_with_dead_args_internal_a
+; CGSCC_NEW-SAME: (i32* [[A:%.*]], i32* [[B:%.*]], void (i32*, i32*, i32*, i64, i32**)* nocapture nofree nonnull [[FP:%.*]])
+; CGSCC_NEW-NEXT: call void [[FP]](i32* [[A]], i32* [[B]], i32* [[A]], i64 -1, i32** null)
+; CGSCC_NEW-NEXT: ret void
;
call void %fp(i32* %a, i32* %b, i32* %a, i64 -1, i32** null)
ret void
; MODULE-NEXT: call void @called_via_pointer_internal_2(i32* [[A]], i32* nonnull align 128 dereferenceable(4) [[B]], i32* [[A]], i64 -1, i32** null)
; MODULE-NEXT: ret void
;
-; CGSCC-LABEL: define {{[^@]+}}@call_via_pointer_with_dead_args_internal_b
-; CGSCC-SAME: (i32* [[A:%.*]], i32* [[B:%.*]], void (i32*, i32*, i32*, i64, i32**)* nocapture nofree nonnull [[FP:%.*]])
-; CGSCC-NEXT: call void @called_via_pointer_internal_2(i32* [[A]], i32* [[B]], i32* [[A]], i64 -1, i32** noalias null)
-; CGSCC-NEXT: ret void
+; CGSCC_OLD-LABEL: define {{[^@]+}}@call_via_pointer_with_dead_args_internal_b
+; CGSCC_OLD-SAME: (i32* [[A:%.*]], i32* [[B:%.*]])
+; CGSCC_OLD-NEXT: call void @called_via_pointer_internal_2(i32* [[A]])
+; CGSCC_OLD-NEXT: ret void
+;
+; CGSCC_NEW-LABEL: define {{[^@]+}}@call_via_pointer_with_dead_args_internal_b
+; CGSCC_NEW-SAME: (i32* [[A:%.*]], i32* [[B:%.*]], void (i32*, i32*, i32*, i64, i32**)* nocapture nofree nonnull [[FP:%.*]])
+; CGSCC_NEW-NEXT: call void [[FP]](i32* [[A]], i32* [[B]], i32* [[A]], i64 -1, i32** null)
+; CGSCC_NEW-NEXT: ret void
;
call void %fp(i32* %a, i32* %b, i32* %a, i64 -1, i32** null)
ret void
}
define void @call_via_pointer_with_dead_args_caller(i32* %a, i32* %b) {
-; CHECK-LABEL: define {{[^@]+}}@call_via_pointer_with_dead_args_caller
-; CHECK-SAME: (i32* [[A:%.*]], i32* [[B:%.*]])
-; CHECK-NEXT: [[PTR1:%.*]] = alloca i32, align 128
-; CHECK-NEXT: [[PTR2:%.*]] = alloca i32, align 128
-; CHECK-NEXT: [[PTR3:%.*]] = alloca i32, align 128
-; CHECK-NEXT: [[PTR4:%.*]] = alloca i32, align 128
-; CHECK-NEXT: call void @call_via_pointer_with_dead_args(i32* [[A]], i32* nonnull align 128 dereferenceable(4) [[PTR1]], void (i32*, i32*, i32*, i64, i32**)* nofree nonnull @called_via_pointer)
-; CHECK-NEXT: call void @call_via_pointer_with_dead_args(i32* [[A]], i32* nonnull align 128 dereferenceable(4) [[PTR2]], void (i32*, i32*, i32*, i64, i32**)* nofree nonnull @called_via_pointer_internal_1)
-; CHECK-NEXT: call void @call_via_pointer_with_dead_args_internal_a(i32* [[B]], i32* nonnull align 128 dereferenceable(4) [[PTR3]], void (i32*, i32*, i32*, i64, i32**)* nofree nonnull @called_via_pointer)
-; CHECK-NEXT: call void @call_via_pointer_with_dead_args_internal_b(i32* [[B]], i32* nonnull align 128 dereferenceable(4) [[PTR4]], void (i32*, i32*, i32*, i64, i32**)* nofree nonnull @called_via_pointer_internal_2)
-; CHECK-NEXT: ret void
+; MODULE-LABEL: define {{[^@]+}}@call_via_pointer_with_dead_args_caller
+; MODULE-SAME: (i32* [[A:%.*]], i32* [[B:%.*]])
+; MODULE-NEXT: [[PTR1:%.*]] = alloca i32, align 128
+; MODULE-NEXT: [[PTR2:%.*]] = alloca i32, align 128
+; MODULE-NEXT: [[PTR3:%.*]] = alloca i32, align 128
+; MODULE-NEXT: [[PTR4:%.*]] = alloca i32, align 128
+; MODULE-NEXT: call void @call_via_pointer_with_dead_args(i32* [[A]], i32* nonnull align 128 dereferenceable(4) [[PTR1]], void (i32*, i32*, i32*, i64, i32**)* nofree nonnull @called_via_pointer)
+; MODULE-NEXT: call void @call_via_pointer_with_dead_args(i32* [[A]], i32* nonnull align 128 dereferenceable(4) [[PTR2]], void (i32*, i32*, i32*, i64, i32**)* nofree nonnull @called_via_pointer_internal_1)
+; MODULE-NEXT: call void @call_via_pointer_with_dead_args_internal_a(i32* [[B]], i32* nonnull align 128 dereferenceable(4) [[PTR3]], void (i32*, i32*, i32*, i64, i32**)* nofree nonnull @called_via_pointer)
+; MODULE-NEXT: call void @call_via_pointer_with_dead_args_internal_b(i32* [[B]], i32* nonnull align 128 dereferenceable(4) [[PTR4]], void (i32*, i32*, i32*, i64, i32**)* nofree nonnull @called_via_pointer_internal_2)
+; MODULE-NEXT: ret void
+;
+; CGSCC_OLD-LABEL: define {{[^@]+}}@call_via_pointer_with_dead_args_caller
+; CGSCC_OLD-SAME: (i32* [[A:%.*]], i32* [[B:%.*]])
+; CGSCC_OLD-NEXT: [[PTR1:%.*]] = alloca i32, align 128
+; CGSCC_OLD-NEXT: [[PTR2:%.*]] = alloca i32, align 128
+; CGSCC_OLD-NEXT: [[PTR3:%.*]] = alloca i32, align 128
+; CGSCC_OLD-NEXT: [[PTR4:%.*]] = alloca i32, align 128
+; CGSCC_OLD-NEXT: call void @call_via_pointer_with_dead_args(i32* [[A]], i32* nonnull align 128 dereferenceable(4) [[PTR1]], void (i32*, i32*, i32*, i64, i32**)* nofree nonnull @called_via_pointer)
+; CGSCC_OLD-NEXT: call void @call_via_pointer_with_dead_args(i32* [[A]], i32* nonnull align 128 dereferenceable(4) [[PTR2]], void (i32*, i32*, i32*, i64, i32**)* nofree nonnull @called_via_pointer_internal_1)
+; CGSCC_OLD-NEXT: call void @call_via_pointer_with_dead_args_internal_a(i32* [[B]], i32* nonnull align 128 dereferenceable(4) [[PTR3]])
+; CGSCC_OLD-NEXT: call void @call_via_pointer_with_dead_args_internal_b(i32* [[B]], i32* nonnull align 128 dereferenceable(4) [[PTR4]])
+; CGSCC_OLD-NEXT: ret void
+;
+; CGSCC_NEW-LABEL: define {{[^@]+}}@call_via_pointer_with_dead_args_caller
+; CGSCC_NEW-SAME: (i32* [[A:%.*]], i32* [[B:%.*]])
+; CGSCC_NEW-NEXT: [[PTR1:%.*]] = alloca i32, align 128
+; CGSCC_NEW-NEXT: [[PTR2:%.*]] = alloca i32, align 128
+; CGSCC_NEW-NEXT: [[PTR3:%.*]] = alloca i32, align 128
+; CGSCC_NEW-NEXT: [[PTR4:%.*]] = alloca i32, align 128
+; CGSCC_NEW-NEXT: call void @call_via_pointer_with_dead_args(i32* [[A]], i32* nonnull align 128 dereferenceable(4) [[PTR1]], void (i32*, i32*, i32*, i64, i32**)* nofree nonnull @called_via_pointer)
+; CGSCC_NEW-NEXT: call void @call_via_pointer_with_dead_args(i32* [[A]], i32* nonnull align 128 dereferenceable(4) [[PTR2]], void (i32*, i32*, i32*, i64, i32**)* nofree nonnull @called_via_pointer_internal_1)
+; CGSCC_NEW-NEXT: call void @call_via_pointer_with_dead_args_internal_a(i32* [[B]], i32* nonnull align 128 dereferenceable(4) [[PTR3]], void (i32*, i32*, i32*, i64, i32**)* nofree nonnull @called_via_pointer)
+; CGSCC_NEW-NEXT: call void @call_via_pointer_with_dead_args_internal_b(i32* [[B]], i32* nonnull align 128 dereferenceable(4) [[PTR4]], void (i32*, i32*, i32*, i64, i32**)* nofree nonnull @called_via_pointer_internal_2)
+; CGSCC_NEW-NEXT: ret void
;
%ptr1 = alloca i32, align 128
%ptr2 = alloca i32, align 128
}
; FIXME: Figure out why the MODULE has the unused arguments still
define internal void @called_via_pointer_internal_2(i32* %a, i32* %b, i32* %c, i64 %d, i32** %e) {
-; CHECK-LABEL: define {{[^@]+}}@called_via_pointer_internal_2
-; CHECK-SAME: (i32* [[A:%.*]], i32* nocapture nofree readnone [[B:%.*]], i32* nocapture nofree readnone [[C:%.*]], i64 [[D:%.*]], i32** nocapture nofree readnone [[E:%.*]])
-; CHECK-NEXT: entry:
-; CHECK-NEXT: tail call void @use_i32p(i32* [[A]])
-; CHECK-NEXT: tail call void @use_i32p(i32* [[A]])
-; CHECK-NEXT: ret void
+; MODULE-LABEL: define {{[^@]+}}@called_via_pointer_internal_2
+; MODULE-SAME: (i32* [[A:%.*]], i32* nocapture nofree readnone [[B:%.*]], i32* nocapture nofree readnone [[C:%.*]], i64 [[D:%.*]], i32** nocapture nofree readnone [[E:%.*]])
+; MODULE-NEXT: entry:
+; MODULE-NEXT: tail call void @use_i32p(i32* [[A]])
+; MODULE-NEXT: tail call void @use_i32p(i32* [[A]])
+; MODULE-NEXT: ret void
+;
+; CGSCC_OLD-LABEL: define {{[^@]+}}@called_via_pointer_internal_2
+; CGSCC_OLD-SAME: (i32* [[A:%.*]])
+; CGSCC_OLD-NEXT: entry:
+; CGSCC_OLD-NEXT: tail call void @use_i32p(i32* [[A]])
+; CGSCC_OLD-NEXT: tail call void @use_i32p(i32* [[A]])
+; CGSCC_OLD-NEXT: ret void
+;
+; CGSCC_NEW-LABEL: define {{[^@]+}}@called_via_pointer_internal_2
+; CGSCC_NEW-SAME: (i32* [[A:%.*]], i32* nocapture nofree readnone [[B:%.*]], i32* nocapture nofree readnone [[C:%.*]], i64 [[D:%.*]], i32** nocapture nofree readnone [[E:%.*]])
+; CGSCC_NEW-NEXT: entry:
+; CGSCC_NEW-NEXT: tail call void @use_i32p(i32* [[A]])
+; CGSCC_NEW-NEXT: tail call void @use_i32p(i32* [[A]])
+; CGSCC_NEW-NEXT: ret void
;
entry:
tail call void @use_i32p(i32* %a)
}
define internal i8*@test_byval2(%struct.X* byval %a) {
-; CHECK-LABEL: define {{[^@]+}}@test_byval2
-; CHECK-SAME: (%struct.X* noalias nocapture nofree nonnull readonly byval align 8 dereferenceable(8) [[A:%.*]])
+; CHECK-LABEL: define {{[^@]+}}@test_byval2()
; CHECK-NEXT: [[G0:%.*]] = getelementptr [[STRUCT_X:%.*]], %struct.X* @S, i32 0, i32 0
; CHECK-NEXT: [[L:%.*]] = load i8*, i8** [[G0]], align 8
; CHECK-NEXT: ret i8* [[L]]
}
define i8* @complicated_args_byval2() {
; CHECK-LABEL: define {{[^@]+}}@complicated_args_byval2()
-; CHECK-NEXT: [[C:%.*]] = call i8* @test_byval2(%struct.X* nofree nonnull readonly align 8 dereferenceable(8) @S)
+; CHECK-NEXT: [[C:%.*]] = call i8* @test_byval2()
; CHECK-NEXT: ret i8* [[C]]
;
%c = call i8* @test_byval2(%struct.X* @S)