[llvm] c7aacbb - [ArgPromotion] Update allocsize indices after promotion

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 18 07:15:40 PDT 2023


Author: Nikita Popov
Date: 2023-09-18T16:15:16+02:00
New Revision: c7aacbb5b6f272e3bf574120805f9ffb90633eb6

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

LOG: [ArgPromotion] Update allocsize indices after promotion

Promotion can add/remove arguments. We need to update the
indices in the allocsize attribute accordingly.

Fixes https://github.com/llvm/llvm-project/issues/66103.

Added: 
    llvm/test/Transforms/ArgumentPromotion/allocsize.ll

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

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp b/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp
index 824da6395f2e53f..db9d5bc5a2cd2f3 100644
--- a/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp
+++ b/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp
@@ -121,19 +121,24 @@ doPromotion(Function *F, FunctionAnalysisManager &FAM,
   // that we are *not* promoting. For the ones that we do promote, the parameter
   // attributes are lost
   SmallVector<AttributeSet, 8> ArgAttrVec;
+  // Mapping from old to new argument indices. -1 for promoted or removed
+  // arguments.
+  SmallVector<unsigned> NewArgIndices;
   AttributeList PAL = F->getAttributes();
 
   // First, determine the new argument list
-  unsigned ArgNo = 0;
+  unsigned ArgNo = 0, NewArgNo = 0;
   for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E;
        ++I, ++ArgNo) {
     if (!ArgsToPromote.count(&*I)) {
       // Unchanged argument
       Params.push_back(I->getType());
       ArgAttrVec.push_back(PAL.getParamAttrs(ArgNo));
+      NewArgIndices.push_back(NewArgNo++);
     } else if (I->use_empty()) {
       // Dead argument (which are always marked as promotable)
       ++NumArgumentsDead;
+      NewArgIndices.push_back((unsigned)-1);
     } else {
       const auto &ArgParts = ArgsToPromote.find(&*I)->second;
       for (const auto &Pair : ArgParts) {
@@ -141,6 +146,8 @@ doPromotion(Function *F, FunctionAnalysisManager &FAM,
         ArgAttrVec.push_back(AttributeSet());
       }
       ++NumArgumentsPromoted;
+      NewArgIndices.push_back((unsigned)-1);
+      NewArgNo += ArgParts.size();
     }
   }
 
@@ -173,6 +180,19 @@ doPromotion(Function *F, FunctionAnalysisManager &FAM,
   // the function.
   NF->setAttributes(AttributeList::get(F->getContext(), PAL.getFnAttrs(),
                                        PAL.getRetAttrs(), ArgAttrVec));
+
+  // Remap argument indices in allocsize attribute.
+  if (auto AllocSize = NF->getAttributes().getFnAttrs().getAllocSizeArgs()) {
+    unsigned Arg1 = NewArgIndices[AllocSize->first];
+    assert(Arg1 != (unsigned)-1 && "allocsize cannot be promoted argument");
+    std::optional<unsigned> Arg2;
+    if (AllocSize->second) {
+      Arg2 = NewArgIndices[*AllocSize->second];
+      assert(Arg2 != (unsigned)-1 && "allocsize cannot be promoted argument");
+    }
+    NF->addFnAttr(Attribute::getWithAllocSizeArgs(F->getContext(), Arg1, Arg2));
+  }
+
   AttributeFuncs::updateMinLegalVectorWidthAttr(*NF, LargestVectorWidth);
   ArgAttrVec.clear();
 

diff  --git a/llvm/test/Transforms/ArgumentPromotion/allocsize.ll b/llvm/test/Transforms/ArgumentPromotion/allocsize.ll
new file mode 100644
index 000000000000000..36271e17c9d76d4
--- /dev/null
+++ b/llvm/test/Transforms/ArgumentPromotion/allocsize.ll
@@ -0,0 +1,94 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-attributes --version 3
+; RUN: opt -S -passes=argpromotion < %s | FileCheck %s
+
+declare ptr @malloc(i64)
+declare ptr @calloc(i64, i64)
+
+define internal ptr @my_alloc1(i64 %unchanged, ptr %unused, i64 %size, ptr %unused2) allocsize(2) {
+; CHECK: Function Attrs: allocsize(1)
+; CHECK-LABEL: define internal ptr @my_alloc1(
+; CHECK-SAME: i64 [[UNCHANGED:%.*]], i64 [[SIZE:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:    [[PTR:%.*]] = call ptr @malloc(i64 [[SIZE]])
+; CHECK-NEXT:    ret ptr [[PTR]]
+;
+  %ptr = call ptr @malloc(i64 %size)
+  ret ptr %ptr
+}
+
+define internal ptr @my_alloc2(i64 %unchanged, ptr %unused, i64 %size, i64 %size2, ptr %unused2) allocsize(2,3) {
+; CHECK: Function Attrs: allocsize(1,2)
+; CHECK-LABEL: define internal ptr @my_alloc2(
+; CHECK-SAME: i64 [[UNCHANGED:%.*]], i64 [[SIZE:%.*]], i64 [[SIZE2:%.*]]) #[[ATTR1:[0-9]+]] {
+; CHECK-NEXT:    [[PTR:%.*]] = call ptr @calloc(i64 [[SIZE]], i64 [[SIZE2]])
+; CHECK-NEXT:    ret ptr [[PTR]]
+;
+  %ptr = call ptr @calloc(i64 %size, i64 %size2)
+  ret ptr %ptr
+}
+
+define internal ptr @my_alloc3(i64 %unchanged, ptr %promoted, ptr %promoted2, i64 %size) allocsize(3) {
+; CHECK: Function Attrs: allocsize(5)
+; CHECK-LABEL: define internal ptr @my_alloc3(
+; CHECK-SAME: i64 [[UNCHANGED:%.*]], i32 [[PROMOTED_0_VAL:%.*]], i32 [[PROMOTED_4_VAL:%.*]], i32 [[PROMOTED2_0_VAL:%.*]], i32 [[PROMOTED2_4_VAL:%.*]], i64 [[SIZE:%.*]]) #[[ATTR2:[0-9]+]] {
+; CHECK-NEXT:    [[PTR:%.*]] = call ptr @malloc(i64 [[SIZE]])
+; CHECK-NEXT:    ret ptr [[PTR]]
+;
+  load i32, ptr %promoted
+  %promoted.gep1 = getelementptr i8, ptr %promoted, i64 4
+  load i32, ptr %promoted.gep1
+
+  load i32, ptr %promoted2
+  %promoted2.gep1 = getelementptr i8, ptr %promoted2, i64 4
+  load i32, ptr %promoted2.gep1
+
+  %ptr = call ptr @malloc(i64 %size)
+  ret ptr %ptr
+}
+
+define internal ptr @my_alloc4(i64 %unchanged, ptr %promoted, ptr %promoted2, i64 %size, i64 %size2) allocsize(3,4) {
+; CHECK: Function Attrs: allocsize(5,6)
+; CHECK-LABEL: define internal ptr @my_alloc4(
+; CHECK-SAME: i64 [[UNCHANGED:%.*]], i32 [[PROMOTED_0_VAL:%.*]], i32 [[PROMOTED_4_VAL:%.*]], i32 [[PROMOTED2_0_VAL:%.*]], i32 [[PROMOTED2_4_VAL:%.*]], i64 [[SIZE:%.*]], i64 [[SIZE2:%.*]]) #[[ATTR3:[0-9]+]] {
+; CHECK-NEXT:    [[PTR:%.*]] = call ptr @calloc(i64 [[SIZE]], i64 [[SIZE2]])
+; CHECK-NEXT:    ret ptr [[PTR]]
+;
+  load i32, ptr %promoted
+  %promoted.gep1 = getelementptr i8, ptr %promoted, i64 4
+  load i32, ptr %promoted.gep1
+
+  load i32, ptr %promoted2
+  %promoted2.gep1 = getelementptr i8, ptr %promoted2, i64 4
+  load i32, ptr %promoted2.gep1
+
+  %ptr = call ptr @calloc(i64 %size, i64 %size2)
+  ret ptr %ptr
+}
+
+define void @call_my_alloc(ptr %arg, ptr %arg2) {
+; CHECK-LABEL: define void @call_my_alloc(
+; CHECK-SAME: ptr [[ARG:%.*]], ptr [[ARG2:%.*]]) {
+; CHECK-NEXT:    [[TMP1:%.*]] = call ptr @my_alloc1(i64 0, i64 2)
+; CHECK-NEXT:    [[TMP2:%.*]] = call ptr @my_alloc2(i64 0, i64 2, i64 2)
+; CHECK-NEXT:    [[ARG_VAL:%.*]] = load i32, ptr [[ARG]], align 4
+; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr i8, ptr [[ARG]], i64 4
+; CHECK-NEXT:    [[ARG_VAL1:%.*]] = load i32, ptr [[TMP3]], align 4
+; CHECK-NEXT:    [[ARG2_VAL:%.*]] = load i32, ptr [[ARG2]], align 4
+; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr i8, ptr [[ARG2]], i64 4
+; CHECK-NEXT:    [[ARG2_VAL2:%.*]] = load i32, ptr [[TMP4]], align 4
+; CHECK-NEXT:    [[TMP5:%.*]] = call ptr @my_alloc3(i64 0, i32 [[ARG_VAL]], i32 [[ARG_VAL1]], i32 [[ARG2_VAL]], i32 [[ARG2_VAL2]], i64 2)
+; CHECK-NEXT:    [[ARG_VAL3:%.*]] = load i32, ptr [[ARG]], align 4
+; CHECK-NEXT:    [[TMP6:%.*]] = getelementptr i8, ptr [[ARG]], i64 4
+; CHECK-NEXT:    [[ARG_VAL4:%.*]] = load i32, ptr [[TMP6]], align 4
+; CHECK-NEXT:    [[ARG2_VAL5:%.*]] = load i32, ptr [[ARG2]], align 4
+; CHECK-NEXT:    [[TMP7:%.*]] = getelementptr i8, ptr [[ARG2]], i64 4
+; CHECK-NEXT:    [[ARG2_VAL6:%.*]] = load i32, ptr [[TMP7]], align 4
+; CHECK-NEXT:    [[TMP8:%.*]] = call ptr @my_alloc4(i64 0, i32 [[ARG_VAL3]], i32 [[ARG_VAL4]], i32 [[ARG2_VAL5]], i32 [[ARG2_VAL6]], i64 2, i64 2)
+; CHECK-NEXT:    ret void
+;
+  %ptr = call ptr @my_alloc1(i64 0, ptr null, i64 2, ptr null)
+  %ptr2 = call ptr @my_alloc2(i64 0, ptr null, i64 2, i64 2, ptr null)
+  %ptr3 = call ptr @my_alloc3(i64 0, ptr %arg, ptr %arg2, i64 2)
+  %ptr4 = call ptr @my_alloc4(i64 0, ptr %arg, ptr %arg2, i64 2, i64 2)
+  ret void
+}
+


        


More information about the llvm-commits mailing list