[Attributor] Generalize `getAssumedConstantInt` interface
authorJohannes Doerfert <johannes@jdoerfert.de>
Sun, 16 Feb 2020 22:45:28 +0000 (16:45 -0600)
committerJohannes Doerfert <johannes@jdoerfert.de>
Thu, 20 Feb 2020 04:33:51 +0000 (22:33 -0600)
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.

llvm/lib/Transforms/IPO/Attributor.cpp
llvm/test/Transforms/Attributor/ArgumentPromotion/2008-07-02-array-indexing.ll
llvm/test/Transforms/Attributor/ArgumentPromotion/chained.ll
llvm/test/Transforms/Attributor/ArgumentPromotion/live_called_from_dead_2.ll
llvm/test/Transforms/Attributor/IPConstantProp/arg-count-mismatch.ll
llvm/test/Transforms/Attributor/IPConstantProp/musttail-call.ll
llvm/test/Transforms/Attributor/IPConstantProp/pthreads.ll
llvm/test/Transforms/Attributor/IPConstantProp/thread_local_acs.ll
llvm/test/Transforms/Attributor/align.ll
llvm/test/Transforms/Attributor/liveness.ll
llvm/test/Transforms/Attributor/value-simplify.ll

index 7d6ea0f..275068d 100644 (file)
@@ -248,9 +248,9 @@ Argument *IRPosition::getAssociatedArgument() const {
   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);
@@ -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<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.
@@ -2919,9 +2933,9 @@ struct AAIsDeadFloating : public AAIsDeadValueImpl {
       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());
@@ -3307,8 +3321,8 @@ identifyAliveSuccessors(Attributor &A, const BranchInst &BI,
   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()) {
@@ -3330,7 +3344,7 @@ identifyAliveSuccessors(Attributor &A, const SwitchInst &SI,
                         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()) {
@@ -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<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;
   }
 
index 717181a..bea9c33 100644 (file)
@@ -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)             ; <i32> [#uses=1]
index f690e77..a6e8c77 100644 (file)
@@ -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:
index d2ee7af..429a3a7 100644 (file)
@@ -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
index fc2f6e7..64c9fce 100644 (file)
@@ -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:%.*]])
index 19e5293..d5755da 100644 (file)
@@ -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
index 7b5c6fc..12fb123 100644 (file)
@@ -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
index 49a3447..3c11e79 100644 (file)
@@ -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:
index baa7fe9..7f3abd9 100644 (file)
@@ -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
index 936f4cb..c8c18c6 100644 (file)
@@ -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)
index 265cedc..ae4101c 100644 (file)
@@ -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)