[llvm] 1221526 - [Attributor][FIX] Check AA preconditions

Johannes Doerfert via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 29 12:32:57 PDT 2023


Author: Johannes Doerfert
Date: 2023-06-29T12:32:45-07:00
New Revision: 1221526681b73c3e99c6e41b5b1cb99ce4b52c69

URL: https://github.com/llvm/llvm-project/commit/1221526681b73c3e99c6e41b5b1cb99ce4b52c69
DIFF: https://github.com/llvm/llvm-project/commit/1221526681b73c3e99c6e41b5b1cb99ce4b52c69.diff

LOG: [Attributor][FIX] Check AA preconditions

AAs often have preconditions, e.g., that the associated type is a
pointer type. If these do not hold, we do not need to bother creating
the AA. Best case, we invalidate it right away, worst case, we crash or
do something wrong (as happend in the issues below).

Fixes: https://github.com/llvm/llvm-project/issues/63553
Fixes: https://github.com/llvm/llvm-project/issues/63597

Added: 
    

Modified: 
    llvm/include/llvm/Transforms/IPO/Attributor.h
    llvm/test/Transforms/Attributor/align.ll
    llvm/test/Transforms/Attributor/liveness.ll

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Transforms/IPO/Attributor.h b/llvm/include/llvm/Transforms/IPO/Attributor.h
index 12784b87a7524..7fbf2de042d81 100644
--- a/llvm/include/llvm/Transforms/IPO/Attributor.h
+++ b/llvm/include/llvm/Transforms/IPO/Attributor.h
@@ -730,6 +730,17 @@ struct IRPosition {
     }
   }
 
+  /// Return true if this is a function or call site position.
+  bool isFunctionScope() const {
+    switch (getPositionKind()) {
+    case IRPosition::IRP_CALL_SITE:
+    case IRPosition::IRP_FUNCTION:
+      return true;
+    default:
+      return false;
+    };
+  }
+
   /// Return the Function surrounding the anchor value.
   Function *getAnchorScope() const {
     Value &V = getAnchorValue();
@@ -3462,6 +3473,14 @@ struct AANoSync
                          StateWrapper<BooleanState, AbstractAttribute>> {
   AANoSync(const IRPosition &IRP, Attributor &A) : IRAttribute(IRP) {}
 
+  /// See AbstractAttribute::isValidIRPositionForInit
+  static bool isValidIRPositionForInit(Attributor &A, const IRPosition &IRP) {
+    if (!IRP.isFunctionScope() &&
+        !IRP.getAssociatedType()->isPtrOrPtrVectorTy())
+      return false;
+    return IRAttribute::isValidIRPositionForInit(A, IRP);
+  }
+
   /// Returns true if "nosync" is assumed.
   bool isAssumedNoSync() const { return getAssumed(); }
 
@@ -3539,6 +3558,13 @@ struct AANonNull
                          StateWrapper<BooleanState, AbstractAttribute>> {
   AANonNull(const IRPosition &IRP, Attributor &A) : IRAttribute(IRP) {}
 
+  /// See AbstractAttribute::isValidIRPositionForInit
+  static bool isValidIRPositionForInit(Attributor &A, const IRPosition &IRP) {
+    if (!IRP.getAssociatedType()->isPtrOrPtrVectorTy())
+      return false;
+    return IRAttribute::isValidIRPositionForInit(A, IRP);
+  }
+
   /// Return true if we assume that the underlying value is nonnull.
   bool isAssumedNonNull() const { return getAssumed(); }
 
@@ -3727,6 +3753,13 @@ struct AANoAlias
                          StateWrapper<BooleanState, AbstractAttribute>> {
   AANoAlias(const IRPosition &IRP, Attributor &A) : IRAttribute(IRP) {}
 
+  /// See AbstractAttribute::isValidIRPositionForInit
+  static bool isValidIRPositionForInit(Attributor &A, const IRPosition &IRP) {
+    if (!IRP.getAssociatedType()->isPtrOrPtrVectorTy())
+      return false;
+    return IRAttribute::isValidIRPositionForInit(A, IRP);
+  }
+
   static bool isImpliedByIR(Attributor &A, const IRPosition &IRP,
                             ArrayRef<Attribute::AttrKind> AttrKinds,
                             bool IgnoreSubsumingPositions = false) {
@@ -3773,6 +3806,14 @@ struct AANoFree
                          StateWrapper<BooleanState, AbstractAttribute>> {
   AANoFree(const IRPosition &IRP, Attributor &A) : IRAttribute(IRP) {}
 
+  /// See AbstractAttribute::isValidIRPositionForInit
+  static bool isValidIRPositionForInit(Attributor &A, const IRPosition &IRP) {
+    if (!IRP.isFunctionScope() &&
+        !IRP.getAssociatedType()->isPtrOrPtrVectorTy())
+      return false;
+    return IRAttribute::isValidIRPositionForInit(A, IRP);
+  }
+
   /// Return true if "nofree" is assumed.
   bool isAssumedNoFree() const { return getAssumed(); }
 
@@ -4068,6 +4109,13 @@ struct AADereferenceable
                          StateWrapper<DerefState, AbstractAttribute>> {
   AADereferenceable(const IRPosition &IRP, Attributor &A) : IRAttribute(IRP) {}
 
+  /// See AbstractAttribute::isValidIRPositionForInit
+  static bool isValidIRPositionForInit(Attributor &A, const IRPosition &IRP) {
+    if (!IRP.getAssociatedType()->isPtrOrPtrVectorTy())
+      return false;
+    return IRAttribute::isValidIRPositionForInit(A, IRP);
+  }
+
   /// Return true if we assume that the underlying value is nonnull.
   bool isAssumedNonNull() const {
     return NonNullAA && NonNullAA->isAssumedNonNull();
@@ -4124,6 +4172,13 @@ struct AAAlign : public IRAttribute<
                      StateWrapper<AAAlignmentStateType, AbstractAttribute>> {
   AAAlign(const IRPosition &IRP, Attributor &A) : IRAttribute(IRP) {}
 
+  /// See AbstractAttribute::isValidIRPositionForInit
+  static bool isValidIRPositionForInit(Attributor &A, const IRPosition &IRP) {
+    if (!IRP.getAssociatedType()->isPtrOrPtrVectorTy())
+      return false;
+    return IRAttribute::isValidIRPositionForInit(A, IRP);
+  }
+
   /// Return assumed alignment.
   Align getAssumedAlign() const { return Align(getAssumed()); }
 
@@ -4195,6 +4250,13 @@ struct AANoCapture
           StateWrapper<BitIntegerState<uint16_t, 7, 0>, AbstractAttribute>> {
   AANoCapture(const IRPosition &IRP, Attributor &A) : IRAttribute(IRP) {}
 
+  /// See AbstractAttribute::isValidIRPositionForInit
+  static bool isValidIRPositionForInit(Attributor &A, const IRPosition &IRP) {
+    if (!IRP.getAssociatedType()->isPtrOrPtrVectorTy())
+      return false;
+    return IRAttribute::isValidIRPositionForInit(A, IRP);
+  }
+
   /// State encoding bits. A set bit in the state means the property holds.
   /// NO_CAPTURE is the best possible state, 0 the worst possible state.
   enum {
@@ -4406,6 +4468,13 @@ struct AAPrivatizablePtr
   using Base = StateWrapper<BooleanState, AbstractAttribute>;
   AAPrivatizablePtr(const IRPosition &IRP, Attributor &A) : Base(IRP) {}
 
+  /// See AbstractAttribute::isValidIRPositionForInit
+  static bool isValidIRPositionForInit(Attributor &A, const IRPosition &IRP) {
+    if (!IRP.getAssociatedType()->isPtrOrPtrVectorTy())
+      return false;
+    return AbstractAttribute::isValidIRPositionForInit(A, IRP);
+  }
+
   /// Returns true if pointer privatization is assumed to be possible.
   bool isAssumedPrivatizablePtr() const { return getAssumed(); }
 
@@ -4445,6 +4514,14 @@ struct AAMemoryBehavior
           StateWrapper<BitIntegerState<uint8_t, 3>, AbstractAttribute>> {
   AAMemoryBehavior(const IRPosition &IRP, Attributor &A) : IRAttribute(IRP) {}
 
+  /// See AbstractAttribute::isValidIRPositionForInit
+  static bool isValidIRPositionForInit(Attributor &A, const IRPosition &IRP) {
+    if (!IRP.isFunctionScope() &&
+        !IRP.getAssociatedType()->isPtrOrPtrVectorTy())
+      return false;
+    return IRAttribute::isValidIRPositionForInit(A, IRP);
+  }
+
   /// State encoding bits. A set bit in the state means the property holds.
   /// BEST_STATE is the best possible state, 0 the worst possible state.
   enum {
@@ -4510,6 +4587,14 @@ struct AAMemoryLocation
 
   AAMemoryLocation(const IRPosition &IRP, Attributor &A) : IRAttribute(IRP) {}
 
+  /// See AbstractAttribute::isValidIRPositionForInit
+  static bool isValidIRPositionForInit(Attributor &A, const IRPosition &IRP) {
+    if (!IRP.isFunctionScope() &&
+        !IRP.getAssociatedType()->isPtrOrPtrVectorTy())
+      return false;
+    return IRAttribute::isValidIRPositionForInit(A, IRP);
+  }
+
   /// Encoding of 
diff erent locations that could be accessed by a memory
   /// access.
   enum {
@@ -4677,6 +4762,13 @@ struct AAValueConstantRange
   AAValueConstantRange(const IRPosition &IRP, Attributor &A)
       : Base(IRP, IRP.getAssociatedType()->getIntegerBitWidth()) {}
 
+  /// See AbstractAttribute::isValidIRPositionForInit
+  static bool isValidIRPositionForInit(Attributor &A, const IRPosition &IRP) {
+    if (!IRP.getAssociatedType()->isIntegerTy())
+      return false;
+    return AbstractAttribute::isValidIRPositionForInit(A, IRP);
+  }
+
   /// See AbstractAttribute::getState(...).
   IntegerRangeState &getState() override { return *this; }
   const IntegerRangeState &getState() const override { return *this; }
@@ -4939,6 +5031,13 @@ struct AAPotentialConstantValues
   using Base = StateWrapper<PotentialConstantIntValuesState, AbstractAttribute>;
   AAPotentialConstantValues(const IRPosition &IRP, Attributor &A) : Base(IRP) {}
 
+  /// See AbstractAttribute::isValidIRPositionForInit
+  static bool isValidIRPositionForInit(Attributor &A, const IRPosition &IRP) {
+    if (!IRP.getAssociatedType()->isIntegerTy())
+      return false;
+    return AbstractAttribute::isValidIRPositionForInit(A, IRP);
+  }
+
   /// See AbstractAttribute::getState(...).
   PotentialConstantIntValuesState &getState() override { return *this; }
   const PotentialConstantIntValuesState &getState() const override {
@@ -5069,6 +5168,19 @@ struct AANoFPClass
 
   AANoFPClass(const IRPosition &IRP, Attributor &A) : IRAttribute(IRP) {}
 
+  /// See AbstractAttribute::isValidIRPositionForInit
+  static bool isValidIRPositionForInit(Attributor &A, const IRPosition &IRP) {
+    Type *Ty = IRP.getAssociatedType();
+    do {
+      if (Ty->isFPOrFPVectorTy())
+        return IRAttribute::isValidIRPositionForInit(A, IRP);
+      if (!Ty->isArrayTy())
+        break;
+      Ty = Ty->getArrayElementType();
+    } while (true);
+    return false;
+  }
+
   /// Return true if we assume that the underlying value is nofpclass.
   FPClassTest getAssumedNoFPClass() const {
     return static_cast<FPClassTest>(getAssumed());
@@ -5406,6 +5518,13 @@ struct AANonConvergent : public StateWrapper<BooleanState, AbstractAttribute> {
 struct AAPointerInfo : public AbstractAttribute {
   AAPointerInfo(const IRPosition &IRP) : AbstractAttribute(IRP) {}
 
+  /// See AbstractAttribute::isValidIRPositionForInit
+  static bool isValidIRPositionForInit(Attributor &A, const IRPosition &IRP) {
+    if (!IRP.getAssociatedType()->isPtrOrPtrVectorTy())
+      return false;
+    return AbstractAttribute::isValidIRPositionForInit(A, IRP);
+  }
+
   enum AccessKind {
     // First two bits to distinguish may and must accesses.
     AK_MUST = 1 << 0,
@@ -5828,6 +5947,13 @@ struct AAAssumptionInfo
 struct AAUnderlyingObjects : AbstractAttribute {
   AAUnderlyingObjects(const IRPosition &IRP) : AbstractAttribute(IRP) {}
 
+  /// See AbstractAttribute::isValidIRPositionForInit
+  static bool isValidIRPositionForInit(Attributor &A, const IRPosition &IRP) {
+    if (!IRP.getAssociatedType()->isPtrOrPtrVectorTy())
+      return false;
+    return AbstractAttribute::isValidIRPositionForInit(A, IRP);
+  }
+
   /// Create an abstract attribute biew for the position \p IRP.
   static AAUnderlyingObjects &createForPosition(const IRPosition &IRP,
                                                 Attributor &A);

diff  --git a/llvm/test/Transforms/Attributor/align.ll b/llvm/test/Transforms/Attributor/align.ll
index 74eb3619e20bc..54338413fb15a 100644
--- a/llvm/test/Transforms/Attributor/align.ll
+++ b/llvm/test/Transforms/Attributor/align.ll
@@ -1089,6 +1089,20 @@ define ptr @aligned_8_return_caller(ptr align(16) %a, i1 %c1, i1 %c2) {
   ret ptr %r
 }
 
+define i32 @implicit_cast_caller(ptr %ptr) {
+; CHECK-LABEL: define {{[^@]+}}@implicit_cast_caller
+; CHECK-SAME: (ptr [[PTR:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call i32 @implicit_cast_callee(ptr [[PTR]])
+; CHECK-NEXT:    ret i32 0
+;
+entry:
+  %call = tail call i32 @implicit_cast_callee(ptr %ptr)
+  ret i32 0
+}
+
+declare void @implicit_cast_callee(i64)
+
 attributes #0 = { nounwind uwtable noinline }
 attributes #1 = { uwtable noinline }
 attributes #2 = { null_pointer_is_valid }

diff  --git a/llvm/test/Transforms/Attributor/liveness.ll b/llvm/test/Transforms/Attributor/liveness.ll
index 955b328067f63..27f2d0e424905 100644
--- a/llvm/test/Transforms/Attributor/liveness.ll
+++ b/llvm/test/Transforms/Attributor/liveness.ll
@@ -1,10 +1,10 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
-; RUN: opt -opaque-pointers=0 -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal  -attributor-annotate-decl-cs  -S < %s | FileCheck %s --check-prefixes=CHECK,TUNIT
-; RUN: opt -opaque-pointers=0 -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal  -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC
+; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal  -attributor-annotate-decl-cs  -S < %s | FileCheck %s --check-prefixes=CHECK,TUNIT
+; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal  -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC
 
-; NOT_CGSCC___: @dead_with_blockaddress_users.l = constant [2 x i8*] [i8* inttoptr (i32 1 to i8*), i8* inttoptr (i32 1 to i8*)]
-; IS__CGSCC___: @dead_with_blockaddress_users.l = constant [2 x i8*] [i8* blockaddress(@dead_with_blockaddress_users, %lab0), i8* blockaddress(@dead_with_blockaddress_users, %end)]
- at dead_with_blockaddress_users.l = constant [2 x i8*] [i8* blockaddress(@dead_with_blockaddress_users, %lab0), i8* blockaddress(@dead_with_blockaddress_users, %end)]
+; NOT_CGSCC___: @dead_with_blockaddress_users.l = constant [2 x ptr] [ptr inttoptr (i32 1 to ptr), ptr inttoptr (i32 1 to ptr)]
+; IS__CGSCC___: @dead_with_blockaddress_users.l = constant [2 x ptr] [ptr blockaddress(@dead_with_blockaddress_users, %lab0), ptr blockaddress(@dead_with_blockaddress_users, %end)]
+ at dead_with_blockaddress_users.l = constant [2 x ptr] [ptr blockaddress(@dead_with_blockaddress_users, %lab0), ptr blockaddress(@dead_with_blockaddress_users, %end)]
 
 declare void @no_return_call() nofree noreturn nounwind nosync
 
@@ -24,16 +24,16 @@ declare i32 @bar() nosync readnone
 ; and nothing should be deduced for it.
 
 ;.
-; TUNIT: @[[DEAD_WITH_BLOCKADDRESS_USERS_L:[a-zA-Z0-9_$"\\.-]+]] = constant [2 x i8*] [i8* inttoptr (i32 1 to i8*), i8* inttoptr (i32 1 to i8*)]
+; TUNIT: @[[DEAD_WITH_BLOCKADDRESS_USERS_L:[a-zA-Z0-9_$"\\.-]+]] = constant [2 x ptr] [ptr inttoptr (i32 1 to ptr), ptr inttoptr (i32 1 to ptr)]
 ; TUNIT: @[[A1:[a-zA-Z0-9_$"\\.-]+]] = common global i8 0, align 8
 ; TUNIT: @[[A2:[a-zA-Z0-9_$"\\.-]+]] = common global i8 0, align 16
-; TUNIT: @[[E:[a-zA-Z0-9_$"\\.-]+]] = global %struct.a* null
+; TUNIT: @[[E:[a-zA-Z0-9_$"\\.-]+]] = global ptr null
 ; TUNIT: @[[P:[a-zA-Z0-9_$"\\.-]+]] = global i8 0
 ;.
-; CGSCC: @[[DEAD_WITH_BLOCKADDRESS_USERS_L:[a-zA-Z0-9_$"\\.-]+]] = constant [2 x i8*] [i8* blockaddress(@dead_with_blockaddress_users, [[LAB0:%.*]]), i8* blockaddress(@dead_with_blockaddress_users, [[END:%.*]])]
+; CGSCC: @[[DEAD_WITH_BLOCKADDRESS_USERS_L:[a-zA-Z0-9_$"\\.-]+]] = constant [2 x ptr] [ptr blockaddress(@dead_with_blockaddress_users, [[LAB0:%.*]]), ptr blockaddress(@dead_with_blockaddress_users, [[END:%.*]])]
 ; CGSCC: @[[A1:[a-zA-Z0-9_$"\\.-]+]] = common global i8 0, align 8
 ; CGSCC: @[[A2:[a-zA-Z0-9_$"\\.-]+]] = common global i8 0, align 16
-; CGSCC: @[[E:[a-zA-Z0-9_$"\\.-]+]] = global %struct.a* null
+; CGSCC: @[[E:[a-zA-Z0-9_$"\\.-]+]] = global ptr null
 ; CGSCC: @[[P:[a-zA-Z0-9_$"\\.-]+]] = global i8 0
 ;.
 define internal i32 @dead_internal_func(i32 %0) {
@@ -67,38 +67,38 @@ define internal i32 @dead_internal_func(i32 %0) {
   br i1 %10, label %3, label %5
 }
 
-define i32 @volatile_load(i32*) norecurse nounwind uwtable {
+define i32 @volatile_load(ptr) norecurse nounwind uwtable {
 ; TUNIT: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) uwtable
 ; TUNIT-LABEL: define {{[^@]+}}@volatile_load
-; TUNIT-SAME: (i32* nofree noundef align 4 [[TMP0:%.*]]) #[[ATTR6:[0-9]+]] {
-; TUNIT-NEXT:    [[TMP2:%.*]] = load volatile i32, i32* [[TMP0]], align 4
+; TUNIT-SAME: (ptr nofree noundef align 4 [[TMP0:%.*]]) #[[ATTR6:[0-9]+]] {
+; TUNIT-NEXT:    [[TMP2:%.*]] = load volatile i32, ptr [[TMP0]], align 4
 ; TUNIT-NEXT:    ret i32 [[TMP2]]
 ;
 ; CGSCC: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) uwtable
 ; CGSCC-LABEL: define {{[^@]+}}@volatile_load
-; CGSCC-SAME: (i32* nofree noundef align 4 [[TMP0:%.*]]) #[[ATTR7:[0-9]+]] {
-; CGSCC-NEXT:    [[TMP2:%.*]] = load volatile i32, i32* [[TMP0]], align 4
+; CGSCC-SAME: (ptr nofree noundef align 4 [[TMP0:%.*]]) #[[ATTR7:[0-9]+]] {
+; CGSCC-NEXT:    [[TMP2:%.*]] = load volatile i32, ptr [[TMP0]], align 4
 ; CGSCC-NEXT:    ret i32 [[TMP2]]
 ;
-  %2 = load volatile i32, i32* %0, align 4
+  %2 = load volatile i32, ptr %0, align 4
   ret i32 %2
 }
 
-define internal i32 @internal_load(i32*) norecurse nounwind uwtable {
+define internal i32 @internal_load(ptr) norecurse nounwind uwtable {
 ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) uwtable
 ; CGSCC-LABEL: define {{[^@]+}}@internal_load
 ; CGSCC-SAME: () #[[ATTR8:[0-9]+]] {
 ; CGSCC-NEXT:    ret i32 undef
 ;
-  %2 = load i32, i32* %0, align 4
+  %2 = load i32, ptr %0, align 4
   ret i32 %2
 }
 ; TEST 1: Only first block is live.
 
-define i32 @first_block_no_return(i32 %a, i32* nonnull %ptr1, i32* %ptr2) #0 {
+define i32 @first_block_no_return(i32 %a, ptr nonnull %ptr1, ptr %ptr2) #0 {
 ; CHECK: Function Attrs: nofree noreturn nosync nounwind
 ; CHECK-LABEL: define {{[^@]+}}@first_block_no_return
-; CHECK-SAME: (i32 [[A:%.*]], i32* nocapture nofree nonnull readnone [[PTR1:%.*]], i32* nocapture nofree readnone [[PTR2:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-SAME: (i32 [[A:%.*]], ptr nocapture nofree nonnull readnone [[PTR1:%.*]], ptr nocapture nofree readnone [[PTR2:%.*]]) #[[ATTR0:[0-9]+]] {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    call void @no_return_call() #[[ATTR3:[0-9]+]]
 ; CHECK-NEXT:    unreachable
@@ -110,15 +110,15 @@ define i32 @first_block_no_return(i32 %a, i32* nonnull %ptr1, i32* %ptr2) #0 {
 ; CHECK-NEXT:    unreachable
 ;
 entry:
-  call i32 @internal_load(i32* %ptr1)
+  call i32 @internal_load(ptr %ptr1)
   call void @no_return_call()
   call i32 @dead_internal_func(i32 10)
   %cmp = icmp eq i32 %a, 0
   br i1 %cmp, label %cond.true, label %cond.false
 
 cond.true:                                        ; preds = %entry
-  call i32 @internal_load(i32* %ptr2)
-  %load = call i32 @volatile_load(i32* %ptr1)
+  call i32 @internal_load(ptr %ptr2)
+  %load = call i32 @volatile_load(ptr %ptr1)
   call void @normal_call()
   %call = call i32 @foo()
   br label %cond.end
@@ -138,9 +138,9 @@ cond.end:                                         ; preds = %cond.false, %cond.t
 ; This is just an example. For example we can put a sync call in a
 ; dead block and check if it is deduced.
 
-define i32 @dead_block_present(i32 %a, i32* %ptr1) #0 {
+define i32 @dead_block_present(i32 %a, ptr %ptr1) #0 {
 ; CHECK-LABEL: define {{[^@]+}}@dead_block_present
-; CHECK-SAME: (i32 [[A:%.*]], i32* nofree [[PTR1:%.*]]) {
+; CHECK-SAME: (i32 [[A:%.*]], ptr nofree [[PTR1:%.*]]) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[A]], 0
 ; CHECK-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
@@ -160,7 +160,7 @@ entry:
 
 cond.true:                                        ; preds = %entry
   call void @no_return_call()
-  %call = call i32 @volatile_load(i32* %ptr1)
+  %call = call i32 @volatile_load(ptr %ptr1)
   br label %cond.end
 
 cond.false:                                       ; preds = %entry
@@ -254,9 +254,9 @@ cond.end:                                         ; preds = %cond.false, %cond.t
 
 ; TEST 5.1 noreturn invoke instruction with a unreachable normal successor block.
 
-define i32 @invoke_noreturn(i32 %a) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+define i32 @invoke_noreturn(i32 %a) personality ptr @__gxx_personality_v0 {
 ; CHECK-LABEL: define {{[^@]+}}@invoke_noreturn
-; CHECK-SAME: (i32 [[A:%.*]]) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+; CHECK-SAME: (i32 [[A:%.*]]) personality ptr @__gxx_personality_v0 {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[A]], 0
 ; CHECK-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
@@ -273,8 +273,8 @@ define i32 @invoke_noreturn(i32 %a) personality i8* bitcast (i32 (...)* @__gxx_p
 ; CHECK:       continue:
 ; CHECK-NEXT:    unreachable
 ; CHECK:       cleanup:
-; CHECK-NEXT:    [[RES:%.*]] = landingpad { i8*, i32 }
-; CHECK-NEXT:    catch i8* null
+; CHECK-NEXT:    [[RES:%.*]] = landingpad { ptr, i32 }
+; CHECK-NEXT:    catch ptr null
 ; CHECK-NEXT:    ret i32 0
 ;
 entry:
@@ -299,17 +299,17 @@ continue:
   br label %cond.end
 
 cleanup:
-  %res = landingpad { i8*, i32 }
-  catch i8* null
+  %res = landingpad { ptr, i32 }
+  catch ptr null
   ret i32 0
 }
 
 ; TEST 5.2 noreturn invoke instruction replaced by a call and an unreachable instruction
 ; put after it.
 
-define i32 @invoke_noreturn_nounwind(i32 %a) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+define i32 @invoke_noreturn_nounwind(i32 %a) personality ptr @__gxx_personality_v0 {
 ; CHECK-LABEL: define {{[^@]+}}@invoke_noreturn_nounwind
-; CHECK-SAME: (i32 [[A:%.*]]) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+; CHECK-SAME: (i32 [[A:%.*]]) personality ptr @__gxx_personality_v0 {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[A]], 0
 ; CHECK-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
@@ -351,15 +351,15 @@ continue:
   br label %cond.end
 
 cleanup:
-  %res = landingpad { i8*, i32 }
-  catch i8* null
+  %res = landingpad { ptr, i32 }
+  catch ptr null
   ret i32 0
 }
 
 ; TEST 5.3 unounwind invoke instruction replaced by a call and a branch instruction put after it.
-define i32 @invoke_nounwind(i32 %a) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+define i32 @invoke_nounwind(i32 %a) personality ptr @__gxx_personality_v0 {
 ; CHECK-LABEL: define {{[^@]+}}@invoke_nounwind
-; CHECK-SAME: (i32 [[A:%.*]]) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+; CHECK-SAME: (i32 [[A:%.*]]) personality ptr @__gxx_personality_v0 {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[A]], 0
 ; CHECK-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
@@ -401,15 +401,15 @@ continue:
   br label %cond.end
 
 cleanup:
-  %res = landingpad { i8*, i32 }
-  catch i8* null
+  %res = landingpad { ptr, i32 }
+  catch ptr null
   ret i32 0
 }
 
 ; TEST 5.4 unounwind invoke instruction replaced by a call and a branch instruction put after it.
-define i32 @invoke_nounwind_phi(i32 %a) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+define i32 @invoke_nounwind_phi(i32 %a) personality ptr @__gxx_personality_v0 {
 ; CHECK-LABEL: define {{[^@]+}}@invoke_nounwind_phi
-; CHECK-SAME: (i32 [[A:%.*]]) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+; CHECK-SAME: (i32 [[A:%.*]]) personality ptr @__gxx_personality_v0 {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[A]], 0
 ; CHECK-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
@@ -446,14 +446,14 @@ continue:
   ret i32 %p
 
 cleanup:
-  %res = landingpad { i8*, i32 } catch i8* null
+  %res = landingpad { ptr, i32 } catch ptr null
   ret i32 0
 }
 
 ; TEST 5.5 unounwind invoke instruction replaced by a call and a branch instruction put after it.
-define i32 @invoke_nounwind_phi_dom(i32 %a) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+define i32 @invoke_nounwind_phi_dom(i32 %a) personality ptr @__gxx_personality_v0 {
 ; CHECK-LABEL: define {{[^@]+}}@invoke_nounwind_phi_dom
-; CHECK-SAME: (i32 [[A:%.*]]) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+; CHECK-SAME: (i32 [[A:%.*]]) personality ptr @__gxx_personality_v0 {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[A]], 0
 ; CHECK-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
@@ -490,36 +490,36 @@ continue:
   ret i32 %p
 
 cleanup:
-  %res = landingpad { i8*, i32 } catch i8* null
+  %res = landingpad { ptr, i32 } catch ptr null
   ret i32 0
 }
 
 ; TEST 6: Undefined behvior, taken from LangRef.
 ; FIXME: Should be able to detect undefined behavior.
 
-define void @ub(i32* %0) {
+define void @ub(ptr %0) {
 ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
 ; TUNIT-LABEL: define {{[^@]+}}@ub
-; TUNIT-SAME: (i32* nocapture nofree writeonly [[TMP0:%.*]]) #[[ATTR7:[0-9]+]] {
+; TUNIT-SAME: (ptr nocapture nofree writeonly [[TMP0:%.*]]) #[[ATTR7:[0-9]+]] {
 ; TUNIT-NEXT:    [[POISON:%.*]] = sub nuw i32 0, 1
 ; TUNIT-NEXT:    [[STILL_POISON:%.*]] = and i32 [[POISON]], 0
-; TUNIT-NEXT:    [[POISON_YET_AGAIN:%.*]] = getelementptr i32, i32* [[TMP0]], i32 [[STILL_POISON]]
-; TUNIT-NEXT:    store i32 0, i32* [[POISON_YET_AGAIN]], align 4
+; TUNIT-NEXT:    [[POISON_YET_AGAIN:%.*]] = getelementptr i32, ptr [[TMP0]], i32 [[STILL_POISON]]
+; TUNIT-NEXT:    store i32 0, ptr [[POISON_YET_AGAIN]], align 4
 ; TUNIT-NEXT:    ret void
 ;
 ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
 ; CGSCC-LABEL: define {{[^@]+}}@ub
-; CGSCC-SAME: (i32* nocapture nofree writeonly [[TMP0:%.*]]) #[[ATTR9:[0-9]+]] {
+; CGSCC-SAME: (ptr nocapture nofree writeonly [[TMP0:%.*]]) #[[ATTR9:[0-9]+]] {
 ; CGSCC-NEXT:    [[POISON:%.*]] = sub nuw i32 0, 1
 ; CGSCC-NEXT:    [[STILL_POISON:%.*]] = and i32 [[POISON]], 0
-; CGSCC-NEXT:    [[POISON_YET_AGAIN:%.*]] = getelementptr i32, i32* [[TMP0]], i32 [[STILL_POISON]]
-; CGSCC-NEXT:    store i32 0, i32* [[POISON_YET_AGAIN]], align 4
+; CGSCC-NEXT:    [[POISON_YET_AGAIN:%.*]] = getelementptr i32, ptr [[TMP0]], i32 [[STILL_POISON]]
+; CGSCC-NEXT:    store i32 0, ptr [[POISON_YET_AGAIN]], align 4
 ; CGSCC-NEXT:    ret void
 ;
   %poison = sub nuw i32 0, 1           ; Results in a poison value.
   %still_poison = and i32 %poison, 0   ; 0, but also poison.
-  %poison_yet_again = getelementptr i32, i32* %0, i32 %still_poison
-  store i32 0, i32* %poison_yet_again  ; Undefined behavior due to store to poison.
+  %poison_yet_again = getelementptr i32, ptr %0, i32 %still_poison
+  store i32 0, ptr %poison_yet_again  ; Undefined behavior due to store to poison.
   ret void
 }
 
@@ -710,84 +710,84 @@ cond.end:                                               ; preds = %cond.if, %con
 @a1 = common global i8 0, align 8
 @a2 = common global i8 0, align 16
 
-define internal i8* @f1(i8* readnone %0) local_unnamed_addr #0 {
+define internal ptr @f1(ptr readnone %0) local_unnamed_addr #0 {
 ; CGSCC-LABEL: define {{[^@]+}}@f1
-; CGSCC-SAME: (i8* readnone [[TMP0:%.*]]) local_unnamed_addr {
-; CGSCC-NEXT:    [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null
+; CGSCC-SAME: (ptr readnone [[TMP0:%.*]]) local_unnamed_addr {
+; CGSCC-NEXT:    [[TMP2:%.*]] = icmp eq ptr [[TMP0]], null
 ; CGSCC-NEXT:    br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]]
 ; CGSCC:       3:
-; CGSCC-NEXT:    [[TMP4:%.*]] = tail call i8* @f2(i8* nonnull @a1)
+; CGSCC-NEXT:    [[TMP4:%.*]] = tail call ptr @f2(ptr nonnull @a1)
 ; CGSCC-NEXT:    br label [[TMP5]]
 ; CGSCC:       5:
-; CGSCC-NEXT:    [[TMP6:%.*]] = phi i8* [ [[TMP4]], [[TMP3]] ], [ [[TMP0]], [[TMP1:%.*]] ]
-; CGSCC-NEXT:    ret i8* [[TMP6]]
+; CGSCC-NEXT:    [[TMP6:%.*]] = phi ptr [ [[TMP4]], [[TMP3]] ], [ [[TMP0]], [[TMP1:%.*]] ]
+; CGSCC-NEXT:    ret ptr [[TMP6]]
 ;
-  %2 = icmp eq i8* %0, null
+  %2 = icmp eq ptr %0, null
   br i1 %2, label %3, label %5
 
 ; <label>:3:                                      ; preds = %1
-  %4 = tail call i8* @f2(i8* nonnull @a1)
+  %4 = tail call ptr @f2(ptr nonnull @a1)
   br label %5
 
 ; <label>:5:                                      ; preds = %1, %3
-  %6 = phi i8* [ %4, %3 ], [ %0, %1 ]
-  ret i8* %6
+  %6 = phi ptr [ %4, %3 ], [ %0, %1 ]
+  ret ptr %6
 }
 
-define internal i8* @f2(i8* readnone %0) local_unnamed_addr #0 {
+define internal ptr @f2(ptr readnone %0) local_unnamed_addr #0 {
 ; CGSCC-LABEL: define {{[^@]+}}@f2
-; CGSCC-SAME: (i8* readnone [[TMP0:%.*]]) local_unnamed_addr {
-; CGSCC-NEXT:    [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null
+; CGSCC-SAME: (ptr readnone [[TMP0:%.*]]) local_unnamed_addr {
+; CGSCC-NEXT:    [[TMP2:%.*]] = icmp eq ptr [[TMP0]], null
 ; CGSCC-NEXT:    br i1 [[TMP2]], label [[TMP5:%.*]], label [[TMP3:%.*]]
 ; CGSCC:       3:
-; CGSCC-NEXT:    [[TMP4:%.*]] = tail call i8* @f1(i8* nonnull [[TMP0]])
+; CGSCC-NEXT:    [[TMP4:%.*]] = tail call ptr @f1(ptr nonnull [[TMP0]])
 ; CGSCC-NEXT:    br label [[TMP7:%.*]]
 ; CGSCC:       5:
-; CGSCC-NEXT:    [[TMP6:%.*]] = tail call i8* @f3(i8* nonnull @a2)
+; CGSCC-NEXT:    [[TMP6:%.*]] = tail call ptr @f3(ptr nonnull @a2)
 ; CGSCC-NEXT:    br label [[TMP7]]
 ; CGSCC:       7:
-; CGSCC-NEXT:    [[TMP8:%.*]] = phi i8* [ [[TMP4]], [[TMP3]] ], [ [[TMP6]], [[TMP5]] ]
-; CGSCC-NEXT:    ret i8* [[TMP8]]
+; CGSCC-NEXT:    [[TMP8:%.*]] = phi ptr [ [[TMP4]], [[TMP3]] ], [ [[TMP6]], [[TMP5]] ]
+; CGSCC-NEXT:    ret ptr [[TMP8]]
 ;
-  %2 = icmp eq i8* %0, null
+  %2 = icmp eq ptr %0, null
   br i1 %2, label %5, label %3
 
 ; <label>:3:                                      ; preds = %1
 
-  %4 = tail call i8* @f1(i8* nonnull %0)
+  %4 = tail call ptr @f1(ptr nonnull %0)
   br label %7
 
 ; <label>:5:                                      ; preds = %1
-  %6 = tail call i8* @f3(i8* nonnull @a2)
+  %6 = tail call ptr @f3(ptr nonnull @a2)
   br label %7
 
 ; <label>:7:                                      ; preds = %5, %3
-  %8 = phi i8* [ %4, %3 ], [ %6, %5 ]
-  ret i8* %8
+  %8 = phi ptr [ %4, %3 ], [ %6, %5 ]
+  ret ptr %8
 }
 
-define internal i8* @f3(i8* readnone %0) local_unnamed_addr #0 {
+define internal ptr @f3(ptr readnone %0) local_unnamed_addr #0 {
 ; CGSCC-LABEL: define {{[^@]+}}@f3
-; CGSCC-SAME: (i8* readnone [[TMP0:%.*]]) local_unnamed_addr {
-; CGSCC-NEXT:    [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null
+; CGSCC-SAME: (ptr readnone [[TMP0:%.*]]) local_unnamed_addr {
+; CGSCC-NEXT:    [[TMP2:%.*]] = icmp eq ptr [[TMP0]], null
 ; CGSCC-NEXT:    br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]]
 ; CGSCC:       3:
-; CGSCC-NEXT:    [[TMP4:%.*]] = tail call i8* @f1(i8* nonnull @a2)
+; CGSCC-NEXT:    [[TMP4:%.*]] = tail call ptr @f1(ptr nonnull @a2)
 ; CGSCC-NEXT:    br label [[TMP5]]
 ; CGSCC:       5:
-; CGSCC-NEXT:    [[TMP6:%.*]] = phi i8* [ [[TMP4]], [[TMP3]] ], [ @a1, [[TMP1:%.*]] ]
-; CGSCC-NEXT:    ret i8* [[TMP6]]
+; CGSCC-NEXT:    [[TMP6:%.*]] = phi ptr [ [[TMP4]], [[TMP3]] ], [ @a1, [[TMP1:%.*]] ]
+; CGSCC-NEXT:    ret ptr [[TMP6]]
 ;
-  %2 = icmp eq i8* %0, null
+  %2 = icmp eq ptr %0, null
   br i1 %2, label %3, label %5
 
 ; <label>:3:                                      ; preds = %1
-  %4 = tail call i8* @f1(i8* nonnull @a2)
+  %4 = tail call ptr @f1(ptr nonnull @a2)
   br label %5
 
 ; <label>:5:                                      ; preds = %1, %3
-  %6 = phi i8* [ %4, %3 ], [ @a1, %1 ]
-  ret i8* %6
+  %6 = phi ptr [ %4, %3 ], [ @a1, %1 ]
+  ret ptr %6
 }
 
 declare void @sink() nofree nosync nounwind willreturn
@@ -2048,31 +2048,31 @@ define internal void @dead_e2() { ret void }
 ; Verify we actually deduce information for these functions.
 
 declare void @blowup() noreturn
-define void @live_with_dead_entry() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+define void @live_with_dead_entry() personality ptr @__gxx_personality_v0 {
 entry:
   invoke void @blowup() to label %live_with_dead_entry unwind label %lpad
 lpad:
-  %0 = landingpad { i8*, i32 } catch i8* null
+  %0 = landingpad { ptr, i32 } catch ptr null
   br label %live_with_dead_entry
 live_with_dead_entry:
   ret void
 }
 
-define void @live_with_dead_entry_lp() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+define void @live_with_dead_entry_lp() personality ptr @__gxx_personality_v0 {
 ; CHECK: Function Attrs: nounwind
 ; CHECK-LABEL: define {{[^@]+}}@live_with_dead_entry_lp
-; CHECK-SAME: () #[[ATTR2]] personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+; CHECK-SAME: () #[[ATTR2]] personality ptr @__gxx_personality_v0 {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    invoke void @blowup() #[[ATTR4]]
 ; CHECK-NEXT:    to label [[LIVE_WITH_DEAD_ENTRY_DEAD:%.*]] unwind label [[LP1:%.*]]
 ; CHECK:       lp1:
-; CHECK-NEXT:    [[LP:%.*]] = landingpad { i8*, i32 }
-; CHECK-NEXT:    catch i8* null
+; CHECK-NEXT:    [[LP:%.*]] = landingpad { ptr, i32 }
+; CHECK-NEXT:    catch ptr null
 ; CHECK-NEXT:    invoke void @blowup() #[[ATTR4]]
 ; CHECK-NEXT:    to label [[LIVE_WITH_DEAD_ENTRY_DEAD1:%.*]] unwind label [[LP2:%.*]]
 ; CHECK:       lp2:
-; CHECK-NEXT:    [[TMP0:%.*]] = landingpad { i8*, i32 }
-; CHECK-NEXT:    catch i8* null
+; CHECK-NEXT:    [[TMP0:%.*]] = landingpad { ptr, i32 }
+; CHECK-NEXT:    catch ptr null
 ; CHECK-NEXT:    br label [[LIVE_WITH_DEAD_ENTRY:%.*]]
 ; CHECK:       live_with_dead_entry.dead:
 ; CHECK-NEXT:    unreachable
@@ -2084,16 +2084,16 @@ define void @live_with_dead_entry_lp() personality i8* bitcast (i32 (...)* @__gx
 entry:
   invoke void @blowup() to label %live_with_dead_entry unwind label %lp1
 lp1:
-  %lp = landingpad { i8*, i32 } catch i8* null
+  %lp = landingpad { ptr, i32 } catch ptr null
   invoke void @blowup() to label %live_with_dead_entry unwind label %lp2
 lp2:
-  %0 = landingpad { i8*, i32 } catch i8* null
+  %0 = landingpad { ptr, i32 } catch ptr null
   br label %live_with_dead_entry
 live_with_dead_entry:
   ret void
 }
 
-define internal void @useless_arg_sink(i32* %a) {
+define internal void @useless_arg_sink(ptr %a) {
 ; TUNIT: Function Attrs: mustprogress nofree nosync nounwind willreturn
 ; TUNIT-LABEL: define {{[^@]+}}@useless_arg_sink
 ; TUNIT-SAME: () #[[ATTR11]] {
@@ -2110,7 +2110,7 @@ define internal void @useless_arg_sink(i32* %a) {
   ret void
 }
 
-define internal void @useless_arg_almost_sink(i32* %a) {
+define internal void @useless_arg_almost_sink(ptr %a) {
 ; TUNIT: Function Attrs: mustprogress nofree nosync nounwind willreturn
 ; TUNIT-LABEL: define {{[^@]+}}@useless_arg_almost_sink
 ; TUNIT-SAME: () #[[ATTR11]] {
@@ -2123,38 +2123,38 @@ define internal void @useless_arg_almost_sink(i32* %a) {
 ; CGSCC-NEXT:    call void @useless_arg_sink() #[[ATTR2]]
 ; CGSCC-NEXT:    ret void
 ;
-  call void @useless_arg_sink(i32* %a)
+  call void @useless_arg_sink(ptr %a)
   ret void
 }
 
 ; Check we do not annotate the function interface of this weak function.
-define weak_odr void @useless_arg_ext(i32* %a) {
+define weak_odr void @useless_arg_ext(ptr %a) {
 ; CHECK-LABEL: define {{[^@]+}}@useless_arg_ext
-; CHECK-SAME: (i32* [[A:%.*]]) {
+; CHECK-SAME: (ptr [[A:%.*]]) {
 ; CHECK-NEXT:    call void @useless_arg_almost_sink() #[[ATTR2]]
 ; CHECK-NEXT:    ret void
 ;
-  call void @useless_arg_almost_sink(i32* %a)
+  call void @useless_arg_almost_sink(ptr %a)
   ret void
 }
 
-define internal void @useless_arg_ext_int(i32* %a) {
+define internal void @useless_arg_ext_int(ptr %a) {
 ; CHECK-LABEL: define {{[^@]+}}@useless_arg_ext_int
-; CHECK-SAME: (i32* [[A:%.*]]) {
-; CHECK-NEXT:    call void @useless_arg_ext(i32* [[A]])
+; CHECK-SAME: (ptr [[A:%.*]]) {
+; CHECK-NEXT:    call void @useless_arg_ext(ptr [[A]])
 ; CHECK-NEXT:    ret void
 ;
-  call void @useless_arg_ext(i32* %a)
+  call void @useless_arg_ext(ptr %a)
   ret void
 }
 
-define void @useless_arg_ext_int_ext(i32* %a) {
+define void @useless_arg_ext_int_ext(ptr %a) {
 ; CHECK-LABEL: define {{[^@]+}}@useless_arg_ext_int_ext
-; CHECK-SAME: (i32* [[A:%.*]]) {
-; CHECK-NEXT:    call void @useless_arg_ext_int(i32* [[A]])
+; CHECK-SAME: (ptr [[A:%.*]]) {
+; CHECK-NEXT:    call void @useless_arg_ext_int(ptr [[A]])
 ; CHECK-NEXT:    ret void
 ;
-  call void @useless_arg_ext_int(i32* %a)
+  call void @useless_arg_ext_int(ptr %a)
   ret void
 }
 
@@ -2263,128 +2263,128 @@ define i32 @switch_default_dead_caller() {
   ret i32 %call2
 }
 
-define void @call_via_pointer_with_dead_args(i32* %a, i32* %b, void (i32*, i32*, i32*, i64, i32**)* %fp) {
+define void @call_via_pointer_with_dead_args(ptr %a, ptr %b, ptr %fp) {
 ; CHECK-LABEL: define {{[^@]+}}@call_via_pointer_with_dead_args
-; CHECK-SAME: (i32* [[A:%.*]], i32* [[B:%.*]], void (i32*, i32*, i32*, i64, i32**)* nocapture nofree noundef nonnull [[FP:%.*]]) {
-; CHECK-NEXT:    call void [[FP]](i32* [[A]], i32* [[B]], i32* [[A]], i64 -1, i32** null)
+; CHECK-SAME: (ptr [[A:%.*]], ptr [[B:%.*]], ptr nocapture nofree noundef nonnull [[FP:%.*]]) {
+; CHECK-NEXT:    call void [[FP]](ptr [[A]], ptr [[B]], ptr [[A]], i64 -1, ptr null)
 ; CHECK-NEXT:    ret void
 ;
-  call void %fp(i32* %a, i32* %b, i32* %a, i64 -1, i32** null)
+  call void %fp(ptr %a, ptr %b, ptr %a, i64 -1, ptr null)
   ret void
 }
 
-define internal void @call_via_pointer_with_dead_args_internal_a(i32* %a, i32* %b, void (i32*, i32*, i32*, i64, i32**)* %fp) {
+define internal void @call_via_pointer_with_dead_args_internal_a(ptr %a, ptr %b, ptr %fp) {
 ; CHECK-LABEL: define {{[^@]+}}@call_via_pointer_with_dead_args_internal_a
-; CHECK-SAME: (i32* [[A:%.*]], i32* noundef nonnull align 128 dereferenceable(4) [[B:%.*]]) {
-; CHECK-NEXT:    call void @called_via_pointer(i32* [[A]], i32* [[B]], i32* [[A]], i64 -1, i32** null)
+; CHECK-SAME: (ptr [[A:%.*]], ptr noundef nonnull align 128 dereferenceable(4) [[B:%.*]]) {
+; CHECK-NEXT:    call void @called_via_pointer(ptr [[A]], ptr [[B]], ptr [[A]], i64 -1, ptr null)
 ; CHECK-NEXT:    ret void
 ;
-  call void %fp(i32* %a, i32* %b, i32* %a, i64 -1, i32** null)
+  call void %fp(ptr %a, ptr %b, ptr %a, i64 -1, ptr null)
   ret void
 }
-define internal void @call_via_pointer_with_dead_args_internal_b(i32* %a, i32* %b, void (i32*, i32*, i32*, i64, i32**)* %fp) {
+define internal void @call_via_pointer_with_dead_args_internal_b(ptr %a, ptr %b, ptr %fp) {
 ; TUNIT-LABEL: define {{[^@]+}}@call_via_pointer_with_dead_args_internal_b
-; TUNIT-SAME: (i32* [[A:%.*]], i32* noundef nonnull align 128 dereferenceable(4) [[B:%.*]]) {
-; TUNIT-NEXT:    call void @called_via_pointer_internal_2(i32* [[A]], i32* [[B]], i32* [[A]], i64 -1, i32** null)
+; TUNIT-SAME: (ptr [[A:%.*]], ptr noundef nonnull align 128 dereferenceable(4) [[B:%.*]]) {
+; TUNIT-NEXT:    call void @called_via_pointer_internal_2(ptr [[A]], ptr [[B]], ptr [[A]], i64 -1, ptr null)
 ; TUNIT-NEXT:    ret void
 ;
 ; CGSCC-LABEL: define {{[^@]+}}@call_via_pointer_with_dead_args_internal_b
-; CGSCC-SAME: (i32* [[A:%.*]], i32* noundef nonnull align 128 dereferenceable(4) [[B:%.*]]) {
-; CGSCC-NEXT:    call void @called_via_pointer_internal_2(i32* [[A]])
+; CGSCC-SAME: (ptr [[A:%.*]], ptr noundef nonnull align 128 dereferenceable(4) [[B:%.*]]) {
+; CGSCC-NEXT:    call void @called_via_pointer_internal_2(ptr [[A]])
 ; CGSCC-NEXT:    ret void
 ;
-  call void %fp(i32* %a, i32* %b, i32* %a, i64 -1, i32** null)
+  call void %fp(ptr %a, ptr %b, ptr %a, i64 -1, ptr null)
   ret void
 }
-define void @call_via_pointer_with_dead_args_caller(i32* %a, i32* %b) {
+define void @call_via_pointer_with_dead_args_caller(ptr %a, ptr %b) {
 ; TUNIT-LABEL: define {{[^@]+}}@call_via_pointer_with_dead_args_caller
-; TUNIT-SAME: (i32* [[A:%.*]], i32* [[B:%.*]]) {
+; TUNIT-SAME: (ptr [[A:%.*]], ptr [[B:%.*]]) {
 ; TUNIT-NEXT:    [[PTR1:%.*]] = alloca i32, align 128
 ; TUNIT-NEXT:    [[PTR2:%.*]] = alloca i32, align 128
 ; TUNIT-NEXT:    [[PTR3:%.*]] = alloca i32, align 128
 ; TUNIT-NEXT:    [[PTR4:%.*]] = alloca i32, align 128
-; TUNIT-NEXT:    call void @call_via_pointer_with_dead_args(i32* [[A]], i32* noundef nonnull align 128 dereferenceable(4) [[PTR1]], void (i32*, i32*, i32*, i64, i32**)* nocapture nofree noundef @called_via_pointer)
-; TUNIT-NEXT:    call void @call_via_pointer_with_dead_args(i32* [[A]], i32* noundef nonnull align 128 dereferenceable(4) [[PTR2]], void (i32*, i32*, i32*, i64, i32**)* nocapture nofree noundef @called_via_pointer_internal_1)
-; TUNIT-NEXT:    call void @call_via_pointer_with_dead_args_internal_a(i32* [[B]], i32* noundef nonnull align 128 dereferenceable(4) [[PTR3]])
-; TUNIT-NEXT:    call void @call_via_pointer_with_dead_args_internal_b(i32* [[B]], i32* noundef nonnull align 128 dereferenceable(4) [[PTR4]])
+; TUNIT-NEXT:    call void @call_via_pointer_with_dead_args(ptr [[A]], ptr noundef nonnull align 128 dereferenceable(4) [[PTR1]], ptr nocapture nofree noundef @called_via_pointer)
+; TUNIT-NEXT:    call void @call_via_pointer_with_dead_args(ptr [[A]], ptr noundef nonnull align 128 dereferenceable(4) [[PTR2]], ptr nocapture nofree noundef @called_via_pointer_internal_1)
+; TUNIT-NEXT:    call void @call_via_pointer_with_dead_args_internal_a(ptr [[B]], ptr noundef nonnull align 128 dereferenceable(4) [[PTR3]])
+; TUNIT-NEXT:    call void @call_via_pointer_with_dead_args_internal_b(ptr [[B]], ptr noundef nonnull align 128 dereferenceable(4) [[PTR4]])
 ; TUNIT-NEXT:    ret void
 ;
 ; CGSCC-LABEL: define {{[^@]+}}@call_via_pointer_with_dead_args_caller
-; CGSCC-SAME: (i32* [[A:%.*]], i32* [[B:%.*]]) {
+; CGSCC-SAME: (ptr [[A:%.*]], ptr [[B:%.*]]) {
 ; CGSCC-NEXT:    [[PTR1:%.*]] = alloca i32, align 128
 ; CGSCC-NEXT:    [[PTR2:%.*]] = alloca i32, align 128
 ; CGSCC-NEXT:    [[PTR3:%.*]] = alloca i32, align 128
 ; CGSCC-NEXT:    [[PTR4:%.*]] = alloca i32, align 128
-; CGSCC-NEXT:    call void @call_via_pointer_with_dead_args(i32* [[A]], i32* noundef nonnull align 128 dereferenceable(4) [[PTR1]], void (i32*, i32*, i32*, i64, i32**)* nocapture nofree noundef nonnull @called_via_pointer)
-; CGSCC-NEXT:    call void @call_via_pointer_with_dead_args(i32* [[A]], i32* noundef nonnull align 128 dereferenceable(4) [[PTR2]], void (i32*, i32*, i32*, i64, i32**)* nocapture nofree noundef nonnull @called_via_pointer_internal_1)
-; CGSCC-NEXT:    call void @call_via_pointer_with_dead_args_internal_a(i32* [[B]], i32* noundef nonnull align 128 dereferenceable(4) [[PTR3]])
-; CGSCC-NEXT:    call void @call_via_pointer_with_dead_args_internal_b(i32* [[B]], i32* noundef nonnull align 128 dereferenceable(4) [[PTR4]])
+; CGSCC-NEXT:    call void @call_via_pointer_with_dead_args(ptr [[A]], ptr noundef nonnull align 128 dereferenceable(4) [[PTR1]], ptr nocapture nofree noundef nonnull @called_via_pointer)
+; CGSCC-NEXT:    call void @call_via_pointer_with_dead_args(ptr [[A]], ptr noundef nonnull align 128 dereferenceable(4) [[PTR2]], ptr nocapture nofree noundef nonnull @called_via_pointer_internal_1)
+; CGSCC-NEXT:    call void @call_via_pointer_with_dead_args_internal_a(ptr [[B]], ptr noundef nonnull align 128 dereferenceable(4) [[PTR3]])
+; CGSCC-NEXT:    call void @call_via_pointer_with_dead_args_internal_b(ptr [[B]], ptr noundef nonnull align 128 dereferenceable(4) [[PTR4]])
 ; CGSCC-NEXT:    ret void
 ;
   %ptr1 = alloca i32, align 128
   %ptr2 = alloca i32, align 128
   %ptr3 = alloca i32, align 128
   %ptr4 = alloca i32, align 128
-  call void @call_via_pointer_with_dead_args(i32* %a, i32* %ptr1, void (i32*, i32*, i32*, i64, i32**)* @called_via_pointer)
-  call void @call_via_pointer_with_dead_args(i32* %a, i32* %ptr2, void (i32*, i32*, i32*, i64, i32**)* @called_via_pointer_internal_1)
-  call void @call_via_pointer_with_dead_args_internal_a(i32* %b, i32* %ptr3, void (i32*, i32*, i32*, i64, i32**)* @called_via_pointer)
-  call void @call_via_pointer_with_dead_args_internal_b(i32* %b, i32* %ptr4, void (i32*, i32*, i32*, i64, i32**)* @called_via_pointer_internal_2)
+  call void @call_via_pointer_with_dead_args(ptr %a, ptr %ptr1, ptr @called_via_pointer)
+  call void @call_via_pointer_with_dead_args(ptr %a, ptr %ptr2, ptr @called_via_pointer_internal_1)
+  call void @call_via_pointer_with_dead_args_internal_a(ptr %b, ptr %ptr3, ptr @called_via_pointer)
+  call void @call_via_pointer_with_dead_args_internal_b(ptr %b, ptr %ptr4, ptr @called_via_pointer_internal_2)
   ret void
 }
-define void @called_via_pointer(i32* %a, i32* %b, i32* %c, i64 %d, i32** %e) {
+define void @called_via_pointer(ptr %a, ptr %b, ptr %c, i64 %d, ptr %e) {
 ; CHECK-LABEL: define {{[^@]+}}@called_via_pointer
-; CHECK-SAME: (i32* [[A:%.*]], i32* nocapture nofree readnone [[B:%.*]], i32* nocapture nofree readnone [[C:%.*]], i64 [[D:%.*]], i32** nocapture nofree readnone [[E:%.*]]) {
+; CHECK-SAME: (ptr [[A:%.*]], ptr nocapture nofree readnone [[B:%.*]], ptr nocapture nofree readnone [[C:%.*]], i64 [[D:%.*]], ptr 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:    tail call void @use_i32p(ptr [[A]])
+; CHECK-NEXT:    tail call void @use_i32p(ptr [[A]])
 ; CHECK-NEXT:    ret void
 ;
 entry:
-  tail call void @use_i32p(i32* %a)
-  tail call void @use_i32p(i32* %a)
+  tail call void @use_i32p(ptr %a)
+  tail call void @use_i32p(ptr %a)
   ret void
 }
-define internal void @called_via_pointer_internal_1(i32* %a, i32* %b, i32* %c, i64 %d, i32** %e) {
+define internal void @called_via_pointer_internal_1(ptr %a, ptr %b, ptr %c, i64 %d, ptr %e) {
 ; CHECK-LABEL: define {{[^@]+}}@called_via_pointer_internal_1
-; CHECK-SAME: (i32* [[A:%.*]], i32* nocapture nofree readnone [[B:%.*]], i32* nocapture nofree readnone [[C:%.*]], i64 [[D:%.*]], i32** nocapture nofree readnone [[E:%.*]]) {
+; CHECK-SAME: (ptr [[A:%.*]], ptr nocapture nofree readnone [[B:%.*]], ptr nocapture nofree readnone [[C:%.*]], i64 [[D:%.*]], ptr 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:    tail call void @use_i32p(ptr [[A]])
+; CHECK-NEXT:    tail call void @use_i32p(ptr [[A]])
 ; CHECK-NEXT:    ret void
 ;
 entry:
-  tail call void @use_i32p(i32* %a)
-  tail call void @use_i32p(i32* %a)
+  tail call void @use_i32p(ptr %a)
+  tail call void @use_i32p(ptr %a)
   ret void
 }
 ; 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) {
+define internal void @called_via_pointer_internal_2(ptr %a, ptr %b, ptr %c, i64 %d, ptr %e) {
 ; TUNIT-LABEL: define {{[^@]+}}@called_via_pointer_internal_2
-; TUNIT-SAME: (i32* [[A:%.*]], i32* nocapture nofree readnone [[B:%.*]], i32* nocapture nofree readnone [[C:%.*]], i64 [[D:%.*]], i32** nocapture nofree readnone [[E:%.*]]) {
+; TUNIT-SAME: (ptr [[A:%.*]], ptr nocapture nofree readnone [[B:%.*]], ptr nocapture nofree readnone [[C:%.*]], i64 [[D:%.*]], ptr nocapture nofree readnone [[E:%.*]]) {
 ; TUNIT-NEXT:  entry:
-; TUNIT-NEXT:    tail call void @use_i32p(i32* [[A]])
-; TUNIT-NEXT:    tail call void @use_i32p(i32* [[A]])
+; TUNIT-NEXT:    tail call void @use_i32p(ptr [[A]])
+; TUNIT-NEXT:    tail call void @use_i32p(ptr [[A]])
 ; TUNIT-NEXT:    ret void
 ;
 ; CGSCC-LABEL: define {{[^@]+}}@called_via_pointer_internal_2
-; CGSCC-SAME: (i32* [[A:%.*]]) {
+; CGSCC-SAME: (ptr [[A:%.*]]) {
 ; CGSCC-NEXT:  entry:
-; CGSCC-NEXT:    tail call void @use_i32p(i32* [[A]])
-; CGSCC-NEXT:    tail call void @use_i32p(i32* [[A]])
+; CGSCC-NEXT:    tail call void @use_i32p(ptr [[A]])
+; CGSCC-NEXT:    tail call void @use_i32p(ptr [[A]])
 ; CGSCC-NEXT:    ret void
 ;
 entry:
-  tail call void @use_i32p(i32* %a)
-  tail call void @use_i32p(i32* %a)
+  tail call void @use_i32p(ptr %a)
+  tail call void @use_i32p(ptr %a)
   ret void
 }
-declare void @use_i32p(i32*)
+declare void @use_i32p(ptr)
 
 ; Allow blockaddress users
-define internal void @dead_with_blockaddress_users(i32* nocapture %pc) nounwind readonly {
+define internal void @dead_with_blockaddress_users(ptr nocapture %pc) nounwind readonly {
 ; CGSCC: Function Attrs: nounwind memory(read)
 ; CGSCC-LABEL: define {{[^@]+}}@dead_with_blockaddress_users
-; CGSCC-SAME: (i32* nocapture [[PC:%.*]]) #[[ATTR14:[0-9]+]] {
+; CGSCC-SAME: (ptr nocapture [[PC:%.*]]) #[[ATTR14:[0-9]+]] {
 ; CGSCC-NEXT:  entry:
 ; CGSCC-NEXT:    br label [[INDIRECTGOTO:%.*]]
 ; CGSCC:       lab0:
@@ -2394,11 +2394,11 @@ define internal void @dead_with_blockaddress_users(i32* nocapture %pc) nounwind
 ; CGSCC-NEXT:    ret void
 ; CGSCC:       indirectgoto:
 ; CGSCC-NEXT:    [[INDVAR]] = phi i32 [ [[INDVAR_NEXT]], [[LAB0:%.*]] ], [ 0, [[ENTRY:%.*]] ]
-; CGSCC-NEXT:    [[PC_ADDR_0:%.*]] = getelementptr i32, i32* [[PC]], i32 [[INDVAR]]
-; CGSCC-NEXT:    [[TMP1_PN:%.*]] = load i32, i32* [[PC_ADDR_0]], align 4
-; CGSCC-NEXT:    [[INDIRECT_GOTO_DEST_IN:%.*]] = getelementptr inbounds [2 x i8*], [2 x i8*]* @dead_with_blockaddress_users.l, i32 0, i32 [[TMP1_PN]]
-; CGSCC-NEXT:    [[INDIRECT_GOTO_DEST:%.*]] = load i8*, i8** [[INDIRECT_GOTO_DEST_IN]], align 8
-; CGSCC-NEXT:    indirectbr i8* [[INDIRECT_GOTO_DEST]], [label [[LAB0]], label %end]
+; CGSCC-NEXT:    [[PC_ADDR_0:%.*]] = getelementptr i32, ptr [[PC]], i32 [[INDVAR]]
+; CGSCC-NEXT:    [[TMP1_PN:%.*]] = load i32, ptr [[PC_ADDR_0]], align 4
+; CGSCC-NEXT:    [[INDIRECT_GOTO_DEST_IN:%.*]] = getelementptr inbounds [2 x ptr], ptr @dead_with_blockaddress_users.l, i32 0, i32 [[TMP1_PN]]
+; CGSCC-NEXT:    [[INDIRECT_GOTO_DEST:%.*]] = load ptr, ptr [[INDIRECT_GOTO_DEST_IN]], align 8
+; CGSCC-NEXT:    indirectbr ptr [[INDIRECT_GOTO_DEST]], [label [[LAB0]], label %end]
 ;
 entry:
   br label %indirectgoto
@@ -2412,74 +2412,45 @@ end:                                              ; preds = %indirectgoto
 
 indirectgoto:                                     ; preds = %lab0, %entry
   %indvar = phi i32 [ %indvar.next, %lab0 ], [ 0, %entry ] ; <i32> [#uses=2]
-  %pc.addr.0 = getelementptr i32, i32* %pc, i32 %indvar ; <i32*> [#uses=1]
-  %tmp1.pn = load i32, i32* %pc.addr.0                 ; <i32> [#uses=1]
-  %indirect.goto.dest.in = getelementptr inbounds [2 x i8*], [2 x i8*]* @dead_with_blockaddress_users.l, i32 0, i32 %tmp1.pn ; <i8**> [#uses=1]
-  %indirect.goto.dest = load i8*, i8** %indirect.goto.dest.in ; <i8*> [#uses=1]
-  indirectbr i8* %indirect.goto.dest, [label %lab0, label %end]
+  %pc.addr.0 = getelementptr i32, ptr %pc, i32 %indvar ; <ptr> [#uses=1]
+  %tmp1.pn = load i32, ptr %pc.addr.0                 ; <i32> [#uses=1]
+  %indirect.goto.dest.in = getelementptr inbounds [2 x ptr], ptr @dead_with_blockaddress_users.l, i32 0, i32 %tmp1.pn ; <ptr> [#uses=1]
+  %indirect.goto.dest = load ptr, ptr %indirect.goto.dest.in ; <ptr> [#uses=1]
+  indirectbr ptr %indirect.goto.dest, [label %lab0, label %end]
 }
 
 
 ; The code below exposed a bug that caused %call to be replaced with `undef`.
 
-%struct.a = type { %struct.a* }
+%struct.a = type { ptr }
 
- at e = global %struct.a* null
+ at e = global ptr null
 
 define i32 @main() {
-; TUNIT-LABEL: define {{[^@]+}}@main() {
-; TUNIT-NEXT:  entry:
-; TUNIT-NEXT:    br label [[FOR_COND_0:%.*]]
-; TUNIT:       for.cond.0:
-; TUNIT-NEXT:    [[G_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY_0:%.*]] ]
-; TUNIT-NEXT:    [[CMP_0:%.*]] = icmp ult i32 [[G_0]], 100
-; TUNIT-NEXT:    br i1 [[CMP_0]], label [[FOR_BODY_0]], label [[FOR_END_0:%.*]]
-; TUNIT:       for.body.0:
-; TUNIT-NEXT:    [[INC]] = add nuw nsw i32 [[G_0]], 1
-; TUNIT-NEXT:    br label [[FOR_COND_0]]
-; TUNIT:       for.end.0:
-; TUNIT-NEXT:    [[CALL:%.*]] = call i8* @malloc(i64 noundef 8)
-; TUNIT-NEXT:    store i8* [[CALL]], i8** bitcast (%struct.a** @e to i8**), align 8
-; TUNIT-NEXT:    [[B:%.*]] = bitcast i8* [[CALL]] to %struct.a**
-; TUNIT-NEXT:    store %struct.a* null, %struct.a** [[B]], align 8
-; TUNIT-NEXT:    br label [[FOR_COND_1:%.*]]
-; TUNIT:       for.cond.1:
-; TUNIT-NEXT:    [[G_1:%.*]] = phi i32 [ 0, [[FOR_END_0]] ], [ [[INC6:%.*]], [[FOR_BODY_1:%.*]] ]
-; TUNIT-NEXT:    [[CMP_1:%.*]] = icmp ult i32 [[G_1]], 100
-; TUNIT-NEXT:    br i1 [[CMP_1]], label [[FOR_BODY_1]], label [[FOR_END_1:%.*]]
-; TUNIT:       for.body.1:
-; TUNIT-NEXT:    [[INC6]] = add nuw nsw i32 [[G_1]], 1
-; TUNIT-NEXT:    br label [[FOR_COND_1]]
-; TUNIT:       for.end.1:
-; TUNIT-NEXT:    ret i32 0
-;
-; CGSCC-LABEL: define {{[^@]+}}@main() {
-; CGSCC-NEXT:  entry:
-; CGSCC-NEXT:    [[F:%.*]] = alloca i32, align 4
-; CGSCC-NEXT:    br label [[FOR_COND_0:%.*]]
-; CGSCC:       for.cond.0:
-; CGSCC-NEXT:    [[G_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY_0:%.*]] ]
-; CGSCC-NEXT:    [[CMP_0:%.*]] = icmp ult i32 [[G_0]], 100
-; CGSCC-NEXT:    br i1 [[CMP_0]], label [[FOR_BODY_0]], label [[FOR_END_0:%.*]]
-; CGSCC:       for.body.0:
-; CGSCC-NEXT:    [[INC]] = add nuw nsw i32 [[G_0]], 1
-; CGSCC-NEXT:    br label [[FOR_COND_0]]
-; CGSCC:       for.end.0:
-; CGSCC-NEXT:    [[CALL:%.*]] = call i8* @malloc(i64 noundef 8)
-; CGSCC-NEXT:    store i8* [[CALL]], i8** bitcast (%struct.a** @e to i8**), align 8
-; CGSCC-NEXT:    [[B:%.*]] = bitcast i8* [[CALL]] to %struct.a**
-; CGSCC-NEXT:    store %struct.a* null, %struct.a** [[B]], align 8
-; CGSCC-NEXT:    br label [[FOR_COND_1:%.*]]
-; CGSCC:       for.cond.1:
-; CGSCC-NEXT:    [[G_1:%.*]] = phi i32 [ 0, [[FOR_END_0]] ], [ [[INC6:%.*]], [[FOR_BODY_1:%.*]] ]
-; CGSCC-NEXT:    [[CMP_1:%.*]] = icmp ult i32 [[G_1]], 100
-; CGSCC-NEXT:    br i1 [[CMP_1]], label [[FOR_BODY_1]], label [[FOR_END_1:%.*]]
-; CGSCC:       for.body.1:
-; CGSCC-NEXT:    [[CALL4:%.*]] = call i32 (i32*, ...) bitcast (i32 (i32)* @h to i32 (i32*, ...)*)(i32* nonnull [[F]]) #[[ATTR2]]
-; CGSCC-NEXT:    [[INC6]] = add nuw nsw i32 [[G_1]], 1
-; CGSCC-NEXT:    br label [[FOR_COND_1]]
-; CGSCC:       for.end.1:
-; CGSCC-NEXT:    ret i32 0
+; CHECK-LABEL: define {{[^@]+}}@main() {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[FOR_COND_0:%.*]]
+; CHECK:       for.cond.0:
+; CHECK-NEXT:    [[G_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY_0:%.*]] ]
+; CHECK-NEXT:    [[CMP_0:%.*]] = icmp ult i32 [[G_0]], 100
+; CHECK-NEXT:    br i1 [[CMP_0]], label [[FOR_BODY_0]], label [[FOR_END_0:%.*]]
+; CHECK:       for.body.0:
+; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[G_0]], 1
+; CHECK-NEXT:    br label [[FOR_COND_0]]
+; CHECK:       for.end.0:
+; CHECK-NEXT:    [[CALL:%.*]] = call ptr @malloc(i64 noundef 8)
+; CHECK-NEXT:    store ptr [[CALL]], ptr @e, align 8
+; CHECK-NEXT:    store ptr null, ptr [[CALL]], align 8
+; CHECK-NEXT:    br label [[FOR_COND_1:%.*]]
+; CHECK:       for.cond.1:
+; CHECK-NEXT:    [[G_1:%.*]] = phi i32 [ 0, [[FOR_END_0]] ], [ [[INC6:%.*]], [[FOR_BODY_1:%.*]] ]
+; CHECK-NEXT:    [[CMP_1:%.*]] = icmp ult i32 [[G_1]], 100
+; CHECK-NEXT:    br i1 [[CMP_1]], label [[FOR_BODY_1]], label [[FOR_END_1:%.*]]
+; CHECK:       for.body.1:
+; CHECK-NEXT:    [[INC6]] = add nuw nsw i32 [[G_1]], 1
+; CHECK-NEXT:    br label [[FOR_COND_1]]
+; CHECK:       for.end.1:
+; CHECK-NEXT:    ret i32 0
 ;
 entry:
   %f = alloca i32
@@ -2495,10 +2466,9 @@ for.body.0:
   br label %for.cond.0
 
 for.end.0:
-  %call = call i8* @malloc(i64 8)
-  store i8* %call, i8** bitcast (%struct.a** @e to i8**)
-  %b = bitcast i8* %call to %struct.a**
-  store %struct.a* null, %struct.a** %b
+  %call = call ptr @malloc(i64 8)
+  store ptr %call, ptr @e
+  store ptr null, ptr %call
   br label %for.cond.1
 
 for.cond.1:
@@ -2507,7 +2477,7 @@ for.cond.1:
   br i1 %cmp.1, label %for.body.1, label %for.end.1
 
 for.body.1:
-  %call4 = call i32 (i32*, ...) bitcast (i32 (i32)* @h to i32 (i32*, ...)*)(i32* nonnull %f)
+  %call4 = call i32 (ptr, ...) @h(ptr nonnull %f)
   %inc6 = add nuw nsw i32 %g.1, 1
   br label %for.cond.1
 
@@ -2515,7 +2485,7 @@ for.end.1:
   ret i32 0
 }
 
-declare noalias i8* @malloc(i64)
+declare noalias ptr @malloc(i64)
 
 define i32 @h(i32 %i) {
 ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
@@ -2543,7 +2513,7 @@ define void @bad_gep() {
 ; TUNIT-NEXT:  entry:
 ; TUNIT-NEXT:    [[N:%.*]] = alloca i8, align 1
 ; TUNIT-NEXT:    [[M:%.*]] = alloca i8, align 1
-; TUNIT-NEXT:    call void @llvm.lifetime.start.p0i8(i64 noundef 1, i8* noalias nocapture nofree noundef nonnull dereferenceable(1) [[N]])
+; TUNIT-NEXT:    call void @llvm.lifetime.start.p0(i64 noundef 1, ptr noalias nocapture nofree noundef nonnull dereferenceable(1) [[N]])
 ; TUNIT-NEXT:    br label [[EXIT:%.*]]
 ; TUNIT:       while.body:
 ; TUNIT-NEXT:    unreachable
@@ -2552,7 +2522,7 @@ define void @bad_gep() {
 ; TUNIT:       if.end:
 ; TUNIT-NEXT:    unreachable
 ; TUNIT:       exit:
-; TUNIT-NEXT:    call void @llvm.lifetime.end.p0i8(i64 noundef 1, i8* noalias nocapture nofree noundef nonnull dereferenceable(1) [[N]])
+; TUNIT-NEXT:    call void @llvm.lifetime.end.p0(i64 noundef 1, ptr noalias nocapture nofree noundef nonnull dereferenceable(1) [[N]])
 ; TUNIT-NEXT:    ret void
 ;
 ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
@@ -2561,7 +2531,7 @@ define void @bad_gep() {
 ; CGSCC-NEXT:  entry:
 ; CGSCC-NEXT:    [[N:%.*]] = alloca i8, align 1
 ; CGSCC-NEXT:    [[M:%.*]] = alloca i8, align 1
-; CGSCC-NEXT:    call void @llvm.lifetime.start.p0i8(i64 noundef 1, i8* noalias nocapture nofree noundef nonnull dereferenceable(1) [[N]])
+; CGSCC-NEXT:    call void @llvm.lifetime.start.p0(i64 noundef 1, ptr noalias nocapture nofree noundef nonnull dereferenceable(1) [[N]])
 ; CGSCC-NEXT:    br label [[EXIT:%.*]]
 ; CGSCC:       while.body:
 ; CGSCC-NEXT:    unreachable
@@ -2570,31 +2540,31 @@ define void @bad_gep() {
 ; CGSCC:       if.end:
 ; CGSCC-NEXT:    unreachable
 ; CGSCC:       exit:
-; CGSCC-NEXT:    call void @llvm.lifetime.end.p0i8(i64 noundef 1, i8* noalias nocapture nofree noundef nonnull dereferenceable(1) [[N]])
+; CGSCC-NEXT:    call void @llvm.lifetime.end.p0(i64 noundef 1, ptr noalias nocapture nofree noundef nonnull dereferenceable(1) [[N]])
 ; CGSCC-NEXT:    ret void
 ;
 entry:
   %n = alloca i8
   %m = alloca i8
-  call void @llvm.lifetime.start.p0i8(i64 1, i8* %n)
+  call void @llvm.lifetime.start.p0(i64 1, ptr %n)
   br label %exit
 
 while.body:
-  %call = call i1 @bad_gep_helper1(i8* %n, i8* %ptr, i8* %m)
+  %call = call i1 @bad_gep_helper1(ptr %n, ptr %ptr, ptr %m)
   br i1 %call, label %if.then, label %if.end
 
 if.then:
-  %0 = load i8, i8* %ptr
+  %0 = load i8, ptr %ptr
   call void @bad_gep_helper2(i8 %0)
   br label %if.end
 
 if.end:
-  %ptr = getelementptr inbounds i8, i8* %ptr, i64 1
-  %cmp = icmp eq i8* %ptr, @p
+  %ptr = getelementptr inbounds i8, ptr %ptr, i64 1
+  %cmp = icmp eq ptr %ptr, @p
   br i1 %cmp, label %exit, label %while.body
 
 exit:
-  call void @llvm.lifetime.end.p0i8(i64 1, i8* %n)
+  call void @llvm.lifetime.end.p0(i64 1, ptr %n)
   ret void
 }
 
@@ -2630,11 +2600,11 @@ b2:
   ret i8 %phi
 }
 
-declare i1 @bad_gep_helper1(i8*, i8*, i8*)
+declare i1 @bad_gep_helper1(ptr, ptr, ptr)
 declare void @bad_gep_helper2(i8)
 
-declare void @llvm.lifetime.start.p0i8(i64 %0, i8* %1)
-declare void @llvm.lifetime.end.p0i8(i64 %0, i8* %1)
+declare void @llvm.lifetime.start.p0(i64 %0, ptr %1)
+declare void @llvm.lifetime.end.p0(i64 %0, ptr %1)
 ;.
 ; TUNIT: attributes #[[ATTR0]] = { nofree noreturn nosync nounwind }
 ; TUNIT: attributes #[[ATTR1:[0-9]+]] = { memory(none) }


        


More information about the llvm-commits mailing list