[llvm] 8f0a479 - [Instrumentor] Fix indirect arguments on gpu targets (#209835)

via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 16 08:59:11 PDT 2026


Author: jandrovins
Date: 2026-07-16T08:59:06-07:00
New Revision: 8f0a479f46c98e1a098319786d0848e4b9e0a98d

URL: https://github.com/llvm/llvm-project/commit/8f0a479f46c98e1a098319786d0848e4b9e0a98d
DIFF: https://github.com/llvm/llvm-project/commit/8f0a479f46c98e1a098319786d0848e4b9e0a98d.diff

LOG: [Instrumentor] Fix indirect arguments on gpu targets (#209835)

When an argument is passed indirectly,
`IRTCallDescription::createLLVMCall` spills it into a temporary alloca
and passes that alloca address to the runtime call. The alloca is
created in the target's alloca address space. On GPUs it is not address
space 0, which is what the runtime expects for indirect parameters. The
alloca pointer was passed as the argument, so its type didn't match the
call's declared parameter type, causing a "bad signature" assertion in
`CallInst::init` when instrumenting GPU code that requires indirection.
The solution is therefore to cast this pointer to address space 0 before
passing it the the instrumentor call.

Added: 
    llvm/test/Instrumentation/Instrumentor/load_store_gpu_ind.json
    llvm/test/Instrumentation/Instrumentor/load_store_gpu_ind.ll

Modified: 
    llvm/lib/Transforms/IPO/Instrumentor.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/IPO/Instrumentor.cpp b/llvm/lib/Transforms/IPO/Instrumentor.cpp
index 3b52e3e1f4605..bc188e5a4bf8e 100644
--- a/llvm/lib/Transforms/IPO/Instrumentor.cpp
+++ b/llvm/lib/Transforms/IPO/Instrumentor.cpp
@@ -111,6 +111,8 @@ Value *tryToCast(IRBTy &IRB, Value *V, Type *Ty, const DataLayout &DL,
     return V;
   if (VTy->isAggregateType() || VTy->isVectorTy())
     return V;
+  if (VTy->isPointerTy() && Ty->isPointerTy())
+    return IRB.CreatePointerBitCastOrAddrSpaceCast(V, Ty);
   TypeSize RequestedSize = DL.getTypeSizeInBits(Ty);
   TypeSize ValueSize = DL.getTypeSizeInBits(VTy);
   bool ShouldTruncate = RequestedSize < ValueSize;
@@ -126,8 +128,6 @@ Value *tryToCast(IRBTy &IRB, Value *V, Type *Ty, const DataLayout &DL,
                                        /*IsSigned=*/false),
                      Ty, DL, AllowTruncate);
   }
-  if (VTy->isPointerTy() && Ty->isPointerTy())
-    return IRB.CreatePointerBitCastOrAddrSpaceCast(V, Ty);
   if (VTy->isIntegerTy() && Ty->isIntegerTy())
     return IRB.CreateIntCast(V, Ty, /*IsSigned=*/false);
   // Use bit-preserving casts for floating-point values: convert float to int
@@ -797,7 +797,7 @@ CallInst *IRTCallDescription::createLLVMCall(Value *&V,
 
       auto *AI = IIRB.getAlloca(Fn, CallParam->getType());
       IIRB.IRB.CreateStore(CallParam, AI);
-      CallParam = CachedParam = AI;
+      CallParam = CachedParam = tryToCast(IIRB.IRB, AI, IIRB.PtrTy, DL);
     }
   }
 

diff  --git a/llvm/test/Instrumentation/Instrumentor/load_store_gpu_ind.json b/llvm/test/Instrumentation/Instrumentor/load_store_gpu_ind.json
new file mode 100644
index 0000000000000..c939df5b38df6
--- /dev/null
+++ b/llvm/test/Instrumentation/Instrumentor/load_store_gpu_ind.json
@@ -0,0 +1,111 @@
+{
+  "configuration": {
+    "runtime_prefix": "__instrumentor_",
+    "runtime_prefix.description": "The runtime API prefix.",
+    "runtime_stubs_file": "",
+    "runtime_stubs_file.description": "The file into which runtime stubs should be written.",
+    "demangle_function_names": true,
+    "demangle_function_names.description": "Demangle functions names passed to the runtime.",
+    "host_enabled": false,
+    "host_enabled.description": "Instrument non-GPU targets",
+    "gpu_enabled": true,
+    "gpu_enabled.description": "Instrument GPU targets"
+  },
+  "instruction_pre": {
+    "load": {
+      "enabled": true,
+      "pointer": true,
+      "pointer.replace": true,
+      "pointer.description": "The accessed pointer.",
+      "pointer_as": true,
+      "pointer_as.description": "The address space of the accessed pointer.",
+      "base_pointer_info": false,
+      "base_pointer_info.description": "The runtime provided base pointer info.",
+      "value_size": true,
+      "value_size.description": "The size of the loaded value.",
+      "alignment": true,
+      "alignment.description": "The known access alignment.",
+      "value_type_id": true,
+      "value_type_id.description": "The type id of the loaded value.",
+      "atomicity_ordering": true,
+      "atomicity_ordering.description": "The atomicity ordering of the load.",
+      "sync_scope_id": true,
+      "sync_scope_id.description": "The sync scope id of the load.",
+      "is_volatile": true,
+      "is_volatile.description": "Flag indicating a volatile load."
+    },
+    "store": {
+      "enabled": true,
+      "pointer": true,
+      "pointer.replace": true,
+      "pointer.description": "The accessed pointer.",
+      "pointer_as": true,
+      "pointer_as.description": "The address space of the accessed pointer.",
+      "base_pointer_info": false,
+      "base_pointer_info.description": "The runtime provided base pointer info.",
+      "value": true,
+      "value.description": "The stored value.",
+      "value_size": true,
+      "value_size.description": "The size of the stored value.",
+      "alignment": true,
+      "alignment.description": "The known access alignment.",
+      "value_type_id": true,
+      "value_type_id.description": "The type id of the stored value.",
+      "atomicity_ordering": true,
+      "atomicity_ordering.description": "The atomicity ordering of the store.",
+      "sync_scope_id": true,
+      "sync_scope_id.description": "The sync scope id of the store.",
+      "is_volatile": true,
+      "is_volatile.description": "Flag indicating a volatile store."
+    }
+  },
+  "instruction_post": {
+    "load": {
+      "enabled": true,
+      "pointer": true,
+      "pointer.description": "The accessed pointer.",
+      "pointer_as": true,
+      "pointer_as.description": "The address space of the accessed pointer.",
+      "base_pointer_info": false,
+      "base_pointer_info.description": "The runtime provided base pointer info.",
+      "value": true,
+      "value.replace": true,
+      "value.description": "The loaded value.",
+      "value_size": true,
+      "value_size.description": "The size of the loaded value.",
+      "alignment": true,
+      "alignment.description": "The known access alignment.",
+      "value_type_id": true,
+      "value_type_id.description": "The type id of the loaded value.",
+      "atomicity_ordering": true,
+      "atomicity_ordering.description": "The atomicity ordering of the load.",
+      "sync_scope_id": true,
+      "sync_scope_id.description": "The sync scope id of the load.",
+      "is_volatile": true,
+      "is_volatile.description": "Flag indicating a volatile load."
+    },
+    "store": {
+      "enabled": true,
+      "pointer": true,
+      "pointer.description": "The accessed pointer.",
+      "pointer_as": true,
+      "pointer_as.description": "The address space of the accessed pointer.",
+      "base_pointer_info": false,
+      "base_pointer_info.description": "The runtime provided base pointer info.",
+      "value": true,
+      "value.description": "The stored value.",
+      "value_size": true,
+      "value_size.description": "The size of the stored value.",
+      "alignment": true,
+      "alignment.description": "The known access alignment.",
+      "value_type_id": true,
+      "value_type_id.description": "The type id of the stored value.",
+      "atomicity_ordering": true,
+      "atomicity_ordering.description": "The atomicity ordering of the store.",
+      "sync_scope_id": true,
+      "sync_scope_id.description": "The sync scope id of the store.",
+      "is_volatile": true,
+      "is_volatile.description": "Flag indicating a volatile store."
+    }
+  }
+}

diff  --git a/llvm/test/Instrumentation/Instrumentor/load_store_gpu_ind.ll b/llvm/test/Instrumentation/Instrumentor/load_store_gpu_ind.ll
new file mode 100644
index 0000000000000..d17ac79988737
--- /dev/null
+++ b/llvm/test/Instrumentation/Instrumentor/load_store_gpu_ind.ll
@@ -0,0 +1,221 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt < %s -passes=instrumentor -instrumentor-read-config-files=%S/load_store_gpu_ind.json -S | FileCheck %s
+
+target datalayout = "e-m:e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-p7:160:256:256:32-p8:128:128:128:48-p9:192:256:256:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7:8:9"
+target triple = "amdgcn-amd-amdhsa"
+
+define noundef zeroext i1 @_Z15store_load_boolPb(ptr captures(none) noundef initializes((0, 1)) %A) {
+; CHECK-LABEL: define noundef zeroext i1 @_Z15store_load_boolPb(
+; CHECK-SAME: ptr noundef captures(none) initializes((0, 1)) [[A:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = call ptr @__instrumentor_pre_store(ptr [[A]], i32 0, i64 1, i64 1, i64 1, i32 12, i32 0, i8 1, i8 0) #[[ATTR0:[0-9]+]]
+; CHECK-NEXT:    store i8 1, ptr [[TMP0]], align 1
+; CHECK-NEXT:    call void @__instrumentor_post_store(ptr [[A]], i32 0, i64 1, i64 1, i64 1, i32 12, i32 0, i8 1, i8 0) #[[ATTR0]]
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i8, ptr [[A]], i64 1
+; CHECK-NEXT:    [[TMP1:%.*]] = call ptr @__instrumentor_pre_load(ptr [[ARRAYIDX]], i32 0, i64 1, i64 1, i32 12, i32 0, i8 1, i8 0) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 1
+; CHECK-NEXT:    [[TMP3:%.*]] = zext i8 [[TMP2]] to i64
+; CHECK-NEXT:    [[TMP4:%.*]] = call i64 @__instrumentor_post_load(ptr [[ARRAYIDX]], i32 0, i64 [[TMP3]], i64 1, i64 1, i32 12, i32 0, i8 1, i8 0) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP5:%.*]] = trunc i64 [[TMP4]] to i8
+; CHECK-NEXT:    [[LOADEDV:%.*]] = trunc nuw i8 [[TMP5]] to i1
+; CHECK-NEXT:    ret i1 [[LOADEDV]]
+;
+entry:
+  store i8 1, ptr %A, align 1
+  %arrayidx = getelementptr inbounds nuw i8, ptr %A, i64 1
+  %0 = load i8, ptr %arrayidx, align 1
+  %loadedv = trunc nuw i8 %0 to i1
+  ret i1 %loadedv
+}
+
+
+define noundef signext i8 @_Z15store_load_charPc(ptr captures(none) noundef initializes((0, 1)) %A) {
+; CHECK-LABEL: define noundef signext i8 @_Z15store_load_charPc(
+; CHECK-SAME: ptr noundef captures(none) initializes((0, 1)) [[A:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = call ptr @__instrumentor_pre_store(ptr [[A]], i32 0, i64 1, i64 1, i64 1, i32 12, i32 0, i8 1, i8 0) #[[ATTR0]]
+; CHECK-NEXT:    store i8 1, ptr [[TMP0]], align 1
+; CHECK-NEXT:    call void @__instrumentor_post_store(ptr [[A]], i32 0, i64 1, i64 1, i64 1, i32 12, i32 0, i8 1, i8 0) #[[ATTR0]]
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i8, ptr [[A]], i64 1
+; CHECK-NEXT:    [[TMP1:%.*]] = call ptr @__instrumentor_pre_load(ptr [[ARRAYIDX]], i32 0, i64 1, i64 1, i32 12, i32 0, i8 1, i8 0) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 1
+; CHECK-NEXT:    [[TMP3:%.*]] = zext i8 [[TMP2]] to i64
+; CHECK-NEXT:    [[TMP4:%.*]] = call i64 @__instrumentor_post_load(ptr [[ARRAYIDX]], i32 0, i64 [[TMP3]], i64 1, i64 1, i32 12, i32 0, i8 1, i8 0) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP5:%.*]] = trunc i64 [[TMP4]] to i8
+; CHECK-NEXT:    ret i8 [[TMP5]]
+;
+entry:
+  store i8 1, ptr %A, align 1
+  %arrayidx = getelementptr inbounds nuw i8, ptr %A, i64 1
+  %0 = load i8, ptr %arrayidx, align 1
+  ret i8 %0
+}
+
+
+define noundef signext i16 @_Z16store_load_shortPs(ptr captures(none) noundef initializes((0, 2)) %A) {
+; CHECK-LABEL: define noundef signext i16 @_Z16store_load_shortPs(
+; CHECK-SAME: ptr noundef captures(none) initializes((0, 2)) [[A:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = call ptr @__instrumentor_pre_store(ptr [[A]], i32 0, i64 2, i64 2, i64 2, i32 12, i32 0, i8 1, i8 0) #[[ATTR0]]
+; CHECK-NEXT:    store i16 2, ptr [[TMP0]], align 2
+; CHECK-NEXT:    call void @__instrumentor_post_store(ptr [[A]], i32 0, i64 2, i64 2, i64 2, i32 12, i32 0, i8 1, i8 0) #[[ATTR0]]
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i8, ptr [[A]], i64 2
+; CHECK-NEXT:    [[TMP1:%.*]] = call ptr @__instrumentor_pre_load(ptr [[ARRAYIDX]], i32 0, i64 2, i64 2, i32 12, i32 0, i8 1, i8 0) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP2:%.*]] = load i16, ptr [[TMP1]], align 2
+; CHECK-NEXT:    [[TMP3:%.*]] = zext i16 [[TMP2]] to i64
+; CHECK-NEXT:    [[TMP4:%.*]] = call i64 @__instrumentor_post_load(ptr [[ARRAYIDX]], i32 0, i64 [[TMP3]], i64 2, i64 2, i32 12, i32 0, i8 1, i8 0) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP5:%.*]] = trunc i64 [[TMP4]] to i16
+; CHECK-NEXT:    ret i16 [[TMP5]]
+;
+entry:
+  store i16 2, ptr %A, align 2
+  %arrayidx = getelementptr inbounds nuw i8, ptr %A, i64 2
+  %0 = load i16, ptr %arrayidx, align 2
+  ret i16 %0
+}
+
+
+define noundef i32 @_Z14store_load_intPi(ptr captures(none) noundef initializes((0, 4)) %A) {
+; CHECK-LABEL: define noundef i32 @_Z14store_load_intPi(
+; CHECK-SAME: ptr noundef captures(none) initializes((0, 4)) [[A:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = call ptr @__instrumentor_pre_store(ptr [[A]], i32 0, i64 3, i64 4, i64 4, i32 12, i32 0, i8 1, i8 0) #[[ATTR0]]
+; CHECK-NEXT:    store i32 3, ptr [[TMP0]], align 4
+; CHECK-NEXT:    call void @__instrumentor_post_store(ptr [[A]], i32 0, i64 3, i64 4, i64 4, i32 12, i32 0, i8 1, i8 0) #[[ATTR0]]
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i8, ptr [[A]], i64 4
+; CHECK-NEXT:    [[TMP1:%.*]] = call ptr @__instrumentor_pre_load(ptr [[ARRAYIDX]], i32 0, i64 4, i64 4, i32 12, i32 0, i8 1, i8 0) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[TMP1]], align 4
+; CHECK-NEXT:    [[TMP3:%.*]] = zext i32 [[TMP2]] to i64
+; CHECK-NEXT:    [[TMP4:%.*]] = call i64 @__instrumentor_post_load(ptr [[ARRAYIDX]], i32 0, i64 [[TMP3]], i64 4, i64 4, i32 12, i32 0, i8 1, i8 0) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP5:%.*]] = trunc i64 [[TMP4]] to i32
+; CHECK-NEXT:    ret i32 [[TMP5]]
+;
+entry:
+  store i32 3, ptr %A, align 4
+  %arrayidx = getelementptr inbounds nuw i8, ptr %A, i64 4
+  %0 = load i32, ptr %arrayidx, align 4
+  ret i32 %0
+}
+
+
+define noundef i64 @_Z15store_load_longPl(ptr captures(none) noundef initializes((0, 8)) %A) {
+; CHECK-LABEL: define noundef i64 @_Z15store_load_longPl(
+; CHECK-SAME: ptr noundef captures(none) initializes((0, 8)) [[A:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = call ptr @__instrumentor_pre_store(ptr [[A]], i32 0, i64 4, i64 8, i64 8, i32 12, i32 0, i8 1, i8 0) #[[ATTR0]]
+; CHECK-NEXT:    store i64 4, ptr [[TMP0]], align 8
+; CHECK-NEXT:    call void @__instrumentor_post_store(ptr [[A]], i32 0, i64 4, i64 8, i64 8, i32 12, i32 0, i8 1, i8 0) #[[ATTR0]]
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i8, ptr [[A]], i64 8
+; CHECK-NEXT:    [[TMP1:%.*]] = call ptr @__instrumentor_pre_load(ptr [[ARRAYIDX]], i32 0, i64 8, i64 8, i32 12, i32 0, i8 1, i8 0) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 8
+; CHECK-NEXT:    [[TMP3:%.*]] = call i64 @__instrumentor_post_load(ptr [[ARRAYIDX]], i32 0, i64 [[TMP2]], i64 8, i64 8, i32 12, i32 0, i8 1, i8 0) #[[ATTR0]]
+; CHECK-NEXT:    ret i64 [[TMP3]]
+;
+entry:
+  store i64 4, ptr %A, align 8
+  %arrayidx = getelementptr inbounds nuw i8, ptr %A, i64 8
+  %0 = load i64, ptr %arrayidx, align 8
+  ret i64 %0
+}
+
+
+define noundef i128 @_Z20store_load_long_longPx(ptr captures(none) noundef initializes((0, 16)) %A) {
+; CHECK-LABEL: define noundef i128 @_Z20store_load_long_longPx(
+; CHECK-SAME: ptr noundef captures(none) initializes((0, 16)) [[A:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = alloca i128, align 8, addrspace(5)
+; CHECK-NEXT:    store i128 5, ptr addrspace(5) [[TMP0]], align 8
+; CHECK-NEXT:    [[TMP1:%.*]] = addrspacecast ptr addrspace(5) [[TMP0]] to ptr
+; CHECK-NEXT:    [[TMP2:%.*]] = call ptr @__instrumentor_pre_store_ind(ptr [[A]], i32 0, ptr [[TMP1]], i64 16, i64 8, i32 12, i32 0, i8 1, i8 0) #[[ATTR0]]
+; CHECK-NEXT:    store i128 5, ptr [[TMP2]], align 8
+; CHECK-NEXT:    call void @__instrumentor_post_store_ind(ptr [[A]], i32 0, ptr [[TMP1]], i64 16, i64 8, i32 12, i32 0, i8 1, i8 0) #[[ATTR0]]
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i8, ptr [[A]], i64 16
+; CHECK-NEXT:    [[TMP3:%.*]] = call ptr @__instrumentor_pre_load(ptr [[ARRAYIDX]], i32 0, i64 16, i64 8, i32 12, i32 0, i8 1, i8 0) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP6:%.*]] = load i128, ptr [[TMP3]], align 8
+; CHECK-NEXT:    store i128 [[TMP6]], ptr addrspace(5) [[TMP0]], align 8
+; CHECK-NEXT:    [[TMP5:%.*]] = addrspacecast ptr addrspace(5) [[TMP0]] to ptr
+; CHECK-NEXT:    call void @__instrumentor_post_load_ind(ptr [[ARRAYIDX]], i32 0, ptr [[TMP5]], i64 16, i64 8, i32 12, i32 0, i8 1, i8 0) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP4:%.*]] = load i128, ptr [[TMP5]], align 8
+; CHECK-NEXT:    ret i128 [[TMP4]]
+;
+entry:
+  store i128 5, ptr %A, align 8
+  %arrayidx = getelementptr inbounds nuw i8, ptr %A, i64 16
+  %0 = load i128, ptr %arrayidx, align 8
+  ret i128 %0
+}
+
+
+define noundef float @_Z16store_load_floatPf(ptr captures(none) noundef initializes((0, 4)) %A) {
+; CHECK-LABEL: define noundef float @_Z16store_load_floatPf(
+; CHECK-SAME: ptr noundef captures(none) initializes((0, 4)) [[A:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = call ptr @__instrumentor_pre_store(ptr [[A]], i32 0, i64 1086324736, i64 4, i64 4, i32 2, i32 0, i8 1, i8 0) #[[ATTR0]]
+; CHECK-NEXT:    store float 6.000000e+00, ptr [[TMP0]], align 4
+; CHECK-NEXT:    call void @__instrumentor_post_store(ptr [[A]], i32 0, i64 1086324736, i64 4, i64 4, i32 2, i32 0, i8 1, i8 0) #[[ATTR0]]
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i8, ptr [[A]], i64 4
+; CHECK-NEXT:    [[TMP1:%.*]] = call ptr @__instrumentor_pre_load(ptr [[ARRAYIDX]], i32 0, i64 4, i64 4, i32 2, i32 0, i8 1, i8 0) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP2:%.*]] = load float, ptr [[TMP1]], align 4
+; CHECK-NEXT:    [[TMP3:%.*]] = bitcast float [[TMP2]] to i32
+; CHECK-NEXT:    [[TMP4:%.*]] = zext i32 [[TMP3]] to i64
+; CHECK-NEXT:    [[TMP5:%.*]] = call i64 @__instrumentor_post_load(ptr [[ARRAYIDX]], i32 0, i64 [[TMP4]], i64 4, i64 4, i32 2, i32 0, i8 1, i8 0) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP6:%.*]] = trunc i64 [[TMP5]] to i32
+; CHECK-NEXT:    [[TMP7:%.*]] = bitcast i32 [[TMP6]] to float
+; CHECK-NEXT:    ret float [[TMP7]]
+;
+entry:
+  store float 6.000000e+00, ptr %A, align 4
+  %arrayidx = getelementptr inbounds nuw i8, ptr %A, i64 4
+  %0 = load float, ptr %arrayidx, align 4
+  ret float %0
+}
+
+
+define noundef double @_Z17store_load_doublePd(ptr captures(none) noundef initializes((0, 8)) %A) {
+; CHECK-LABEL: define noundef double @_Z17store_load_doublePd(
+; CHECK-SAME: ptr noundef captures(none) initializes((0, 8)) [[A:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = call ptr @__instrumentor_pre_store(ptr [[A]], i32 0, i64 4619567317775286272, i64 8, i64 8, i32 3, i32 0, i8 1, i8 0) #[[ATTR0]]
+; CHECK-NEXT:    store double 7.000000e+00, ptr [[TMP0]], align 8
+; CHECK-NEXT:    call void @__instrumentor_post_store(ptr [[A]], i32 0, i64 4619567317775286272, i64 8, i64 8, i32 3, i32 0, i8 1, i8 0) #[[ATTR0]]
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i8, ptr [[A]], i64 8
+; CHECK-NEXT:    [[TMP1:%.*]] = call ptr @__instrumentor_pre_load(ptr [[ARRAYIDX]], i32 0, i64 8, i64 8, i32 3, i32 0, i8 1, i8 0) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP2:%.*]] = load double, ptr [[TMP1]], align 8
+; CHECK-NEXT:    [[TMP3:%.*]] = bitcast double [[TMP2]] to i64
+; CHECK-NEXT:    [[TMP4:%.*]] = call i64 @__instrumentor_post_load(ptr [[ARRAYIDX]], i32 0, i64 [[TMP3]], i64 8, i64 8, i32 3, i32 0, i8 1, i8 0) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP5:%.*]] = bitcast i64 [[TMP4]] to double
+; CHECK-NEXT:    ret double [[TMP5]]
+;
+entry:
+  store double 7.000000e+00, ptr %A, align 8
+  %arrayidx = getelementptr inbounds nuw i8, ptr %A, i64 8
+  %0 = load double, ptr %arrayidx, align 8
+  ret double %0
+}
+
+
+define <4 x i8> @store_load_vec4i8(ptr captures(none) noundef initializes((0, 4)) %A) {
+; CHECK-LABEL: define <4 x i8> @store_load_vec4i8(
+; CHECK-SAME: ptr noundef captures(none) initializes((0, 4)) [[A:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = alloca <4 x i8>, align 4, addrspace(5)
+; CHECK-NEXT:    store <4 x i8> <i8 1, i8 2, i8 3, i8 4>, ptr addrspace(5) [[TMP0]], align 4
+; CHECK-NEXT:    [[TMP1:%.*]] = addrspacecast ptr addrspace(5) [[TMP0]] to ptr
+; CHECK-NEXT:    [[TMP2:%.*]] = call ptr @__instrumentor_pre_store_ind(ptr [[A]], i32 0, ptr [[TMP1]], i64 4, i64 1, i32 18, i32 0, i8 1, i8 0) #[[ATTR0]]
+; CHECK-NEXT:    store <4 x i8> <i8 1, i8 2, i8 3, i8 4>, ptr [[TMP2]], align 1
+; CHECK-NEXT:    call void @__instrumentor_post_store_ind(ptr [[A]], i32 0, ptr [[TMP1]], i64 4, i64 1, i32 18, i32 0, i8 1, i8 0) #[[ATTR0]]
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i8, ptr [[A]], i64 4
+; CHECK-NEXT:    [[TMP3:%.*]] = call ptr @__instrumentor_pre_load(ptr [[ARRAYIDX]], i32 0, i64 4, i64 1, i32 18, i32 0, i8 1, i8 0) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP4:%.*]] = load <4 x i8>, ptr [[TMP3]], align 1
+; CHECK-NEXT:    store <4 x i8> [[TMP4]], ptr addrspace(5) [[TMP0]], align 4
+; CHECK-NEXT:    [[TMP5:%.*]] = addrspacecast ptr addrspace(5) [[TMP0]] to ptr
+; CHECK-NEXT:    call void @__instrumentor_post_load_ind(ptr [[ARRAYIDX]], i32 0, ptr [[TMP5]], i64 4, i64 1, i32 18, i32 0, i8 1, i8 0) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP6:%.*]] = load <4 x i8>, ptr [[TMP5]], align 4
+; CHECK-NEXT:    ret <4 x i8> [[TMP6]]
+;
+entry:
+  store <4 x i8> <i8 1, i8 2, i8 3, i8 4>, ptr %A, align 1
+  %arrayidx = getelementptr inbounds nuw i8, ptr %A, i64 4
+  %0 = load <4 x i8>, ptr %arrayidx, align 1
+  ret <4 x i8> %0
+}


        


More information about the llvm-commits mailing list