[llvm] 2371c5a - [OpaquePtr][ARM] Use elementtype on ldrex/ldaex/stlex/strex

Arthur Eubanks via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 16 14:12:55 PDT 2022


Author: Arthur Eubanks
Date: 2022-03-16T14:11:53-07:00
New Revision: 2371c5a0e06d22b48da0427cebaf53a5e5c54635

URL: https://github.com/llvm/llvm-project/commit/2371c5a0e06d22b48da0427cebaf53a5e5c54635
DIFF: https://github.com/llvm/llvm-project/commit/2371c5a0e06d22b48da0427cebaf53a5e5c54635.diff

LOG: [OpaquePtr][ARM] Use elementtype on ldrex/ldaex/stlex/strex

Includes verifier changes checking the elementtype, clang codegen
changes to emit the elementtype, and ISel changes using the elementtype.

Basically the same as D120527.

Reviewed By: #opaque-pointers, nikic

Differential Revision: https://reviews.llvm.org/D121847

Added: 
    llvm/test/Bitcode/arm-intrinsics.bc
    llvm/test/Bitcode/arm-intrinsics.ll
    llvm/test/Verifier/arm-intrinsics.ll

Modified: 
    clang/lib/CodeGen/CGBuiltin.cpp
    clang/test/CodeGen/arm_acle.c
    clang/test/CodeGen/builtins-arm-exclusive.c
    clang/test/CodeGenCXX/builtins-arm-exclusive.cpp
    llvm/lib/Bitcode/Reader/BitcodeReader.cpp
    llvm/lib/IR/Verifier.cpp
    llvm/lib/Target/ARM/ARMISelLowering.cpp
    llvm/test/CodeGen/ARM/ldaex-stlex.ll
    llvm/test/CodeGen/ARM/ldrex-frame-size.ll
    llvm/test/CodeGen/ARM/ldstrex.ll
    llvm/test/Transforms/AtomicExpand/ARM/atomic-expansion-v7.ll
    llvm/test/Transforms/AtomicExpand/ARM/atomic-expansion-v8.ll
    llvm/test/Transforms/AtomicExpand/ARM/cmpxchg-weak.ll

Removed: 
    


################################################################################
diff  --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index bdb430c62e0d5..eec4c8089c757 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -7696,23 +7696,26 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
 
     QualType Ty = E->getType();
     llvm::Type *RealResTy = ConvertType(Ty);
-    llvm::Type *PtrTy = llvm::IntegerType::get(
-        getLLVMContext(), getContext().getTypeSize(Ty))->getPointerTo();
+    llvm::Type *IntTy =
+        llvm::IntegerType::get(getLLVMContext(), getContext().getTypeSize(Ty));
+    llvm::Type *PtrTy = IntTy->getPointerTo();
     LoadAddr = Builder.CreateBitCast(LoadAddr, PtrTy);
 
     Function *F = CGM.getIntrinsic(BuiltinID == ARM::BI__builtin_arm_ldaex
                                        ? Intrinsic::arm_ldaex
                                        : Intrinsic::arm_ldrex,
                                    PtrTy);
-    Value *Val = Builder.CreateCall(F, LoadAddr, "ldrex");
+    CallInst *Val = Builder.CreateCall(F, LoadAddr, "ldrex");
+    Val->addParamAttr(
+        0, Attribute::get(getLLVMContext(), Attribute::ElementType, IntTy));
 
     if (RealResTy->isPointerTy())
       return Builder.CreateIntToPtr(Val, RealResTy);
     else {
       llvm::Type *IntResTy = llvm::IntegerType::get(
           getLLVMContext(), CGM.getDataLayout().getTypeSizeInBits(RealResTy));
-      Val = Builder.CreateTruncOrBitCast(Val, IntResTy);
-      return Builder.CreateBitCast(Val, RealResTy);
+      return Builder.CreateBitCast(Builder.CreateTruncOrBitCast(Val, IntResTy),
+                                   RealResTy);
     }
   }
 
@@ -7762,7 +7765,11 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
                                        ? Intrinsic::arm_stlex
                                        : Intrinsic::arm_strex,
                                    StoreAddr->getType());
-    return Builder.CreateCall(F, {StoreVal, StoreAddr}, "strex");
+
+    CallInst *CI = Builder.CreateCall(F, {StoreVal, StoreAddr}, "strex");
+    CI->addParamAttr(
+        1, Attribute::get(getLLVMContext(), Attribute::ElementType, StoreTy));
+    return CI;
   }
 
   if (BuiltinID == ARM::BI__builtin_arm_clrex) {

diff  --git a/clang/test/CodeGen/arm_acle.c b/clang/test/CodeGen/arm_acle.c
index 350aff5814644..837c3a51f5fc2 100644
--- a/clang/test/CodeGen/arm_acle.c
+++ b/clang/test/CodeGen/arm_acle.c
@@ -141,8 +141,8 @@ void test_dbg(void) {
 // AArch32-NEXT:    [[TMP0:%.*]] = bitcast i8* [[P:%.*]] to i32*
 // AArch32-NEXT:    br label [[DO_BODY_I:%.*]]
 // AArch32:       do.body.i:
-// AArch32-NEXT:    [[LDREX_I:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* [[TMP0]]) [[ATTR1]]
-// AArch32-NEXT:    [[STREX_I:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 [[X:%.*]], i32* [[TMP0]]) [[ATTR1]]
+// AArch32-NEXT:    [[LDREX_I:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* elementtype(i32) [[TMP0]]) [[ATTR1]]
+// AArch32-NEXT:    [[STREX_I:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 [[X:%.*]], i32* elementtype(i32) [[TMP0]]) [[ATTR1]]
 // AArch32-NEXT:    [[TOBOOL_I:%.*]] = icmp ne i32 [[STREX_I]], 0
 // AArch32-NEXT:    br i1 [[TOBOOL_I]], label [[DO_BODY_I]], label [[__SWP_EXIT:%.*]], [[LOOP3:!llvm.loop !.*]]
 // AArch32:       __swp.exit:

diff  --git a/clang/test/CodeGen/builtins-arm-exclusive.c b/clang/test/CodeGen/builtins-arm-exclusive.c
index 5abe888e50ae5..fe2aad37ff5e7 100644
--- a/clang/test/CodeGen/builtins-arm-exclusive.c
+++ b/clang/test/CodeGen/builtins-arm-exclusive.c
@@ -10,7 +10,7 @@ int test_ldrex(char *addr, long long *addr64, float *addrfloat) {
 // CHECK-ARM64-LABEL: @test_ldrex
   int sum = 0;
   sum += __builtin_arm_ldrex(addr);
-// CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %addr)
+// CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* elementtype(i8) %addr)
 // CHECK: trunc i32 [[INTRES]] to i8
 
 // CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldxr.p0i8(i8* elementtype(i8) %addr)
@@ -18,7 +18,7 @@ int test_ldrex(char *addr, long long *addr64, float *addrfloat) {
 
   sum += __builtin_arm_ldrex((short *)addr);
 // CHECK: [[ADDR16:%.*]] = bitcast i8* %addr to i16*
-// CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldrex.p0i16(i16* [[ADDR16]])
+// CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldrex.p0i16(i16* elementtype(i16) [[ADDR16]])
 // CHECK: trunc i32 [[INTRES]] to i16
 
 // CHECK-ARM64: [[ADDR16:%.*]] = bitcast i8* %addr to i16*
@@ -27,7 +27,7 @@ int test_ldrex(char *addr, long long *addr64, float *addrfloat) {
 
   sum += __builtin_arm_ldrex((int *)addr);
 // CHECK: [[ADDR32:%.*]] = bitcast i8* %addr to i32*
-// CHECK: call i32 @llvm.arm.ldrex.p0i32(i32* [[ADDR32]])
+// CHECK: call i32 @llvm.arm.ldrex.p0i32(i32* elementtype(i32) [[ADDR32]])
 
 // CHECK-ARM64: [[ADDR32:%.*]] = bitcast i8* %addr to i32*
 // CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldxr.p0i32(i32* elementtype(i32) [[ADDR32]])
@@ -49,7 +49,7 @@ int test_ldrex(char *addr, long long *addr64, float *addrfloat) {
 
   sum += __builtin_arm_ldrex(addrfloat);
 // CHECK: [[INTADDR:%.*]] = bitcast float* %addrfloat to i32*
-// CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* [[INTADDR]])
+// CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* elementtype(i32) [[INTADDR]])
 // CHECK: bitcast i32 [[INTRES]] to float
 
 // CHECK-ARM64: [[INTADDR:%.*]] = bitcast float* %addrfloat to i32*
@@ -77,7 +77,7 @@ int test_ldrex(char *addr, long long *addr64, float *addrfloat) {
   sum += *__builtin_arm_ldrex((int **)addr);
 // CHECK: [[TMP4:%.*]] = bitcast i8* %addr to i32**
 // CHECK: [[TMP5:%.*]] = bitcast i32** [[TMP4]] to i32*
-// CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* [[TMP5]])
+// CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* elementtype(i32) [[TMP5]])
 // CHECK: inttoptr i32 [[INTRES]] to i32*
 
 // CHECK-ARM64: [[TMP4:%.*]] = bitcast i8* %addr to i32**
@@ -88,7 +88,7 @@ int test_ldrex(char *addr, long long *addr64, float *addrfloat) {
   sum += __builtin_arm_ldrex((struct Simple **)addr)->a;
 // CHECK: [[TMP4:%.*]] = bitcast i8* %addr to %struct.Simple**
 // CHECK: [[TMP5:%.*]] = bitcast %struct.Simple** [[TMP4]] to i32*
-// CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* [[TMP5]])
+// CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* elementtype(i32) [[TMP5]])
 // CHECK: inttoptr i32 [[INTRES]] to %struct.Simple*
 
 // CHECK-ARM64: [[TMP4:%.*]] = bitcast i8* %addr to %struct.Simple**
@@ -103,7 +103,7 @@ int test_ldaex(char *addr, long long *addr64, float *addrfloat) {
 // CHECK-ARM64-LABEL: @test_ldaex
   int sum = 0;
   sum += __builtin_arm_ldaex(addr);
-// CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldaex.p0i8(i8* %addr)
+// CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldaex.p0i8(i8* elementtype(i8) %addr)
 // CHECK: trunc i32 [[INTRES]] to i8
 
 // CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldaxr.p0i8(i8* elementtype(i8) %addr)
@@ -111,7 +111,7 @@ int test_ldaex(char *addr, long long *addr64, float *addrfloat) {
 
   sum += __builtin_arm_ldaex((short *)addr);
 // CHECK: [[ADDR16:%.*]] = bitcast i8* %addr to i16*
-// CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldaex.p0i16(i16* [[ADDR16]])
+// CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldaex.p0i16(i16* elementtype(i16) [[ADDR16]])
 // CHECK: trunc i32 [[INTRES]] to i16
 
 // CHECK-ARM64: [[ADDR16:%.*]] = bitcast i8* %addr to i16*
@@ -120,7 +120,7 @@ int test_ldaex(char *addr, long long *addr64, float *addrfloat) {
 
   sum += __builtin_arm_ldaex((int *)addr);
 // CHECK: [[ADDR32:%.*]] = bitcast i8* %addr to i32*
-// CHECK:  call i32 @llvm.arm.ldaex.p0i32(i32* [[ADDR32]])
+// CHECK:  call i32 @llvm.arm.ldaex.p0i32(i32* elementtype(i32) [[ADDR32]])
 
 // CHECK-ARM64: [[ADDR32:%.*]] = bitcast i8* %addr to i32*
 // CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldaxr.p0i32(i32* elementtype(i32) [[ADDR32]])
@@ -142,7 +142,7 @@ int test_ldaex(char *addr, long long *addr64, float *addrfloat) {
 
   sum += __builtin_arm_ldaex(addrfloat);
 // CHECK: [[INTADDR:%.*]] = bitcast float* %addrfloat to i32*
-// CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldaex.p0i32(i32* [[INTADDR]])
+// CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldaex.p0i32(i32* elementtype(i32) [[INTADDR]])
 // CHECK: bitcast i32 [[INTRES]] to float
 
 // CHECK-ARM64: [[INTADDR:%.*]] = bitcast float* %addrfloat to i32*
@@ -170,7 +170,7 @@ int test_ldaex(char *addr, long long *addr64, float *addrfloat) {
   sum += *__builtin_arm_ldaex((int **)addr);
 // CHECK: [[TMP4:%.*]] = bitcast i8* %addr to i32**
 // CHECK: [[TMP5:%.*]] = bitcast i32** [[TMP4]] to i32*
-// CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldaex.p0i32(i32* [[TMP5]])
+// CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldaex.p0i32(i32* elementtype(i32) [[TMP5]])
 // CHECK: inttoptr i32 [[INTRES]] to i32*
 
 // CHECK-ARM64: [[TMP4:%.*]] = bitcast i8* %addr to i32**
@@ -181,7 +181,7 @@ int test_ldaex(char *addr, long long *addr64, float *addrfloat) {
   sum += __builtin_arm_ldaex((struct Simple **)addr)->a;
 // CHECK: [[TMP4:%.*]] = bitcast i8* %addr to %struct.Simple**
 // CHECK: [[TMP5:%.*]] = bitcast %struct.Simple** [[TMP4]] to i32*
-// CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldaex.p0i32(i32* [[TMP5]])
+// CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldaex.p0i32(i32* elementtype(i32) [[TMP5]])
 // CHECK: inttoptr i32 [[INTRES]] to %struct.Simple*
 
 // CHECK-ARM64: [[TMP4:%.*]] = bitcast i8* %addr to %struct.Simple**
@@ -197,20 +197,20 @@ int test_strex(char *addr) {
   int res = 0;
   struct Simple var = {0};
   res |= __builtin_arm_strex(4, addr);
-// CHECK: call i32 @llvm.arm.strex.p0i8(i32 4, i8* %addr)
+// CHECK: call i32 @llvm.arm.strex.p0i8(i32 4, i8* elementtype(i8) %addr)
 
 // CHECK-ARM64: call i32 @llvm.aarch64.stxr.p0i8(i64 4, i8* elementtype(i8) %addr)
 
   res |= __builtin_arm_strex(42, (short *)addr);
 // CHECK: [[ADDR16:%.*]] = bitcast i8* %addr to i16*
-// CHECK:  call i32 @llvm.arm.strex.p0i16(i32 42, i16* [[ADDR16]])
+// CHECK:  call i32 @llvm.arm.strex.p0i16(i32 42, i16* elementtype(i16) [[ADDR16]])
 
 // CHECK-ARM64: [[ADDR16:%.*]] = bitcast i8* %addr to i16*
 // CHECK-ARM64:  call i32 @llvm.aarch64.stxr.p0i16(i64 42, i16* elementtype(i16) [[ADDR16]])
 
   res |= __builtin_arm_strex(42, (int *)addr);
 // CHECK: [[ADDR32:%.*]] = bitcast i8* %addr to i32*
-// CHECK: call i32 @llvm.arm.strex.p0i32(i32 42, i32* [[ADDR32]])
+// CHECK: call i32 @llvm.arm.strex.p0i32(i32 42, i32* elementtype(i32) [[ADDR32]])
 
 // CHECK-ARM64: [[ADDR32:%.*]] = bitcast i8* %addr to i32*
 // CHECK-ARM64: call i32 @llvm.aarch64.stxr.p0i32(i64 42, i32* elementtype(i32) [[ADDR32]])
@@ -231,7 +231,7 @@ int test_strex(char *addr) {
   res |= __builtin_arm_strex(2.71828f, (float *)addr);
 // CHECK: [[TMP4:%.*]] = bitcast i8* %addr to float*
 // CHECK: [[TMP5:%.*]] = bitcast float* [[TMP4]] to i32*
-// CHECK: call i32 @llvm.arm.strex.p0i32(i32 1076754509, i32* [[TMP5]])
+// CHECK: call i32 @llvm.arm.strex.p0i32(i32 1076754509, i32* elementtype(i32) [[TMP5]])
 
 // CHECK-ARM64: [[TMP4:%.*]] = bitcast i8* %addr to float*
 // CHECK-ARM64: [[TMP5:%.*]] = bitcast float* [[TMP4]] to i32*
@@ -255,7 +255,7 @@ int test_strex(char *addr) {
 // CHECK: [[TMP4:%.*]] = bitcast i8* %addr to %struct.Simple**
 // CHECK: [[TMP5:%.*]] = bitcast %struct.Simple** [[TMP4]] to i32*
 // CHECK: [[INTVAL:%.*]] = ptrtoint %struct.Simple* %var to i32
-// CHECK: call i32 @llvm.arm.strex.p0i32(i32 [[INTVAL]], i32* [[TMP5]])
+// CHECK: call i32 @llvm.arm.strex.p0i32(i32 [[INTVAL]], i32* elementtype(i32) [[TMP5]])
 
 // CHECK-ARM64: [[TMP4:%.*]] = bitcast i8* %addr to %struct.Simple**
 // CHECK-ARM64: [[TMP5:%.*]] = bitcast %struct.Simple** [[TMP4]] to i64*
@@ -271,20 +271,20 @@ int test_stlex(char *addr) {
   int res = 0;
   struct Simple var = {0};
   res |= __builtin_arm_stlex(4, addr);
-// CHECK: call i32 @llvm.arm.stlex.p0i8(i32 4, i8* %addr)
+// CHECK: call i32 @llvm.arm.stlex.p0i8(i32 4, i8* elementtype(i8) %addr)
 
 // CHECK-ARM64: call i32 @llvm.aarch64.stlxr.p0i8(i64 4, i8* elementtype(i8) %addr)
 
   res |= __builtin_arm_stlex(42, (short *)addr);
 // CHECK: [[ADDR16:%.*]] = bitcast i8* %addr to i16*
-// CHECK:  call i32 @llvm.arm.stlex.p0i16(i32 42, i16* [[ADDR16]])
+// CHECK:  call i32 @llvm.arm.stlex.p0i16(i32 42, i16* elementtype(i16) [[ADDR16]])
 
 // CHECK-ARM64: [[ADDR16:%.*]] = bitcast i8* %addr to i16*
 // CHECK-ARM64:  call i32 @llvm.aarch64.stlxr.p0i16(i64 42, i16* elementtype(i16) [[ADDR16]])
 
   res |= __builtin_arm_stlex(42, (int *)addr);
 // CHECK: [[ADDR32:%.*]] = bitcast i8* %addr to i32*
-// CHECK: call i32 @llvm.arm.stlex.p0i32(i32 42, i32* [[ADDR32]])
+// CHECK: call i32 @llvm.arm.stlex.p0i32(i32 42, i32* elementtype(i32) [[ADDR32]])
 
 // CHECK-ARM64: [[ADDR32:%.*]] = bitcast i8* %addr to i32*
 // CHECK-ARM64: call i32 @llvm.aarch64.stlxr.p0i32(i64 42, i32* elementtype(i32) [[ADDR32]])
@@ -305,7 +305,7 @@ int test_stlex(char *addr) {
   res |= __builtin_arm_stlex(2.71828f, (float *)addr);
 // CHECK: [[TMP4:%.*]] = bitcast i8* %addr to float*
 // CHECK: [[TMP5:%.*]] = bitcast float* [[TMP4]] to i32*
-// CHECK: call i32 @llvm.arm.stlex.p0i32(i32 1076754509, i32* [[TMP5]])
+// CHECK: call i32 @llvm.arm.stlex.p0i32(i32 1076754509, i32* elementtype(i32) [[TMP5]])
 
 // CHECK-ARM64: [[TMP4:%.*]] = bitcast i8* %addr to float*
 // CHECK-ARM64: [[TMP5:%.*]] = bitcast float* [[TMP4]] to i32*
@@ -329,7 +329,7 @@ int test_stlex(char *addr) {
 // CHECK: [[TMP4:%.*]] = bitcast i8* %addr to %struct.Simple**
 // CHECK: [[TMP5:%.*]] = bitcast %struct.Simple** [[TMP4]] to i32*
 // CHECK: [[INTVAL:%.*]] = ptrtoint %struct.Simple* %var to i32
-// CHECK: call i32 @llvm.arm.stlex.p0i32(i32 [[INTVAL]], i32* [[TMP5]])
+// CHECK: call i32 @llvm.arm.stlex.p0i32(i32 [[INTVAL]], i32* elementtype(i32) [[TMP5]])
 
 // CHECK-ARM64: [[TMP4:%.*]] = bitcast i8* %addr to %struct.Simple**
 // CHECK-ARM64: [[TMP5:%.*]] = bitcast %struct.Simple** [[TMP4]] to i64*

diff  --git a/clang/test/CodeGenCXX/builtins-arm-exclusive.cpp b/clang/test/CodeGenCXX/builtins-arm-exclusive.cpp
index 05cb330a4ddae..e927eb9f91b22 100644
--- a/clang/test/CodeGenCXX/builtins-arm-exclusive.cpp
+++ b/clang/test/CodeGenCXX/builtins-arm-exclusive.cpp
@@ -4,7 +4,7 @@
 bool b;
 
 // CHECK-LABEL: @_Z10test_ldrexv()
-// CHECK: call i32 @llvm.arm.ldrex.p0i8(i8* @b)
+// CHECK: call i32 @llvm.arm.ldrex.p0i8(i8* elementtype(i8) @b)
 
 // CHECK-ARM64-LABEL: @_Z10test_ldrexv()
 // CHECK-ARM64: call i64 @llvm.aarch64.ldxr.p0i8(i8* elementtype(i8) @b)
@@ -14,7 +14,7 @@ void test_ldrex() {
 }
 
 // CHECK-LABEL: @_Z10tset_strexv()
-// CHECK: %{{.*}} = call i32 @llvm.arm.strex.p0i8(i32 1, i8* @b)
+// CHECK: %{{.*}} = call i32 @llvm.arm.strex.p0i8(i32 1, i8* elementtype(i8) @b)
 
 // CHECK-ARM64-LABEL: @_Z10tset_strexv()
 // CHECK-ARM64: %{{.*}} = call i32 @llvm.aarch64.stxr.p0i8(i64 1, i8* elementtype(i8) @b)

diff  --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index 3ad5fd7171db8..afe18c556cdaa 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -52,6 +52,7 @@
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/IntrinsicsAArch64.h"
+#include "llvm/IR/IntrinsicsARM.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Metadata.h"
 #include "llvm/IR/Module.h"
@@ -4144,11 +4145,23 @@ Error BitcodeReader::propagateAttributeTypes(CallBase *CB,
   case Intrinsic::aarch64_ldaxr:
   case Intrinsic::aarch64_ldxr:
   case Intrinsic::aarch64_stlxr:
-  case Intrinsic::aarch64_stxr: {
-    unsigned ArgNo = CB->getIntrinsicID() == Intrinsic::aarch64_stlxr ||
-                             CB->getIntrinsicID() == Intrinsic::aarch64_stxr
-                         ? 1
-                         : 0;
+  case Intrinsic::aarch64_stxr:
+  case Intrinsic::arm_ldaex:
+  case Intrinsic::arm_ldrex:
+  case Intrinsic::arm_stlex:
+  case Intrinsic::arm_strex: {
+    unsigned ArgNo;
+    switch (CB->getIntrinsicID()) {
+    case Intrinsic::aarch64_stlxr:
+    case Intrinsic::aarch64_stxr:
+    case Intrinsic::arm_stlex:
+    case Intrinsic::arm_strex:
+      ArgNo = 1;
+      break;
+    default:
+      ArgNo = 0;
+      break;
+    }
     if (!Attrs.getParamElementType(ArgNo)) {
       Type *ElTy = getPtrElementTypeByID(ArgTyIDs[ArgNo]);
       if (!ElTy)

diff  --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 632cc0af3846c..ec15f5f1efae2 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -85,6 +85,7 @@
 #include "llvm/IR/IntrinsicInst.h"
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/IntrinsicsAArch64.h"
+#include "llvm/IR/IntrinsicsARM.h"
 #include "llvm/IR/IntrinsicsWebAssembly.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Metadata.h"
@@ -5523,7 +5524,9 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) {
   case Intrinsic::preserve_array_access_index:
   case Intrinsic::preserve_struct_access_index:
   case Intrinsic::aarch64_ldaxr:
-  case Intrinsic::aarch64_ldxr: {
+  case Intrinsic::aarch64_ldxr:
+  case Intrinsic::arm_ldaex:
+  case Intrinsic::arm_ldrex: {
     Type *ElemTy = Call.getParamElementType(0);
     Assert(ElemTy,
            "Intrinsic requires elementtype attribute on first argument.",
@@ -5531,7 +5534,9 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) {
     break;
   }
   case Intrinsic::aarch64_stlxr:
-  case Intrinsic::aarch64_stxr: {
+  case Intrinsic::aarch64_stxr:
+  case Intrinsic::arm_stlex:
+  case Intrinsic::arm_strex: {
     Type *ElemTy = Call.getAttributes().getParamElementType(1);
     Assert(ElemTy,
            "Intrinsic requires elementtype attribute on second argument.",

diff  --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index 987b67fcae485..583b6b8afb5f3 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -20807,24 +20807,24 @@ bool ARMTargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info,
   case Intrinsic::arm_ldaex:
   case Intrinsic::arm_ldrex: {
     auto &DL = I.getCalledFunction()->getParent()->getDataLayout();
-    PointerType *PtrTy = cast<PointerType>(I.getArgOperand(0)->getType());
+    Type *ValTy = I.getParamElementType(0);
     Info.opc = ISD::INTRINSIC_W_CHAIN;
-    Info.memVT = MVT::getVT(PtrTy->getPointerElementType());
+    Info.memVT = MVT::getVT(ValTy);
     Info.ptrVal = I.getArgOperand(0);
     Info.offset = 0;
-    Info.align = DL.getABITypeAlign(PtrTy->getPointerElementType());
+    Info.align = DL.getABITypeAlign(ValTy);
     Info.flags = MachineMemOperand::MOLoad | MachineMemOperand::MOVolatile;
     return true;
   }
   case Intrinsic::arm_stlex:
   case Intrinsic::arm_strex: {
     auto &DL = I.getCalledFunction()->getParent()->getDataLayout();
-    PointerType *PtrTy = cast<PointerType>(I.getArgOperand(1)->getType());
+    Type *ValTy = I.getParamElementType(1);
     Info.opc = ISD::INTRINSIC_W_CHAIN;
-    Info.memVT = MVT::getVT(PtrTy->getPointerElementType());
+    Info.memVT = MVT::getVT(ValTy);
     Info.ptrVal = I.getArgOperand(1);
     Info.offset = 0;
-    Info.align = DL.getABITypeAlign(PtrTy->getPointerElementType());
+    Info.align = DL.getABITypeAlign(ValTy);
     Info.flags = MachineMemOperand::MOStore | MachineMemOperand::MOVolatile;
     return true;
   }
@@ -21119,8 +21119,11 @@ Value *ARMTargetLowering::emitLoadLinked(IRBuilderBase &Builder, Type *ValueTy,
   Type *Tys[] = { Addr->getType() };
   Intrinsic::ID Int = IsAcquire ? Intrinsic::arm_ldaex : Intrinsic::arm_ldrex;
   Function *Ldrex = Intrinsic::getDeclaration(M, Int, Tys);
+  CallInst *CI = Builder.CreateCall(Ldrex, Addr);
 
-  return Builder.CreateTruncOrBitCast(Builder.CreateCall(Ldrex, Addr), ValueTy);
+  CI->addParamAttr(
+      0, Attribute::get(M->getContext(), Attribute::ElementType, ValueTy));
+  return Builder.CreateTruncOrBitCast(CI, ValueTy);
 }
 
 void ARMTargetLowering::emitAtomicCmpXchgNoStoreLLBalance(
@@ -21158,10 +21161,13 @@ Value *ARMTargetLowering::emitStoreConditional(IRBuilderBase &Builder,
   Type *Tys[] = { Addr->getType() };
   Function *Strex = Intrinsic::getDeclaration(M, Int, Tys);
 
-  return Builder.CreateCall(
+  CallInst *CI = Builder.CreateCall(
       Strex, {Builder.CreateZExtOrBitCast(
                   Val, Strex->getFunctionType()->getParamType(0)),
               Addr});
+  CI->addParamAttr(1, Attribute::get(M->getContext(), Attribute::ElementType,
+                                     Val->getType()));
+  return CI;
 }
 
 

diff  --git a/llvm/test/Bitcode/arm-intrinsics.bc b/llvm/test/Bitcode/arm-intrinsics.bc
new file mode 100644
index 0000000000000..92a5f263fd18a
Binary files /dev/null and b/llvm/test/Bitcode/arm-intrinsics.bc 
diff er

diff  --git a/llvm/test/Bitcode/arm-intrinsics.ll b/llvm/test/Bitcode/arm-intrinsics.ll
new file mode 100644
index 0000000000000..42066c6029821
--- /dev/null
+++ b/llvm/test/Bitcode/arm-intrinsics.ll
@@ -0,0 +1,19 @@
+; RUN: llvm-dis < %S/arm-intrinsics.bc | FileCheck %s
+
+define void @f(i32* %p) {
+; CHECK: call i32 @llvm.arm.ldrex.p0i32(i32* elementtype(i32)
+  %a = call i32 @llvm.arm.ldrex.p0i32(i32* %p)
+; CHECK: call i32 @llvm.arm.strex.p0i32(i32 0, i32* elementtype(i32)
+  %c = call i32 @llvm.arm.strex.p0i32(i32 0, i32* %p)
+
+; CHECK: call i32 @llvm.arm.ldaex.p0i32(i32* elementtype(i32)
+  %a2 = call i32 @llvm.arm.ldaex.p0i32(i32* %p)
+; CHECK: call i32 @llvm.arm.stlex.p0i32(i32 0, i32* elementtype(i32)
+  %c2 = call i32 @llvm.arm.stlex.p0i32(i32 0, i32* %p)
+  ret void
+}
+
+declare i32 @llvm.arm.ldrex.p0i32(i32*)
+declare i32 @llvm.arm.ldaex.p0i32(i32*)
+declare i32 @llvm.arm.stlex.p0i32(i32, i32*)
+declare i32 @llvm.arm.strex.p0i32(i32, i32*)
\ No newline at end of file

diff  --git a/llvm/test/CodeGen/ARM/ldaex-stlex.ll b/llvm/test/CodeGen/ARM/ldaex-stlex.ll
index bfdfea3315630..fc9dded9e875d 100644
--- a/llvm/test/CodeGen/ARM/ldaex-stlex.ll
+++ b/llvm/test/CodeGen/ARM/ldaex-stlex.ll
@@ -36,7 +36,7 @@ declare i32 @llvm.arm.stlexd(i32, i32, i8*) nounwind
 ; CHECK-NOT: uxtb
 ; CHECK-NOT: and
 define zeroext i8 @test_load_i8(i8* %addr) {
-  %val = call i32 @llvm.arm.ldaex.p0i8(i8* %addr)
+  %val = call i32 @llvm.arm.ldaex.p0i8(i8* elementtype(i8) %addr)
   %val8 = trunc i32 %val to i8
   ret i8 %val8
 }
@@ -46,7 +46,7 @@ define zeroext i8 @test_load_i8(i8* %addr) {
 ; CHECK-NOT: uxth
 ; CHECK-NOT: and
 define zeroext i16 @test_load_i16(i16* %addr) {
-  %val = call i32 @llvm.arm.ldaex.p0i16(i16* %addr)
+  %val = call i32 @llvm.arm.ldaex.p0i16(i16* elementtype(i16) %addr)
   %val16 = trunc i32 %val to i16
   ret i16 %val16
 }
@@ -54,7 +54,7 @@ define zeroext i16 @test_load_i16(i16* %addr) {
 ; CHECK-LABEL: test_load_i32:
 ; CHECK: ldaex r0, [r0]
 define i32 @test_load_i32(i32* %addr) {
-  %val = call i32 @llvm.arm.ldaex.p0i32(i32* %addr)
+  %val = call i32 @llvm.arm.ldaex.p0i32(i32* elementtype(i32) %addr)
   ret i32 %val
 }
 
@@ -67,7 +67,7 @@ declare i32 @llvm.arm.ldaex.p0i32(i32*) nounwind readonly
 ; CHECK: stlexb r0, r1, [r2]
 define i32 @test_store_i8(i32, i8 %val, i8* %addr) {
   %extval = zext i8 %val to i32
-  %res = call i32 @llvm.arm.stlex.p0i8(i32 %extval, i8* %addr)
+  %res = call i32 @llvm.arm.stlex.p0i8(i32 %extval, i8* elementtype(i8) %addr)
   ret i32 %res
 }
 
@@ -76,14 +76,14 @@ define i32 @test_store_i8(i32, i8 %val, i8* %addr) {
 ; CHECK: stlexh r0, r1, [r2]
 define i32 @test_store_i16(i32, i16 %val, i16* %addr) {
   %extval = zext i16 %val to i32
-  %res = call i32 @llvm.arm.stlex.p0i16(i32 %extval, i16* %addr)
+  %res = call i32 @llvm.arm.stlex.p0i16(i32 %extval, i16* elementtype(i16) %addr)
   ret i32 %res
 }
 
 ; CHECK-LABEL: test_store_i32:
 ; CHECK: stlex r0, r1, [r2]
 define i32 @test_store_i32(i32, i32 %val, i32* %addr) {
-  %res = call i32 @llvm.arm.stlex.p0i32(i32 %val, i32* %addr)
+  %res = call i32 @llvm.arm.stlex.p0i32(i32 %val, i32* elementtype(i32) %addr)
   ret i32 %res
 }
 

diff  --git a/llvm/test/CodeGen/ARM/ldrex-frame-size.ll b/llvm/test/CodeGen/ARM/ldrex-frame-size.ll
index f34fb8f4d22df..8766e024649c5 100644
--- a/llvm/test/CodeGen/ARM/ldrex-frame-size.ll
+++ b/llvm/test/CodeGen/ARM/ldrex-frame-size.ll
@@ -16,7 +16,7 @@ define void @test_large_frame() {
   %ptr = alloca i32, i32 252
 
   %addr = getelementptr i32, i32* %ptr, i32 1
-  call i32 @llvm.arm.ldrex.p0i32(i32* %addr)
+  call i32 @llvm.arm.ldrex.p0i32(i32* elementtype(i32) %addr)
   ret void
 }
 
@@ -29,7 +29,7 @@ define void @test_small_frame() {
   %ptr = alloca i32, i32 251
 
   %addr = getelementptr i32, i32* %ptr, i32 1
-  call i32 @llvm.arm.ldrex.p0i32(i32* %addr)
+  call i32 @llvm.arm.ldrex.p0i32(i32* elementtype(i32) %addr)
   ret void
 }
 

diff  --git a/llvm/test/CodeGen/ARM/ldstrex.ll b/llvm/test/CodeGen/ARM/ldstrex.ll
index 73afa0e27469e..7c97163854f15 100644
--- a/llvm/test/CodeGen/ARM/ldstrex.ll
+++ b/llvm/test/CodeGen/ARM/ldstrex.ll
@@ -38,7 +38,7 @@ declare i32 @llvm.arm.strexd(i32, i32, i8*) nounwind
 ; CHECK-NOT: uxtb
 ; CHECK-NOT: and
 define zeroext i8 @test_load_i8(i8* %addr) {
-  %val = call i32 @llvm.arm.ldrex.p0i8(i8* %addr)
+  %val = call i32 @llvm.arm.ldrex.p0i8(i8* elementtype(i8) %addr)
   %val8 = trunc i32 %val to i8
   ret i8 %val8
 }
@@ -48,7 +48,7 @@ define zeroext i8 @test_load_i8(i8* %addr) {
 ; CHECK-NOT: uxth
 ; CHECK-NOT: and
 define zeroext i16 @test_load_i16(i16* %addr) {
-  %val = call i32 @llvm.arm.ldrex.p0i16(i16* %addr)
+  %val = call i32 @llvm.arm.ldrex.p0i16(i16* elementtype(i16) %addr)
   %val16 = trunc i32 %val to i16
   ret i16 %val16
 }
@@ -56,7 +56,7 @@ define zeroext i16 @test_load_i16(i16* %addr) {
 ; CHECK-LABEL: test_load_i32:
 ; CHECK: ldrex r0, [r0]
 define i32 @test_load_i32(i32* %addr) {
-  %val = call i32 @llvm.arm.ldrex.p0i32(i32* %addr)
+  %val = call i32 @llvm.arm.ldrex.p0i32(i32* elementtype(i32) %addr)
   ret i32 %val
 }
 
@@ -69,7 +69,7 @@ declare i32 @llvm.arm.ldrex.p0i32(i32*) nounwind readonly
 ; CHECK: strexb r0, r1, [r2]
 define i32 @test_store_i8(i32, i8 %val, i8* %addr) {
   %extval = zext i8 %val to i32
-  %res = call i32 @llvm.arm.strex.p0i8(i32 %extval, i8* %addr)
+  %res = call i32 @llvm.arm.strex.p0i8(i32 %extval, i8* elementtype(i8) %addr)
   ret i32 %res
 }
 
@@ -78,14 +78,14 @@ define i32 @test_store_i8(i32, i8 %val, i8* %addr) {
 ; CHECK: strexh r0, r1, [r2]
 define i32 @test_store_i16(i32, i16 %val, i16* %addr) {
   %extval = zext i16 %val to i32
-  %res = call i32 @llvm.arm.strex.p0i16(i32 %extval, i16* %addr)
+  %res = call i32 @llvm.arm.strex.p0i16(i32 %extval, i16* elementtype(i16) %addr)
   ret i32 %res
 }
 
 ; CHECK-LABEL: test_store_i32:
 ; CHECK: strex r0, r1, [r2]
 define i32 @test_store_i32(i32, i32 %val, i32* %addr) {
-  %res = call i32 @llvm.arm.strex.p0i32(i32 %val, i32* %addr)
+  %res = call i32 @llvm.arm.strex.p0i32(i32 %val, i32* elementtype(i32) %addr)
   ret i32 %res
 }
 
@@ -108,15 +108,15 @@ define void @excl_addrmode() {
 ; CHECK-T2ADDRMODE-LABEL: excl_addrmode:
   %base1020 = load i32*, i32** @base
   %offset1020 = getelementptr i32, i32* %base1020, i32 255
-  call i32 @llvm.arm.ldrex.p0i32(i32* %offset1020)
-  call i32 @llvm.arm.strex.p0i32(i32 0, i32* %offset1020)
+  call i32 @llvm.arm.ldrex.p0i32(i32* elementtype(i32) %offset1020)
+  call i32 @llvm.arm.strex.p0i32(i32 0, i32* elementtype(i32) %offset1020)
 ; CHECK-T2ADDRMODE: ldrex {{r[0-9]+}}, [{{r[0-9]+}}, #1020]
 ; CHECK-T2ADDRMODE: strex {{r[0-9]+}}, {{r[0-9]+}}, [{{r[0-9]+}}, #1020]
 
   %base1024 = load i32*, i32** @base
   %offset1024 = getelementptr i32, i32* %base1024, i32 256
-  call i32 @llvm.arm.ldrex.p0i32(i32* %offset1024)
-  call i32 @llvm.arm.strex.p0i32(i32 0, i32* %offset1024)
+  call i32 @llvm.arm.ldrex.p0i32(i32* elementtype(i32) %offset1024)
+  call i32 @llvm.arm.strex.p0i32(i32 0, i32* elementtype(i32) %offset1024)
 ; CHECK-T2ADDRMODE: add.w r[[ADDR:[0-9]+]], {{r[0-9]+}}, #1024
 ; CHECK-T2ADDRMODE: ldrex {{r[0-9]+}}, [r[[ADDR]]]
 ; CHECK-T2ADDRMODE: strex {{r[0-9]+}}, {{r[0-9]+}}, [r[[ADDR]]]
@@ -125,16 +125,16 @@ define void @excl_addrmode() {
   %addr8 = bitcast i32* %base1 to i8*
   %offset1_8 = getelementptr i8, i8* %addr8, i32 1
   %offset1 = bitcast i8* %offset1_8 to i32*
-  call i32 @llvm.arm.ldrex.p0i32(i32* %offset1)
-  call i32 @llvm.arm.strex.p0i32(i32 0, i32* %offset1)
+  call i32 @llvm.arm.ldrex.p0i32(i32* elementtype(i32) %offset1)
+  call i32 @llvm.arm.strex.p0i32(i32 0, i32* elementtype(i32) %offset1)
 ; CHECK-T2ADDRMODE: adds r[[ADDR:[0-9]+]], #1
 ; CHECK-T2ADDRMODE: ldrex {{r[0-9]+}}, [r[[ADDR]]]
 ; CHECK-T2ADDRMODE: strex {{r[0-9]+}}, {{r[0-9]+}}, [r[[ADDR]]]
 
   %local = alloca i8, i32 1024
   %local32 = bitcast i8* %local to i32*
-  call i32 @llvm.arm.ldrex.p0i32(i32* %local32)
-  call i32 @llvm.arm.strex.p0i32(i32 0, i32* %local32)
+  call i32 @llvm.arm.ldrex.p0i32(i32* elementtype(i32) %local32)
+  call i32 @llvm.arm.strex.p0i32(i32 0, i32* elementtype(i32) %local32)
 ; CHECK-T2ADDRMODE: mov r[[ADDR:[0-9]+]], sp
 ; CHECK-T2ADDRMODE: ldrex {{r[0-9]+}}, [r[[ADDR]]]
 ; CHECK-T2ADDRMODE: strex {{r[0-9]+}}, {{r[0-9]+}}, [r[[ADDR]]]
@@ -148,15 +148,15 @@ define void @test_excl_addrmode_folded() {
 
   %local.0 = getelementptr i8, i8* %local, i32 4
   %local32.0 = bitcast i8* %local.0 to i32*
-  call i32 @llvm.arm.ldrex.p0i32(i32* %local32.0)
-  call i32 @llvm.arm.strex.p0i32(i32 0, i32* %local32.0)
+  call i32 @llvm.arm.ldrex.p0i32(i32* elementtype(i32) %local32.0)
+  call i32 @llvm.arm.strex.p0i32(i32 0, i32* elementtype(i32) %local32.0)
 ; CHECK-T2ADDRMODE: ldrex {{r[0-9]+}}, [sp, #4]
 ; CHECK-T2ADDRMODE: strex {{r[0-9]+}}, {{r[0-9]+}}, [sp, #4]
 
   %local.1 = getelementptr i8, i8* %local, i32 1020
   %local32.1 = bitcast i8* %local.1 to i32*
-  call i32 @llvm.arm.ldrex.p0i32(i32* %local32.1)
-  call i32 @llvm.arm.strex.p0i32(i32 0, i32* %local32.1)
+  call i32 @llvm.arm.ldrex.p0i32(i32* elementtype(i32) %local32.1)
+  call i32 @llvm.arm.strex.p0i32(i32 0, i32* elementtype(i32) %local32.1)
 ; CHECK-T2ADDRMODE: ldrex {{r[0-9]+}}, [sp, #1020]
 ; CHECK-T2ADDRMODE: strex {{r[0-9]+}}, {{r[0-9]+}}, [sp, #1020]
 
@@ -169,8 +169,8 @@ define void @test_excl_addrmode_range() {
 
   %local.0 = getelementptr i8, i8* %local, i32 1024
   %local32.0 = bitcast i8* %local.0 to i32*
-  call i32 @llvm.arm.ldrex.p0i32(i32* %local32.0)
-  call i32 @llvm.arm.strex.p0i32(i32 0, i32* %local32.0)
+  call i32 @llvm.arm.ldrex.p0i32(i32* elementtype(i32) %local32.0)
+  call i32 @llvm.arm.strex.p0i32(i32 0, i32* elementtype(i32) %local32.0)
 ; CHECK-T2ADDRMODE: mov r[[TMP:[0-9]+]], sp
 ; CHECK-T2ADDRMODE: add.w r[[ADDR:[0-9]+]], r[[TMP]], #1024
 ; CHECK-T2ADDRMODE: ldrex {{r[0-9]+}}, [r[[ADDR]]]
@@ -185,8 +185,8 @@ define void @test_excl_addrmode_align() {
 
   %local.0 = getelementptr i8, i8* %local, i32 2
   %local32.0 = bitcast i8* %local.0 to i32*
-  call i32 @llvm.arm.ldrex.p0i32(i32* %local32.0)
-  call i32 @llvm.arm.strex.p0i32(i32 0, i32* %local32.0)
+  call i32 @llvm.arm.ldrex.p0i32(i32* elementtype(i32) %local32.0)
+  call i32 @llvm.arm.strex.p0i32(i32 0, i32* elementtype(i32) %local32.0)
 ; CHECK-T2ADDRMODE: mov r[[ADDR:[0-9]+]], sp
 ; CHECK-T2ADDRMODE: adds r[[ADDR:[0-9]+]], #2
 ; CHECK-T2ADDRMODE: ldrex {{r[0-9]+}}, [r[[ADDR]]]
@@ -201,8 +201,8 @@ define void @test_excl_addrmode_sign() {
 
   %local.0 = getelementptr i8, i8* %local, i32 -4
   %local32.0 = bitcast i8* %local.0 to i32*
-  call i32 @llvm.arm.ldrex.p0i32(i32* %local32.0)
-  call i32 @llvm.arm.strex.p0i32(i32 0, i32* %local32.0)
+  call i32 @llvm.arm.ldrex.p0i32(i32* elementtype(i32) %local32.0)
+  call i32 @llvm.arm.strex.p0i32(i32 0, i32* elementtype(i32) %local32.0)
 ; CHECK-T2ADDRMODE: mov r[[ADDR:[0-9]+]], sp
 ; CHECK-T2ADDRMODE: subs r[[ADDR:[0-9]+]], #4
 ; CHECK-T2ADDRMODE: ldrex {{r[0-9]+}}, [r[[ADDR]]]
@@ -218,8 +218,8 @@ define void @test_excl_addrmode_combination() {
 
   %local.0 = getelementptr i8, i8* %local, i32 4
   %local32.0 = bitcast i8* %local.0 to i32*
-  call i32 @llvm.arm.ldrex.p0i32(i32* %local32.0)
-  call i32 @llvm.arm.strex.p0i32(i32 0, i32* %local32.0)
+  call i32 @llvm.arm.ldrex.p0i32(i32* elementtype(i32) %local32.0)
+  call i32 @llvm.arm.strex.p0i32(i32 0, i32* elementtype(i32) %local32.0)
 ; CHECK-T2ADDRMODE: ldrex {{r[0-9]+}}, [sp, #68]
 ; CHECK-T2ADDRMODE: strex {{r[0-9]+}}, {{r[0-9]+}}, [sp, #68]
 
@@ -234,7 +234,7 @@ define zeroext i8 @test_cross_block_zext_i8(i1 %tst, i8* %addr) {
 ; CHECK-NOT: uxtb
 ; CHECK-NOT: and
 ; CHECK: bx lr
-  %val = call i32 @llvm.arm.ldrex.p0i8(i8* %addr)
+  %val = call i32 @llvm.arm.ldrex.p0i8(i8* elementtype(i8) %addr)
   br i1 %tst, label %end, label %mid
 mid:
   ret i8 42

diff  --git a/llvm/test/Transforms/AtomicExpand/ARM/atomic-expansion-v7.ll b/llvm/test/Transforms/AtomicExpand/ARM/atomic-expansion-v7.ll
index 39108874b7f98..1cc20eb9f71e4 100644
--- a/llvm/test/Transforms/AtomicExpand/ARM/atomic-expansion-v7.ll
+++ b/llvm/test/Transforms/AtomicExpand/ARM/atomic-expansion-v7.ll
@@ -5,10 +5,10 @@ define i8 @test_atomic_xchg_i8(i8* %ptr, i8 %xchgend) {
 ; CHECK-NOT: dmb
 ; CHECK: br label %[[LOOP:.*]]
 ; CHECK: [[LOOP]]:
-; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr)
+; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* elementtype(i8) %ptr)
 ; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i8
 ; CHECK: [[NEWVAL32:%.*]] = zext i8 %xchgend to i32
-; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* %ptr)
+; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* elementtype(i8) %ptr)
 ; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0
 ; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]]
 ; CHECK: [[END]]:
@@ -23,11 +23,11 @@ define i16 @test_atomic_add_i16(i16* %ptr, i16 %addend) {
 ; CHECK: call void @llvm.arm.dmb(i32 11)
 ; CHECK: br label %[[LOOP:.*]]
 ; CHECK: [[LOOP]]:
-; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i16(i16* %ptr)
+; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i16(i16* elementtype(i16) %ptr)
 ; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i16
 ; CHECK: [[NEWVAL:%.*]] = add i16 [[OLDVAL]], %addend
 ; CHECK: [[NEWVAL32:%.*]] = zext i16 [[NEWVAL]] to i32
-; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i16(i32 [[NEWVAL32]], i16* %ptr)
+; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i16(i32 [[NEWVAL32]], i16* elementtype(i16) %ptr)
 ; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0
 ; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]]
 ; CHECK: [[END]]:
@@ -42,9 +42,9 @@ define i32 @test_atomic_sub_i32(i32* %ptr, i32 %subend) {
 ; CHECK-NOT: dmb
 ; CHECK: br label %[[LOOP:.*]]
 ; CHECK: [[LOOP]]:
-; CHECK: [[OLDVAL:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* %ptr)
+; CHECK: [[OLDVAL:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* elementtype(i32) %ptr)
 ; CHECK: [[NEWVAL:%.*]] = sub i32 [[OLDVAL]], %subend
-; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 [[NEWVAL]], i32* %ptr)
+; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 [[NEWVAL]], i32* elementtype(i32) %ptr)
 ; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0
 ; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]]
 ; CHECK: [[END]]:
@@ -59,11 +59,11 @@ define i8 @test_atomic_and_i8(i8* %ptr, i8 %andend) {
 ; CHECK: call void @llvm.arm.dmb(i32 11)
 ; CHECK: br label %[[LOOP:.*]]
 ; CHECK: [[LOOP]]:
-; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr)
+; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* elementtype(i8) %ptr)
 ; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i8
 ; CHECK: [[NEWVAL:%.*]] = and i8 [[OLDVAL]], %andend
 ; CHECK: [[NEWVAL32:%.*]] = zext i8 [[NEWVAL]] to i32
-; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* %ptr)
+; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* elementtype(i8) %ptr)
 ; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0
 ; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]]
 ; CHECK: [[END]]:
@@ -78,12 +78,12 @@ define i16 @test_atomic_nand_i16(i16* %ptr, i16 %nandend) {
 ; CHECK: call void @llvm.arm.dmb(i32 11)
 ; CHECK: br label %[[LOOP:.*]]
 ; CHECK: [[LOOP]]:
-; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i16(i16* %ptr)
+; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i16(i16* elementtype(i16) %ptr)
 ; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i16
 ; CHECK: [[NEWVAL_TMP:%.*]] = and i16 [[OLDVAL]], %nandend
 ; CHECK: [[NEWVAL:%.*]] = xor i16 [[NEWVAL_TMP]], -1
 ; CHECK: [[NEWVAL32:%.*]] = zext i16 [[NEWVAL]] to i32
-; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i16(i32 [[NEWVAL32]], i16* %ptr)
+; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i16(i32 [[NEWVAL32]], i16* elementtype(i16) %ptr)
 ; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0
 ; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]]
 ; CHECK: [[END]]:
@@ -126,11 +126,11 @@ define i8 @test_atomic_xor_i8(i8* %ptr, i8 %xorend) {
 ; CHECK: call void @llvm.arm.dmb(i32 11)
 ; CHECK: br label %[[LOOP:.*]]
 ; CHECK: [[LOOP]]:
-; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr)
+; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* elementtype(i8) %ptr)
 ; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i8
 ; CHECK: [[NEWVAL:%.*]] = xor i8 [[OLDVAL]], %xorend
 ; CHECK: [[NEWVAL32:%.*]] = zext i8 [[NEWVAL]] to i32
-; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* %ptr)
+; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* elementtype(i8) %ptr)
 ; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0
 ; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]]
 ; CHECK: [[END]]:
@@ -145,12 +145,12 @@ define i8 @test_atomic_max_i8(i8* %ptr, i8 %maxend) {
 ; CHECK: call void @llvm.arm.dmb(i32 11)
 ; CHECK: br label %[[LOOP:.*]]
 ; CHECK: [[LOOP]]:
-; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr)
+; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* elementtype(i8) %ptr)
 ; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i8
 ; CHECK: [[WANT_OLD:%.*]] = icmp sgt i8 [[OLDVAL]], %maxend
 ; CHECK: [[NEWVAL:%.*]] = select i1 [[WANT_OLD]], i8 [[OLDVAL]], i8 %maxend
 ; CHECK: [[NEWVAL32:%.*]] = zext i8 [[NEWVAL]] to i32
-; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* %ptr)
+; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* elementtype(i8) %ptr)
 ; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0
 ; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]]
 ; CHECK: [[END]]:
@@ -165,12 +165,12 @@ define i8 @test_atomic_min_i8(i8* %ptr, i8 %minend) {
 ; CHECK: call void @llvm.arm.dmb(i32 11)
 ; CHECK: br label %[[LOOP:.*]]
 ; CHECK: [[LOOP]]:
-; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr)
+; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* elementtype(i8) %ptr)
 ; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i8
 ; CHECK: [[WANT_OLD:%.*]] = icmp sle i8 [[OLDVAL]], %minend
 ; CHECK: [[NEWVAL:%.*]] = select i1 [[WANT_OLD]], i8 [[OLDVAL]], i8 %minend
 ; CHECK: [[NEWVAL32:%.*]] = zext i8 [[NEWVAL]] to i32
-; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* %ptr)
+; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* elementtype(i8) %ptr)
 ; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0
 ; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]]
 ; CHECK: [[END]]:
@@ -185,12 +185,12 @@ define i8 @test_atomic_umax_i8(i8* %ptr, i8 %umaxend) {
 ; CHECK: call void @llvm.arm.dmb(i32 11)
 ; CHECK: br label %[[LOOP:.*]]
 ; CHECK: [[LOOP]]:
-; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr)
+; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* elementtype(i8) %ptr)
 ; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i8
 ; CHECK: [[WANT_OLD:%.*]] = icmp ugt i8 [[OLDVAL]], %umaxend
 ; CHECK: [[NEWVAL:%.*]] = select i1 [[WANT_OLD]], i8 [[OLDVAL]], i8 %umaxend
 ; CHECK: [[NEWVAL32:%.*]] = zext i8 [[NEWVAL]] to i32
-; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* %ptr)
+; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* elementtype(i8) %ptr)
 ; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0
 ; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]]
 ; CHECK: [[END]]:
@@ -205,12 +205,12 @@ define i8 @test_atomic_umin_i8(i8* %ptr, i8 %uminend) {
 ; CHECK: call void @llvm.arm.dmb(i32 11)
 ; CHECK: br label %[[LOOP:.*]]
 ; CHECK: [[LOOP]]:
-; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr)
+; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* elementtype(i8) %ptr)
 ; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i8
 ; CHECK: [[WANT_OLD:%.*]] = icmp ule i8 [[OLDVAL]], %uminend
 ; CHECK: [[NEWVAL:%.*]] = select i1 [[WANT_OLD]], i8 [[OLDVAL]], i8 %uminend
 ; CHECK: [[NEWVAL32:%.*]] = zext i8 [[NEWVAL]] to i32
-; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* %ptr)
+; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* elementtype(i8) %ptr)
 ; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0
 ; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]]
 ; CHECK: [[END]]:
@@ -225,7 +225,7 @@ define i8 @test_cmpxchg_i8_seqcst_seqcst(i8* %ptr, i8 %desired, i8 %newval) {
 ; CHECK: br label %[[START:.*]]
 
 ; CHECK: [[START]]:
-; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr)
+; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* elementtype(i8) %ptr)
 ; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i8
 ; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i8 [[OLDVAL]], %desired
 ; CHECK: br i1 [[SHOULD_STORE]], label %[[FENCED_STORE:.*]], label %[[NO_STORE_BB:.*]]
@@ -237,12 +237,12 @@ define i8 @test_cmpxchg_i8_seqcst_seqcst(i8* %ptr, i8 %desired, i8 %newval) {
 ; CHECK: [[LOOP]]:
 ; CHECK: [[LOADED_LOOP:%.*]] = phi i8 [ [[OLDVAL]], %[[FENCED_STORE]] ], [ [[OLDVAL_LOOP:%.*]], %[[RELEASED_LOAD:.*]] ]
 ; CHECK: [[NEWVAL32:%.*]] = zext i8 %newval to i32
-; CHECK: [[TRYAGAIN:%.*]] =  call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* %ptr)
+; CHECK: [[TRYAGAIN:%.*]] =  call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* elementtype(i8) %ptr)
 ; CHECK: [[TST:%.*]] = icmp eq i32 [[TRYAGAIN]], 0
 ; CHECK: br i1 [[TST]], label %[[SUCCESS_BB:.*]], label %[[RELEASED_LOAD]]
 
 ; CHECK: [[RELEASED_LOAD]]:
-; CHECK: [[OLDVAL32_LOOP:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr)
+; CHECK: [[OLDVAL32_LOOP:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* elementtype(i8) %ptr)
 ; CHECK: [[OLDVAL_LOOP]] = trunc i32 [[OLDVAL32_LOOP]] to i8
 ; CHECK: [[SHOULD_STORE_LOOP:%.*]] = icmp eq i8 [[OLDVAL_LOOP]], %desired
 ; CHECK: br i1 [[SHOULD_STORE_LOOP]], label %[[LOOP]], label %[[NO_STORE_BB]]
@@ -276,7 +276,7 @@ define i16 @test_cmpxchg_i16_seqcst_monotonic(i16* %ptr, i16 %desired, i16 %newv
 ; CHECK: br label %[[LOOP:.*]]
 
 ; CHECK: [[LOOP]]:
-; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i16(i16* %ptr)
+; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i16(i16* elementtype(i16) %ptr)
 ; CHECK: [[OLDVAL:%.*]] = trunc i32 %1 to i16
 ; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i16 [[OLDVAL]], %desired
 ; CHECK: br i1 [[SHOULD_STORE]], label %[[FENCED_STORE:.*]], label %[[NO_STORE_BB:.*]]
@@ -288,12 +288,12 @@ define i16 @test_cmpxchg_i16_seqcst_monotonic(i16* %ptr, i16 %desired, i16 %newv
 ; CHECK: [[LOOP]]:
 ; CHECK: [[LOADED_LOOP:%.*]] = phi i16 [ [[OLDVAL]], %[[FENCED_STORE]] ], [ [[OLDVAL_LOOP:%.*]], %[[RELEASED_LOAD:.*]] ]
 ; CHECK: [[NEWVAL32:%.*]] = zext i16 %newval to i32
-; CHECK: [[TRYAGAIN:%.*]] =  call i32 @llvm.arm.strex.p0i16(i32 [[NEWVAL32]], i16* %ptr)
+; CHECK: [[TRYAGAIN:%.*]] =  call i32 @llvm.arm.strex.p0i16(i32 [[NEWVAL32]], i16* elementtype(i16) %ptr)
 ; CHECK: [[TST:%.*]] = icmp eq i32 [[TRYAGAIN]], 0
 ; CHECK: br i1 [[TST]], label %[[SUCCESS_BB:.*]], label %[[RELEASED_LOAD:.*]]
 
 ; CHECK: [[RELEASED_LOAD]]:
-; CHECK: [[OLDVAL32_LOOP:%.*]] = call i32 @llvm.arm.ldrex.p0i16(i16* %ptr)
+; CHECK: [[OLDVAL32_LOOP:%.*]] = call i32 @llvm.arm.ldrex.p0i16(i16* elementtype(i16) %ptr)
 ; CHECK: [[OLDVAL_LOOP]] = trunc i32 [[OLDVAL32_LOOP]] to i16
 ; CHECK: [[SHOULD_STORE_LOOP:%.*]] = icmp eq i16 [[OLDVAL_LOOP]], %desired
 ; CHECK: br i1 [[SHOULD_STORE_LOOP]], label %[[LOOP]], label %[[NO_STORE_BB]]
@@ -328,7 +328,7 @@ define i32 @test_cmpxchg_i32_acquire_acquire(i32* %ptr, i32 %desired, i32 %newva
 ; CHECK: br label %[[LOOP:.*]]
 
 ; CHECK: [[LOOP]]:
-; CHECK: [[OLDVAL:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* %ptr)
+; CHECK: [[OLDVAL:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* elementtype(i32) %ptr)
 ; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i32 [[OLDVAL]], %desired
 ; CHECK: br i1 [[SHOULD_STORE]], label %[[FENCED_STORE:.*]], label %[[NO_STORE_BB:.*]]
 
@@ -337,7 +337,7 @@ define i32 @test_cmpxchg_i32_acquire_acquire(i32* %ptr, i32 %desired, i32 %newva
 
 ; CHECK: [[TRY_STORE]]:
 ; CHECK: [[LOADED_TRYSTORE:%.*]] = phi i32 [ [[OLDVAL]], %[[FENCED_STORE]] ]
-; CHECK: [[TRYAGAIN:%.*]] =  call i32 @llvm.arm.strex.p0i32(i32 %newval, i32* %ptr)
+; CHECK: [[TRYAGAIN:%.*]] =  call i32 @llvm.arm.strex.p0i32(i32 %newval, i32* elementtype(i32) %ptr)
 ; CHECK: [[TST:%.*]] = icmp eq i32 [[TRYAGAIN]], 0
 ; CHECK: br i1 [[TST]], label %[[SUCCESS_BB:.*]], label %[[LOOP]]
 
@@ -425,7 +425,7 @@ define i32 @test_cmpxchg_minsize(i32* %addr, i32 %desired, i32 %new) minsize {
 ; CHECK:     br label %[[START:.*]]
 
 ; CHECK: [[START]]:
-; CHECK:     [[LOADED:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* %addr)
+; CHECK:     [[LOADED:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* elementtype(i32) %addr)
 ; CHECK:     [[SHOULD_STORE:%.*]] = icmp eq i32 [[LOADED]], %desired
 ; CHECK:     br i1 [[SHOULD_STORE]], label %[[FENCED_STORE:.*]], label %[[NO_STORE_BB:.*]]
 
@@ -434,7 +434,7 @@ define i32 @test_cmpxchg_minsize(i32* %addr, i32 %desired, i32 %new) minsize {
 
 ; CHECK: [[TRY_STORE]]:
 ; CHECK:     [[LOADED_TRYSTORE:%.*]] = phi i32 [ [[LOADED]], %[[FENCED_STORE]] ]
-; CHECK:     [[STREX:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 %new, i32* %addr)
+; CHECK:     [[STREX:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 %new, i32* elementtype(i32) %addr)
 ; CHECK:     [[SUCCESS:%.*]] = icmp eq i32 [[STREX]], 0
 ; CHECK:     br i1 [[SUCCESS]], label %[[SUCCESS_BB:.*]], label %[[START]]
 

diff  --git a/llvm/test/Transforms/AtomicExpand/ARM/atomic-expansion-v8.ll b/llvm/test/Transforms/AtomicExpand/ARM/atomic-expansion-v8.ll
index deecf01f24365..cce8799ad1198 100644
--- a/llvm/test/Transforms/AtomicExpand/ARM/atomic-expansion-v8.ll
+++ b/llvm/test/Transforms/AtomicExpand/ARM/atomic-expansion-v8.ll
@@ -5,10 +5,10 @@ define i8 @test_atomic_xchg_i8(i8* %ptr, i8 %xchgend) {
 ; CHECK-NOT: fence
 ; CHECK: br label %[[LOOP:.*]]
 ; CHECK: [[LOOP]]:
-; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr)
+; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* elementtype(i8) %ptr)
 ; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i8
 ; CHECK: [[NEWVAL32:%.*]] = zext i8 %xchgend to i32
-; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* %ptr)
+; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* elementtype(i8) %ptr)
 ; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0
 ; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]]
 ; CHECK: [[END]]:
@@ -23,11 +23,11 @@ define i16 @test_atomic_add_i16(i16* %ptr, i16 %addend) {
 ; CHECK-NOT: fence
 ; CHECK: br label %[[LOOP:.*]]
 ; CHECK: [[LOOP]]:
-; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldaex.p0i16(i16* %ptr)
+; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldaex.p0i16(i16* elementtype(i16) %ptr)
 ; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i16
 ; CHECK: [[NEWVAL:%.*]] = add i16 [[OLDVAL]], %addend
 ; CHECK: [[NEWVAL32:%.*]] = zext i16 [[NEWVAL]] to i32
-; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.stlex.p0i16(i32 [[NEWVAL32]], i16* %ptr)
+; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.stlex.p0i16(i32 [[NEWVAL32]], i16* elementtype(i16) %ptr)
 ; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0
 ; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]]
 ; CHECK: [[END]]:
@@ -42,9 +42,9 @@ define i32 @test_atomic_sub_i32(i32* %ptr, i32 %subend) {
 ; CHECK-NOT: fence
 ; CHECK: br label %[[LOOP:.*]]
 ; CHECK: [[LOOP]]:
-; CHECK: [[OLDVAL:%.*]] = call i32 @llvm.arm.ldaex.p0i32(i32* %ptr)
+; CHECK: [[OLDVAL:%.*]] = call i32 @llvm.arm.ldaex.p0i32(i32* elementtype(i32) %ptr)
 ; CHECK: [[NEWVAL:%.*]] = sub i32 [[OLDVAL]], %subend
-; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 [[NEWVAL]], i32* %ptr)
+; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 [[NEWVAL]], i32* elementtype(i32) %ptr)
 ; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0
 ; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]]
 ; CHECK: [[END]]:
@@ -88,7 +88,7 @@ define i8 @test_cmpxchg_i8_seqcst_seqcst(i8* %ptr, i8 %desired, i8 %newval) {
 ; CHECK: br label %[[LOOP:.*]]
 
 ; CHECK: [[LOOP]]:
-; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldaex.p0i8(i8* %ptr)
+; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldaex.p0i8(i8* elementtype(i8) %ptr)
 ; CHECK: [[OLDVAL:%.*]] = trunc i32 %1 to i8
 ; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i8 [[OLDVAL]], %desired
 ; CHECK: br i1 [[SHOULD_STORE]], label %[[FENCED_STORE:.*]], label %[[NO_STORE_BB:.*]]
@@ -99,7 +99,7 @@ define i8 @test_cmpxchg_i8_seqcst_seqcst(i8* %ptr, i8 %desired, i8 %newval) {
 ; CHECK: [[TRY_STORE]]:
 ; CHECK: [[LOADED_TRYSTORE:%.*]] = phi i8 [ [[OLDVAL]], %[[FENCED_STORE]] ]
 ; CHECK: [[NEWVAL32:%.*]] = zext i8 %newval to i32
-; CHECK: [[TRYAGAIN:%.*]] =  call i32 @llvm.arm.stlex.p0i8(i32 [[NEWVAL32]], i8* %ptr)
+; CHECK: [[TRYAGAIN:%.*]] =  call i32 @llvm.arm.stlex.p0i8(i32 [[NEWVAL32]], i8* elementtype(i8) %ptr)
 ; CHECK: [[TST:%.*]] = icmp eq i32 [[TRYAGAIN]], 0
 ; CHECK: br i1 [[TST]], label %[[SUCCESS_BB:.*]], label %[[LOOP]]
 
@@ -133,7 +133,7 @@ define i16 @test_cmpxchg_i16_seqcst_monotonic(i16* %ptr, i16 %desired, i16 %newv
 ; CHECK: br label %[[LOOP:.*]]
 
 ; CHECK: [[LOOP]]:
-; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldaex.p0i16(i16* %ptr)
+; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldaex.p0i16(i16* elementtype(i16) %ptr)
 ; CHECK: [[OLDVAL:%.*]] = trunc i32 %1 to i16
 ; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i16 [[OLDVAL]], %desired
 ; CHECK: br i1 [[SHOULD_STORE]], label %[[FENCED_STORE:.*]], label %[[NO_STORE_BB:.*]]
@@ -144,7 +144,7 @@ define i16 @test_cmpxchg_i16_seqcst_monotonic(i16* %ptr, i16 %desired, i16 %newv
 ; CHECK: [[TRY_STORE]]:
 ; CHECK: [[LOADED_TRYSTORE:%.*]] = phi i16 [ [[OLDVAL]], %[[FENCED_STORE]] ]
 ; CHECK: [[NEWVAL32:%.*]] = zext i16 %newval to i32
-; CHECK: [[TRYAGAIN:%.*]] =  call i32 @llvm.arm.stlex.p0i16(i32 [[NEWVAL32]], i16* %ptr)
+; CHECK: [[TRYAGAIN:%.*]] =  call i32 @llvm.arm.stlex.p0i16(i32 [[NEWVAL32]], i16* elementtype(i16) %ptr)
 ; CHECK: [[TST:%.*]] = icmp eq i32 [[TRYAGAIN]], 0
 ; CHECK: br i1 [[TST]], label %[[SUCCESS_BB:.*]], label %[[LOOP]]
 
@@ -179,7 +179,7 @@ define i32 @test_cmpxchg_i32_acquire_acquire(i32* %ptr, i32 %desired, i32 %newva
 ; CHECK: br label %[[LOOP:.*]]
 
 ; CHECK: [[LOOP]]:
-; CHECK: [[OLDVAL:%.*]] = call i32 @llvm.arm.ldaex.p0i32(i32* %ptr)
+; CHECK: [[OLDVAL:%.*]] = call i32 @llvm.arm.ldaex.p0i32(i32* elementtype(i32) %ptr)
 ; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i32 [[OLDVAL]], %desired
 ; CHECK: br i1 [[SHOULD_STORE]], label %[[FENCED_STORE:.*]], label %[[NO_STORE_BB:.*]]
 
@@ -188,7 +188,7 @@ define i32 @test_cmpxchg_i32_acquire_acquire(i32* %ptr, i32 %desired, i32 %newva
 
 ; CHECK: [[TRY_STORE]]:
 ; CHECK: [[LOADED_TRYSTORE:%.*]] = phi i32 [ [[OLDVAL]], %[[FENCED_STORE]] ]
-; CHECK: [[TRYAGAIN:%.*]] =  call i32 @llvm.arm.strex.p0i32(i32 %newval, i32* %ptr)
+; CHECK: [[TRYAGAIN:%.*]] =  call i32 @llvm.arm.strex.p0i32(i32 %newval, i32* elementtype(i32) %ptr)
 ; CHECK: [[TST:%.*]] = icmp eq i32 [[TRYAGAIN]], 0
 ; CHECK: br i1 [[TST]], label %[[SUCCESS_BB:.*]], label %[[LOOP]]
 

diff  --git a/llvm/test/Transforms/AtomicExpand/ARM/cmpxchg-weak.ll b/llvm/test/Transforms/AtomicExpand/ARM/cmpxchg-weak.ll
index 828c1c4cb3b7e..1b90ac999dcdb 100644
--- a/llvm/test/Transforms/AtomicExpand/ARM/cmpxchg-weak.ll
+++ b/llvm/test/Transforms/AtomicExpand/ARM/cmpxchg-weak.ll
@@ -6,7 +6,7 @@ define i32 @test_cmpxchg_seq_cst(i32* %addr, i32 %desired, i32 %new) {
 ; CHECK:     br label %[[START:.*]]
 
 ; CHECK: [[START]]:
-; CHECK:     [[LOADED:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* %addr)
+; CHECK:     [[LOADED:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* elementtype(i32) %addr)
 ; CHECK:     [[SHOULD_STORE:%.*]] = icmp eq i32 [[LOADED]], %desired
 ; CHECK:     br i1 [[SHOULD_STORE]], label %[[FENCED_STORE:.*]], label %[[NO_STORE_BB:.*]]
 
@@ -16,7 +16,7 @@ define i32 @test_cmpxchg_seq_cst(i32* %addr, i32 %desired, i32 %new) {
 
 ; CHECK: [[TRY_STORE]]:
 ; CHECK:     [[LOADED_TRYSTORE:%.*]] = phi i32 [ [[LOADED]], %[[FENCED_STORE]] ]
-; CHECK:     [[STREX:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 %new, i32* %addr)
+; CHECK:     [[STREX:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 %new, i32* elementtype(i32) %addr)
 ; CHECK:     [[SUCCESS:%.*]] = icmp eq i32 [[STREX]], 0
 ; CHECK:     br i1 [[SUCCESS]], label %[[SUCCESS_BB:.*]], label %[[FAILURE_BB:.*]]
 
@@ -49,7 +49,7 @@ define i1 @test_cmpxchg_weak_fail(i32* %addr, i32 %desired, i32 %new) {
 ; CHECK:     br label %[[START:.*]]
 
 ; CHECK: [[START]]:
-; CHECK:     [[LOADED:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* %addr)
+; CHECK:     [[LOADED:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* elementtype(i32) %addr)
 ; CHECK:     [[SHOULD_STORE:%.*]] = icmp eq i32 [[LOADED]], %desired
 ; CHECK:     br i1 [[SHOULD_STORE]], label %[[FENCED_STORE:.*]], label %[[NO_STORE_BB:.*]]
 
@@ -58,7 +58,7 @@ define i1 @test_cmpxchg_weak_fail(i32* %addr, i32 %desired, i32 %new) {
 ; CHECK:     br label %[[TRY_STORE:.*]]
 
 ; CHECK: [[TRY_STORE]]:
-; CHECK:     [[STREX:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 %new, i32* %addr)
+; CHECK:     [[STREX:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 %new, i32* elementtype(i32) %addr)
 ; CHECK:     [[SUCCESS:%.*]] = icmp eq i32 [[STREX]], 0
 ; CHECK:     br i1 [[SUCCESS]], label %[[SUCCESS_BB:.*]], label %[[FAILURE_BB:.*]]
 
@@ -89,7 +89,7 @@ define i32 @test_cmpxchg_monotonic(i32* %addr, i32 %desired, i32 %new) {
 ; CHECK:     br label %[[START:.*]]
 
 ; CHECK: [[START]]:
-; CHECK:     [[LOADED:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* %addr)
+; CHECK:     [[LOADED:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* elementtype(i32) %addr)
 ; CHECK:     [[SHOULD_STORE:%.*]] = icmp eq i32 [[LOADED]], %desired
 ; CHECK:     br i1 [[SHOULD_STORE]], label %[[FENCED_STORE:.*]], label %[[NO_STORE_BB:.*]]
 
@@ -98,7 +98,7 @@ define i32 @test_cmpxchg_monotonic(i32* %addr, i32 %desired, i32 %new) {
 
 ; CHECK: [[TRY_STORE]]:
 ; CHECK:     [[LOADED_TRYSTORE:%.*]] = phi i32 [ [[LOADED]], %[[FENCED_STORE]] ]
-; CHECK:     [[STREX:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 %new, i32* %addr)
+; CHECK:     [[STREX:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 %new, i32* elementtype(i32) %addr)
 ; CHECK:     [[SUCCESS:%.*]] = icmp eq i32 [[STREX]], 0
 ; CHECK:     br i1 [[SUCCESS]], label %[[SUCCESS_BB:.*]], label %[[FAILURE_BB:.*]]
 
@@ -131,7 +131,7 @@ define i32 @test_cmpxchg_seq_cst_minsize(i32* %addr, i32 %desired, i32 %new) min
 ; CHECK:     br label %[[START:.*]]
 
 ; CHECK: [[START]]:
-; CHECK:     [[LOADED:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* %addr)
+; CHECK:     [[LOADED:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* elementtype(i32) %addr)
 ; CHECK:     [[SHOULD_STORE:%.*]] = icmp eq i32 [[LOADED]], %desired
 ; CHECK:     br i1 [[SHOULD_STORE]], label %[[FENCED_STORE:.*]], label %[[NO_STORE_BB:.*]]
 
@@ -141,7 +141,7 @@ define i32 @test_cmpxchg_seq_cst_minsize(i32* %addr, i32 %desired, i32 %new) min
 
 ; CHECK: [[TRY_STORE]]:
 ; CHECK:     [[LOADED_TRYSTORE:%.*]] = phi i32 [ [[LOADED]], %[[FENCED_STORE]] ]
-; CHECK:     [[STREX:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 %new, i32* %addr)
+; CHECK:     [[STREX:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 %new, i32* elementtype(i32) %addr)
 ; CHECK:     [[SUCCESS:%.*]] = icmp eq i32 [[STREX]], 0
 ; CHECK:     br i1 [[SUCCESS]], label %[[SUCCESS_BB:.*]], label %[[FAILURE_BB:.*]]
 

diff  --git a/llvm/test/Verifier/arm-intrinsics.ll b/llvm/test/Verifier/arm-intrinsics.ll
new file mode 100644
index 0000000000000..a9f2fe94f5685
--- /dev/null
+++ b/llvm/test/Verifier/arm-intrinsics.ll
@@ -0,0 +1,19 @@
+; RUN: not opt -passes=verify -S < %s 2>&1 | FileCheck %s
+
+define void @f(i32* %p) {
+; CHECK: Intrinsic requires elementtype attribute on first argument
+  %a = call i32 @llvm.arm.ldrex.p0i32(i32* %p)
+; CHECK: Intrinsic requires elementtype attribute on second argument
+  %c = call i32 @llvm.arm.strex.p0i32(i32 0, i32* %p)
+
+; CHECK: Intrinsic requires elementtype attribute on first argument
+  %a2 = call i32 @llvm.arm.ldaex.p0i32(i32* %p)
+; CHECK: Intrinsic requires elementtype attribute on second argument
+  %c2 = call i32 @llvm.arm.stlex.p0i32(i32 0, i32* %p)
+  ret void
+}
+
+declare i32 @llvm.arm.ldrex.p0i32(i32*)
+declare i32 @llvm.arm.ldaex.p0i32(i32*)
+declare i32 @llvm.arm.stlex.p0i32(i32, i32*)
+declare i32 @llvm.arm.strex.p0i32(i32, i32*)
\ No newline at end of file


        


More information about the llvm-commits mailing list