[llvm] 8afb643 - [SimplifyCFG] Select the first instruction that we can handle in `passingValueIsAlwaysUndefined` (#98802)

via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 16 04:06:46 PDT 2024


Author: DianQK
Date: 2024-07-16T19:06:32+08:00
New Revision: 8afb6432c239a3f5502c5014ebab6b372d7b3d50

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

LOG: [SimplifyCFG] Select the first instruction that we can handle in `passingValueIsAlwaysUndefined` (#98802)

Fixes #98799.

Added: 
    llvm/test/Transforms/PhaseOrdering/pr98799-inline-simplifycfg-ub.ll

Modified: 
    llvm/lib/Transforms/Utils/SimplifyCFG.cpp
    llvm/test/Transforms/SimplifyCFG/UnreachableEliminate.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 3fa3c0f1f52b0..8f717cb43bcb4 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -7573,11 +7573,31 @@ static bool passingValueIsAlwaysUndefined(Value *V, Instruction *I, bool PtrValu
     return false;
 
   if (C->isNullValue() || isa<UndefValue>(C)) {
-    // Only look at the first use, avoid hurting compile time with long uselists
-    auto *Use = cast<Instruction>(*I->user_begin());
+    // Only look at the first use we can handle, avoid hurting compile time with
+    // long uselists
+    auto FindUse = llvm::find_if(I->users(), [](auto *U) {
+      auto *Use = cast<Instruction>(U);
+      // Change this list when we want to add new instructions.
+      switch (Use->getOpcode()) {
+      default:
+        return false;
+      case Instruction::GetElementPtr:
+      case Instruction::Ret:
+      case Instruction::BitCast:
+      case Instruction::Load:
+      case Instruction::Store:
+      case Instruction::Call:
+      case Instruction::CallBr:
+      case Instruction::Invoke:
+        return true;
+      }
+    });
+    if (FindUse == I->user_end())
+      return false;
+    auto *Use = cast<Instruction>(*FindUse);
     // Bail out if Use is not in the same BB as I or Use == I or Use comes
-    // before I in the block. The latter two can be the case if Use is a PHI
-    // node.
+    // before I in the block. The latter two can be the case if Use is a
+    // PHI node.
     if (Use->getParent() != I->getParent() || Use == I || Use->comesBefore(I))
       return false;
 

diff  --git a/llvm/test/Transforms/PhaseOrdering/pr98799-inline-simplifycfg-ub.ll b/llvm/test/Transforms/PhaseOrdering/pr98799-inline-simplifycfg-ub.ll
new file mode 100644
index 0000000000000..17073fa198202
--- /dev/null
+++ b/llvm/test/Transforms/PhaseOrdering/pr98799-inline-simplifycfg-ub.ll
@@ -0,0 +1,56 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt < %s -passes=inline,simplifycfg -S | FileCheck --check-prefix=CUSTOM %s
+; RUN: opt < %s -O2 -S | FileCheck --check-prefix=O2 %s
+
+define internal ptr @bar(ptr %arg, i1 %arg1) {
+bb:
+  br i1 %arg1, label %bb4, label %bb2
+
+bb2:
+  %i = load ptr, ptr %arg, align 8
+  %i3 = getelementptr inbounds i8, ptr %i, i64 1
+  store ptr %i3, ptr %arg, align 8
+  br label %bb4
+
+bb4:
+  %i5 = phi ptr [ %i, %bb2 ], [ null, %bb ]
+  ret ptr %i5
+}
+
+define i32 @foo(ptr %arg, i1 %arg1) {
+; CUSTOM-LABEL: define i32 @foo(
+; CUSTOM-SAME: ptr [[ARG:%.*]], i1 [[ARG1:%.*]]) {
+; CUSTOM-NEXT:  [[BB:.*:]]
+; CUSTOM-NEXT:    [[TMP0:%.*]] = xor i1 [[ARG1]], true
+; CUSTOM-NEXT:    call void @llvm.assume(i1 [[TMP0]])
+; CUSTOM-NEXT:    [[I_I:%.*]] = load ptr, ptr [[ARG]], align 8
+; CUSTOM-NEXT:    [[I3_I:%.*]] = getelementptr inbounds i8, ptr [[I_I]], i64 1
+; CUSTOM-NEXT:    store ptr [[I3_I]], ptr [[ARG]], align 8
+; CUSTOM-NEXT:    [[I2:%.*]] = icmp ne ptr [[I_I]], null
+; CUSTOM-NEXT:    call void @llvm.assume(i1 [[I2]])
+; CUSTOM-NEXT:    [[I3:%.*]] = load i32, ptr [[I_I]], align 4
+; CUSTOM-NEXT:    ret i32 [[I3]]
+;
+; O2-LABEL: define i32 @foo(
+; O2-SAME: ptr nocapture [[ARG:%.*]], i1 [[ARG1:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+; O2-NEXT:  [[BB:.*:]]
+; O2-NEXT:    [[TMP0:%.*]] = xor i1 [[ARG1]], true
+; O2-NEXT:    tail call void @llvm.assume(i1 [[TMP0]])
+; O2-NEXT:    [[I_I:%.*]] = load ptr, ptr [[ARG]], align 8, !nonnull [[META0:![0-9]+]], !noundef [[META0]]
+; O2-NEXT:    [[I3_I:%.*]] = getelementptr inbounds i8, ptr [[I_I]], i64 1
+; O2-NEXT:    store ptr [[I3_I]], ptr [[ARG]], align 8
+; O2-NEXT:    [[I3:%.*]] = load i32, ptr [[I_I]], align 4
+; O2-NEXT:    ret i32 [[I3]]
+;
+bb:
+  %i = call ptr @bar(ptr %arg, i1 %arg1)
+  %i2 = icmp ne ptr %i, null
+  call void @llvm.assume(i1 %i2)
+  %i3 = load i32, ptr %i, align 4
+  ret i32 %i3
+}
+
+declare void @llvm.assume(i1)
+;.
+; O2: [[META0]] = !{}
+;.

diff  --git a/llvm/test/Transforms/SimplifyCFG/UnreachableEliminate.ll b/llvm/test/Transforms/SimplifyCFG/UnreachableEliminate.ll
index ef2d3219cca9b..c4602e72ecbce 100644
--- a/llvm/test/Transforms/SimplifyCFG/UnreachableEliminate.ll
+++ b/llvm/test/Transforms/SimplifyCFG/UnreachableEliminate.ll
@@ -20,7 +20,7 @@ F:
 define void @test2() personality ptr @__gxx_personality_v0 {
 ; CHECK-LABEL: @test2(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    call void @test2() #[[ATTR3:[0-9]+]]
+; CHECK-NEXT:    call void @test2() #[[ATTR4:[0-9]+]]
 ; CHECK-NEXT:    ret void
 ;
 entry:
@@ -242,6 +242,8 @@ declare ptr @fn_nonnull_deref_arg(ptr nonnull dereferenceable(4) %p)
 declare ptr @fn_nonnull_deref_or_null_arg(ptr nonnull dereferenceable_or_null(4) %p)
 declare ptr @fn_nonnull_arg(ptr nonnull %p)
 declare ptr @fn_noundef_arg(ptr noundef %p)
+declare ptr @fn_ptr_arg(ptr)
+declare ptr @fn_ptr_arg_nounwind_willreturn(ptr) nounwind willreturn
 
 define void @test9(i1 %X, ptr %Y) {
 ; CHECK-LABEL: @test9(
@@ -855,10 +857,72 @@ exit:
   ret i32 %res
 }
 
+; From bb to bb5 is UB.
+define i32 @test9_null_user_order_1(ptr %arg, i1 %arg1, ptr %arg2) {
+; CHECK-LABEL: @test9_null_user_order_1(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[ARG1:%.*]], true
+; CHECK-NEXT:    call void @llvm.assume(i1 [[TMP0]])
+; CHECK-NEXT:    [[I:%.*]] = load ptr, ptr [[ARG:%.*]], align 8
+; CHECK-NEXT:    [[I4:%.*]] = getelementptr inbounds i8, ptr [[I]], i64 1
+; CHECK-NEXT:    store ptr [[I4]], ptr [[ARG]], align 8
+; CHECK-NEXT:    [[I7:%.*]] = load i32, ptr [[I]], align 4
+; CHECK-NEXT:    [[I8:%.*]] = icmp ne ptr [[I]], [[ARG2:%.*]]
+; CHECK-NEXT:    call void @fn_ptr_arg(i1 [[I8]])
+; CHECK-NEXT:    ret i32 [[I7]]
+;
+bb:
+  br i1 %arg1, label %bb5, label %bb3
+
+bb3:                                              ; preds = %bb
+  %i = load ptr, ptr %arg, align 8
+  %i4 = getelementptr inbounds i8, ptr %i, i64 1
+  store ptr %i4, ptr %arg, align 8
+  br label %bb5
+
+bb5:                                              ; preds = %bb3, %bb
+  %i6 = phi ptr [ %i, %bb3 ], [ null, %bb ]
+  %i7 = load i32, ptr %i6, align 4
+  %i8 = icmp ne ptr %i6, %arg2
+  call void @fn_ptr_arg(i1 %i8)
+  ret i32 %i7
+}
+
+define i32 @test9_null_user_order_2(ptr %arg, i1 %arg1, ptr %arg2) {
+; CHECK-LABEL: @test9_null_user_order_2(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[ARG1:%.*]], true
+; CHECK-NEXT:    call void @llvm.assume(i1 [[TMP0]])
+; CHECK-NEXT:    [[I:%.*]] = load ptr, ptr [[ARG:%.*]], align 8
+; CHECK-NEXT:    [[I4:%.*]] = getelementptr inbounds i8, ptr [[I]], i64 1
+; CHECK-NEXT:    store ptr [[I4]], ptr [[ARG]], align 8
+; CHECK-NEXT:    [[I8:%.*]] = icmp ne ptr [[I]], [[ARG2:%.*]]
+; CHECK-NEXT:    call void @fn_ptr_arg_nounwind_willreturn(i1 [[I8]])
+; CHECK-NEXT:    [[I7:%.*]] = load i32, ptr [[I]], align 4
+; CHECK-NEXT:    ret i32 [[I7]]
+;
+bb:
+  br i1 %arg1, label %bb5, label %bb3
+
+bb3:                                              ; preds = %bb
+  %i = load ptr, ptr %arg, align 8
+  %i4 = getelementptr inbounds i8, ptr %i, i64 1
+  store ptr %i4, ptr %arg, align 8
+  br label %bb5
+
+bb5:                                              ; preds = %bb3, %bb
+  %i6 = phi ptr [ %i, %bb3 ], [ null, %bb ]
+  %i8 = icmp ne ptr %i6, %arg2
+  call void @fn_ptr_arg_nounwind_willreturn(i1 %i8)
+  %i7 = load i32, ptr %i6, align 4
+  ret i32 %i7
+}
+
 attributes #0 = { null_pointer_is_valid }
 ;.
 ; CHECK: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }
 ; CHECK: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
 ; CHECK: attributes #[[ATTR2:[0-9]+]] = { null_pointer_is_valid }
-; CHECK: attributes #[[ATTR3]] = { nounwind }
+; CHECK: attributes #[[ATTR3:[0-9]+]] = { nounwind willreturn }
+; CHECK: attributes #[[ATTR4]] = { nounwind }
 ;.


        


More information about the llvm-commits mailing list