From: Johannes Doerfert Date: Sun, 16 Feb 2020 22:45:28 +0000 (-0600) Subject: [Attributor] Generalize `getAssumedConstantInt` interface X-Git-Tag: llvmorg-12-init~14128 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e1eed6c5b9faf89491beaa592180a1c96fe13e0e;p=platform%2Fupstream%2Fllvm.git [Attributor] Generalize `getAssumedConstantInt` interface We are often interested in an assumed constant and sometimes it has to be an integer constant. Before we only looked for the latter, now we can ask for either. --- diff --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp index 7d6ea0f..275068d 100644 --- a/llvm/lib/Transforms/IPO/Attributor.cpp +++ b/llvm/lib/Transforms/IPO/Attributor.cpp @@ -248,9 +248,9 @@ Argument *IRPosition::getAssociatedArgument() const { return nullptr; } -static Optional -getAssumedConstant(Attributor &A, const Value &V, const AbstractAttribute &AA, - bool &UsedAssumedInformation) { +static Optional getAssumedConstant(Attributor &A, const Value &V, + const AbstractAttribute &AA, + bool &UsedAssumedInformation) { const auto &ValueSimplifyAA = A.getAAFor( AA, IRPosition::value(V), /* TrackDependence */ false); Optional SimplifiedV = ValueSimplifyAA.getAssumedSimplifiedValue(A); @@ -264,12 +264,26 @@ getAssumedConstant(Attributor &A, const Value &V, const AbstractAttribute &AA, A.recordDependence(ValueSimplifyAA, AA, DepClassTy::OPTIONAL); return llvm::None; } - ConstantInt *CI = dyn_cast_or_null(SimplifiedV.getValue()); + Constant *CI = dyn_cast_or_null(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 +getAssumedConstantInt(Attributor &A, const Value &V, + const AbstractAttribute &AA, + bool &UsedAssumedInformation) { + Optional C = getAssumedConstant(A, V, AA, UsedAssumedInformation); + if (C.hasValue()) + return dyn_cast_or_null(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. @@ -2919,9 +2933,9 @@ struct AAIsDeadFloating : public AAIsDeadValueImpl { return ChangeStatus::UNCHANGED; bool UsedAssumedInformation = false; - Optional CI = + Optional 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()); @@ -3307,8 +3321,8 @@ identifyAliveSuccessors(Attributor &A, const BranchInst &BI, if (BI.getNumSuccessors() == 1) { AliveSuccessors.push_back(&BI.getSuccessor(0)->front()); } else { - Optional CI = - getAssumedConstant(A, *BI.getCondition(), AA, UsedAssumedInformation); + Optional CI = getAssumedConstantInt( + A, *BI.getCondition(), AA, UsedAssumedInformation); if (!CI.hasValue()) { // No value yet, assume both edges are dead. } else if (CI.getValue()) { @@ -3330,7 +3344,7 @@ identifyAliveSuccessors(Attributor &A, const SwitchInst &SI, SmallVectorImpl &AliveSuccessors) { bool UsedAssumedInformation = false; Optional 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()) { @@ -7220,11 +7234,11 @@ bool Attributor::checkForAllUses( // 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 CI = + Optional 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; } diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-07-02-array-indexing.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-07-02-array-indexing.ll index 717181a..bea9c33 100644 --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-07-02-array-indexing.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-07-02-array-indexing.ll @@ -5,8 +5,7 @@ ; 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:%.*]] @@ -34,7 +33,7 @@ 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) ; [#uses=1] diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/chained.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/chained.ll index f690e77..a6e8c77 100644 --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/chained.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/chained.ll @@ -5,8 +5,7 @@ @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]] @@ -21,7 +20,7 @@ entry: 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: diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/live_called_from_dead_2.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/live_called_from_dead_2.ll index d2ee7af..429a3a7 100644 --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/live_called_from_dead_2.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/live_called_from_dead_2.ll @@ -1,7 +1,7 @@ ; 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 diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/arg-count-mismatch.ll b/llvm/test/Transforms/Attributor/IPConstantProp/arg-count-mismatch.ll index fc2f6e7..64c9fce 100644 --- a/llvm/test/Transforms/Attributor/IPConstantProp/arg-count-mismatch.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/arg-count-mismatch.ll @@ -30,6 +30,8 @@ ; 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:%.*]]) diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/musttail-call.ll b/llvm/test/Transforms/Attributor/IPConstantProp/musttail-call.ll index 19e5293..d5755da 100644 --- a/llvm/test/Transforms/Attributor/IPConstantProp/musttail-call.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/musttail-call.ll @@ -63,7 +63,7 @@ define internal i8* @side_effects(i8 %v) { 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 } @@ -72,7 +72,7 @@ define internal i8* @dont_zap_me(i8 %v) { ; 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 diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/pthreads.ll b/llvm/test/Transforms/Attributor/IPConstantProp/pthreads.ll index 7b5c6fc..12fb123 100644 --- a/llvm/test/Transforms/Attributor/IPConstantProp/pthreads.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/pthreads.ll @@ -29,16 +29,27 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" ; 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 diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/thread_local_acs.ll b/llvm/test/Transforms/Attributor/IPConstantProp/thread_local_acs.ll index 49a3447..3c11e79 100644 --- a/llvm/test/Transforms/Attributor/IPConstantProp/thread_local_acs.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/thread_local_acs.ll @@ -39,7 +39,7 @@ entry: 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: diff --git a/llvm/test/Transforms/Attributor/align.ll b/llvm/test/Transforms/Attributor/align.ll index baa7fe9..7f3abd9 100644 --- a/llvm/test/Transforms/Attributor/align.ll +++ b/llvm/test/Transforms/Attributor/align.ll @@ -1,4 +1,4 @@ -; 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 @@ -138,12 +138,11 @@ define internal i8* @f3(i8* readnone %0) local_unnamed_addr #0 { ; 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]] ; @@ -159,7 +158,7 @@ define internal i8* @f1b(i8* readnone %0) local_unnamed_addr #0 { ; 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]] @@ -172,7 +171,7 @@ define internal i8* @f1b(i8* readnone %0) local_unnamed_addr #0 { ; 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]] @@ -197,19 +196,18 @@ define internal i8* @f1b(i8* readnone %0) local_unnamed_addr #0 { ; 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 @@ -231,16 +229,15 @@ define internal i8* @f2b(i8* readnone %0) local_unnamed_addr #0 { ; 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 diff --git a/llvm/test/Transforms/Attributor/liveness.ll b/llvm/test/Transforms/Attributor/liveness.ll index 936f4cb..c8c18c6 100644 --- a/llvm/test/Transforms/Attributor/liveness.ll +++ b/llvm/test/Transforms/Attributor/liveness.ll @@ -1189,10 +1189,15 @@ define internal void @call_via_pointer_with_dead_args_internal_a(i32* %a, i32* % ; 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 @@ -1203,26 +1208,55 @@ define internal void @call_via_pointer_with_dead_args_internal_b(i32* %a, i32* % ; 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 @@ -1262,12 +1296,26 @@ entry: } ; 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) diff --git a/llvm/test/Transforms/Attributor/value-simplify.ll b/llvm/test/Transforms/Attributor/value-simplify.ll index 265cedc..ae4101c 100644 --- a/llvm/test/Transforms/Attributor/value-simplify.ll +++ b/llvm/test/Transforms/Attributor/value-simplify.ll @@ -256,8 +256,7 @@ define void @complicated_args_byval() { } 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]] @@ -268,7 +267,7 @@ define internal i8*@test_byval2(%struct.X* byval %a) { } 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)