[llvm] 15cd90a - [Attributor][FIX] Make value simplification aware of "complicated" attributes

Johannes Doerfert via llvm-commits llvm-commits at lists.llvm.org
Fri Nov 1 22:30:23 PDT 2019


Author: Johannes Doerfert
Date: 2019-11-02T00:29:17-05:00
New Revision: 15cd90a2c44aacbab1fe8682b8c07101ccffb9c4

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

LOG: [Attributor][FIX] Make value simplification aware of "complicated" attributes

We cannot simply replace arguments that carry attributes like `nest`,
`inalloca`, `sret`, and `byval`. Except for the last one, which we can
replace if it is not written, we bail for now.

Added: 
    

Modified: 
    llvm/lib/Transforms/IPO/Attributor.cpp
    llvm/test/Transforms/FunctionAttrs/value-simplify.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp
index ddd2ff076e11..9fdfed8dbedb 100644
--- a/llvm/lib/Transforms/IPO/Attributor.cpp
+++ b/llvm/lib/Transforms/IPO/Attributor.cpp
@@ -3628,8 +3628,26 @@ struct AAValueSimplifyImpl : AAValueSimplify {
 struct AAValueSimplifyArgument final : AAValueSimplifyImpl {
   AAValueSimplifyArgument(const IRPosition &IRP) : AAValueSimplifyImpl(IRP) {}
 
+  void initialize(Attributor &A) override {
+    AAValueSimplifyImpl::initialize(A);
+    if (!getAssociatedFunction() || getAssociatedFunction()->isDeclaration())
+      indicatePessimisticFixpoint();
+    if (hasAttr({Attribute::InAlloca, Attribute::StructRet, Attribute::Nest},
+                /* IgnoreSubsumingPositions */ true))
+      indicatePessimisticFixpoint();
+  }
+
   /// See AbstractAttribute::updateImpl(...).
   ChangeStatus updateImpl(Attributor &A) override {
+    // Byval is only replacable if it is readonly otherwise we would write into
+    // the replaced value and not the copy that byval creates implicitly.
+    Argument *Arg = getAssociatedArgument();
+    if (Arg->hasByValAttr()) {
+      const auto &MemAA = A.getAAFor<AAMemoryBehavior>(*this, getIRPosition());
+      if (!MemAA.isAssumedReadOnly())
+        return indicatePessimisticFixpoint();
+    }
+
     bool HasValueBefore = SimplifiedAssociatedValue.hasValue();
 
     auto PredForCallSite = [&](AbstractCallSite ACS) {

diff  --git a/llvm/test/Transforms/FunctionAttrs/value-simplify.ll b/llvm/test/Transforms/FunctionAttrs/value-simplify.ll
index d4bb070f4978..92d0fbd0c1d5 100644
--- a/llvm/test/Transforms/FunctionAttrs/value-simplify.ll
+++ b/llvm/test/Transforms/FunctionAttrs/value-simplify.ll
@@ -1,6 +1,10 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
 ; RUN: opt -attributor --attributor-disable=false -attributor-annotate-decl-cs -S < %s | FileCheck %s
 ; TODO: Add max-iteration check
+
+; Disable update test checks and enable it where required.
+; UTC_ARGS: --turn off
+
 ; ModuleID = 'value-simplify.ll'
 source_filename = "value-simplify.ll"
 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
@@ -192,3 +196,81 @@ define i32 @ipccp3() {
   %r = call i32 @ipccp3i(i32 7)
   ret i32 %r
 }
+
+; UTC_ARGS: --turn on
+
+; Do not touch complicated arguments (for now)
+%struct.X = type { i8* }
+define internal i32* @test_inalloca(i32* inalloca %a) {
+; CHECK-LABEL: define {{[^@]+}}@test_inalloca
+; CHECK-SAME: (i32* inalloca noalias returned writeonly [[A:%.*]])
+; CHECK-NEXT:    ret i32* [[A]]
+;
+  ret i32* %a
+}
+define i32* @complicated_args_inalloca() {
+; CHECK-LABEL: define {{[^@]+}}@complicated_args_inalloca()
+; CHECK-NEXT:    [[CALL:%.*]] = call i32* @test_inalloca(i32* noalias null)
+; CHECK-NEXT:    ret i32* [[CALL]]
+;
+  %call = call i32* @test_inalloca(i32* null)
+  ret i32* %call
+}
+
+define internal void @test_sret(%struct.X* sret %a, %struct.X** %b) {
+; CHECK-LABEL: define {{[^@]+}}@test_sret
+; CHECK-SAME: (%struct.X* sret writeonly [[A:%.*]], %struct.X** nocapture nonnull writeonly dereferenceable(8) [[B:%.*]])
+; CHECK-NEXT:    store %struct.X* [[A]], %struct.X** [[B]]
+; CHECK-NEXT:    ret void
+;
+  store %struct.X* %a, %struct.X** %b
+  ret void
+}
+define void @complicated_args_sret(%struct.X** %b) {
+; CHECK-LABEL: define {{[^@]+}}@complicated_args_sret
+; CHECK-SAME: (%struct.X** nocapture writeonly [[B:%.*]])
+; CHECK-NEXT:    call void @test_sret(%struct.X* null, %struct.X** nocapture writeonly [[B]])
+; CHECK-NEXT:    ret void
+;
+  call void @test_sret(%struct.X* null, %struct.X** %b)
+  ret void
+}
+
+define internal %struct.X* @test_nest(%struct.X* nest %a) {
+; CHECK-LABEL: define {{[^@]+}}@test_nest
+; CHECK-SAME: (%struct.X* nest noalias readnone returned [[A:%.*]])
+; CHECK-NEXT:    ret %struct.X* [[A]]
+;
+  ret %struct.X* %a
+}
+define %struct.X* @complicated_args_nest() {
+; CHECK-LABEL: define {{[^@]+}}@complicated_args_nest()
+; CHECK-NEXT:    [[CALL:%.*]] = call %struct.X* @test_nest(%struct.X* noalias null)
+; CHECK-NEXT:    ret %struct.X* [[CALL]]
+;
+  %call = call %struct.X* @test_nest(%struct.X* null)
+  ret %struct.X* %call
+}
+
+ at S = external global %struct.X
+define internal void @test_byval(%struct.X* byval %a) {
+; CHECK-LABEL: define {{[^@]+}}@test_byval
+; CHECK-SAME: (%struct.X* nocapture nonnull writeonly byval align 8 dereferenceable(8) [[A:%.*]])
+; CHECK-NEXT:    [[G0:%.*]] = getelementptr [[STRUCT_X:%.*]], %struct.X* [[A]], i32 0, i32 0
+; CHECK-NEXT:    store i8* null, i8** [[G0]], align 8
+; CHECK-NEXT:    ret void
+;
+  %g0 = getelementptr %struct.X, %struct.X* %a, i32 0, i32 0
+  store i8* null, i8** %g0
+  ret void
+}
+define void @complicated_args_byval() {
+; CHECK-LABEL: define {{[^@]+}}@complicated_args_byval()
+; CHECK-NEXT:    call void @test_byval(%struct.X* nonnull align 8 dereferenceable(8) @S)
+; CHECK-NEXT:    ret void
+;
+  call void @test_byval(%struct.X* @S)
+  ret void
+}
+
+; UTC_ARGS: --turn off


        


More information about the llvm-commits mailing list