[llvm] 13b4d1b - [SimplifyCFG][LICM] Add additional speculation tests

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 18 05:49:08 PDT 2024


Author: Nikita Popov
Date: 2024-09-18T14:48:58+02:00
New Revision: 13b4d1bfeacc441d792557b42759f258dc4316e6

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

LOG: [SimplifyCFG][LICM] Add additional speculation tests

These are related to https://github.com/llvm/llvm-project/issues/108854.

Added: 
    llvm/test/Transforms/SimplifyCFG/speculate-derefable-load.ll

Modified: 
    llvm/test/Transforms/LICM/hoist-deref-load.ll

Removed: 
    


################################################################################
diff  --git a/llvm/test/Transforms/LICM/hoist-deref-load.ll b/llvm/test/Transforms/LICM/hoist-deref-load.ll
index 149976ab18746b..c498e85ddd6c29 100644
--- a/llvm/test/Transforms/LICM/hoist-deref-load.ll
+++ b/llvm/test/Transforms/LICM/hoist-deref-load.ll
@@ -420,7 +420,7 @@ for.end:                                          ; preds = %for.inc, %entry
 define void @test7(ptr noalias %a, ptr %b, ptr %cptr, i32 %n) #0 {
 ; CHECK-LABEL: @test7(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[C:%.*]] = load ptr, ptr [[CPTR:%.*]], align 8, !dereferenceable !0, !align !0
+; CHECK-NEXT:    [[C:%.*]] = load ptr, ptr [[CPTR:%.*]], align 8, !dereferenceable [[META0:![0-9]+]], !align [[META0]]
 ; CHECK-NEXT:    [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 0
 ; CHECK-NEXT:    br i1 [[CMP11]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]
 ; CHECK:       for.body.preheader:
@@ -492,7 +492,7 @@ for.end:                                          ; preds = %for.inc, %entry
 define void @test8(ptr noalias %a, ptr %b, ptr %cptr, i32 %n) #0 {
 ; CHECK-LABEL: @test8(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[C:%.*]] = load ptr, ptr [[CPTR:%.*]], align 8, !dereferenceable_or_null !0, !align !0
+; CHECK-NEXT:    [[C:%.*]] = load ptr, ptr [[CPTR:%.*]], align 8, !dereferenceable_or_null [[META0]], !align [[META0]]
 ; CHECK-NEXT:    [[NOT_NULL:%.*]] = icmp ne ptr [[C]], null
 ; CHECK-NEXT:    br i1 [[NOT_NULL]], label [[NOT_NULL:%.*]], label [[FOR_END:%.*]]
 ; CHECK:       not.null:
@@ -562,7 +562,7 @@ for.end:                                          ; preds = %for.inc, %entry, %n
 define void @test9(ptr noalias %a, ptr %b, ptr %cptr, i32 %n) #0 {
 ; CHECK-LABEL: @test9(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[C:%.*]] = load ptr, ptr [[CPTR:%.*]], align 8, !dereferenceable_or_null !0
+; CHECK-NEXT:    [[C:%.*]] = load ptr, ptr [[CPTR:%.*]], align 8, !dereferenceable_or_null [[META0]]
 ; CHECK-NEXT:    [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 0
 ; CHECK-NEXT:    br i1 [[CMP11]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]
 ; CHECK:       for.body.preheader:
@@ -693,7 +693,7 @@ define void @test11(ptr noalias %a, ptr %b, ptr dereferenceable(8) %cptr, i32 %n
 ; CHECK-NEXT:    [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 0
 ; CHECK-NEXT:    br i1 [[CMP11]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]
 ; CHECK:       for.body.preheader:
-; CHECK-NEXT:    [[C:%.*]] = load ptr, ptr [[CPTR:%.*]], align 8, !dereferenceable !0
+; CHECK-NEXT:    [[C:%.*]] = load ptr, ptr [[CPTR:%.*]], align 8, !dereferenceable [[META0]]
 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
 ; CHECK:       for.body:
 ; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
@@ -1164,5 +1164,78 @@ for.end:                                          ; preds = %for.inc, %entry
   ret void
 }
 
+declare void @use(i64)
+
+define void @licm_deref_no_hoist(i1 %c1, i1 %c2, ptr align 8 dereferenceable(8) %p1) {
+; CHECK-LABEL: @licm_deref_no_hoist(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[P2:%.*]] = load ptr, ptr [[P1:%.*]], align 8, !align [[META1:![0-9]+]]
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    br i1 [[C1:%.*]], label [[IF:%.*]], label [[LOOP_LATCH:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[V:%.*]] = load i64, ptr [[P2]], align 8
+; CHECK-NEXT:    call void @use(i64 [[V]]) #[[ATTR1:[0-9]+]]
+; CHECK-NEXT:    br label [[LOOP_LATCH]]
+; CHECK:       loop.latch:
+; CHECK-NEXT:    br i1 [[C2:%.*]], label [[LOOP]], label [[EXIT:%.*]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  br label %loop
+
+loop:
+  br i1 %c1, label %if, label %loop.latch
+
+if:
+  %p2 = load ptr, ptr %p1, align 8, !dereferenceable !1, !align !1
+  %v = load i64, ptr %p2, align 8
+  call void @use(i64 %v) memory(none)
+  br label %loop.latch
+
+loop.latch:
+  br i1 %c2, label %loop, label %exit
+
+exit:
+  ret void
+}
+
+define void @licm_deref_hoist(i1 %c1, i1 %c2, ptr align 8 dereferenceable(8) %p1) {
+; CHECK-LABEL: @licm_deref_hoist(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[P2:%.*]] = load ptr, ptr [[P1:%.*]], align 8, !dereferenceable [[META1]], !align [[META1]]
+; CHECK-NEXT:    [[V:%.*]] = load i64, ptr [[P2]], align 8
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    br i1 [[C1:%.*]], label [[IF:%.*]], label [[LOOP_LATCH:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    call void @use(i64 [[V]]) #[[ATTR1]]
+; CHECK-NEXT:    br label [[LOOP_LATCH]]
+; CHECK:       loop.latch:
+; CHECK-NEXT:    br i1 [[C2:%.*]], label [[LOOP]], label [[EXIT:%.*]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %p2 = load ptr, ptr %p1, align 8, !dereferenceable !1, !align !1
+  br label %loop
+
+loop:
+  br i1 %c1, label %if, label %loop.latch
+
+if:
+  %v = load i64, ptr %p2, align 8
+  call void @use(i64 %v) memory(none)
+  br label %loop.latch
+
+loop.latch:
+  br i1 %c2, label %loop, label %exit
+
+exit:
+  ret void
+}
+
 attributes #0 = { nounwind uwtable nofree nosync }
 !0 = !{i64 4}
+!1 = !{i64 8}

diff  --git a/llvm/test/Transforms/SimplifyCFG/speculate-derefable-load.ll b/llvm/test/Transforms/SimplifyCFG/speculate-derefable-load.ll
new file mode 100644
index 00000000000000..9e3f333018e680
--- /dev/null
+++ b/llvm/test/Transforms/SimplifyCFG/speculate-derefable-load.ll
@@ -0,0 +1,198 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -S -passes=simplifycfg < %s | FileCheck %s
+
+define i64 @align_deref_align(i1 %c, ptr %p) {
+; CHECK-LABEL: define i64 @align_deref_align(
+; CHECK-SAME: i1 [[C:%.*]], ptr [[P:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 8), "align"(ptr [[P]], i64 8) ]
+; CHECK-NEXT:    br i1 [[C]], label %[[IF:.*]], label %[[EXIT:.*]]
+; CHECK:       [[IF]]:
+; CHECK-NEXT:    [[V:%.*]] = load i64, ptr [[P]], align 8
+; CHECK-NEXT:    br label %[[EXIT]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    [[RES:%.*]] = phi i64 [ [[V]], %[[IF]] ], [ 0, %[[ENTRY]] ]
+; CHECK-NEXT:    ret i64 [[RES]]
+;
+entry:
+  call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %p, i64 8), "align"(ptr %p, i64 8) ]
+  br i1 %c, label %if, label %exit
+
+if:
+  %v = load i64, ptr %p, align 8
+  br label %exit
+
+exit:
+  %res = phi i64 [ %v, %if ], [ 0, %entry ]
+  ret i64 %res
+}
+
+define i64 @assume_deref_align2(i1 %c1, i32 %x, ptr %p) {
+; CHECK-LABEL: define i64 @assume_deref_align2(
+; CHECK-SAME: i1 [[C1:%.*]], i32 [[X:%.*]], ptr [[P:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 8), "align"(ptr [[P]], i64 8) ]
+; CHECK-NEXT:    br i1 [[C1]], label %[[IF1:.*]], label %[[EXIT:.*]]
+; CHECK:       [[IF1]]:
+; CHECK-NEXT:    [[C2:%.*]] = icmp ugt i32 [[X]], 10
+; CHECK-NEXT:    br i1 [[C2]], label %[[IF2:.*]], label %[[EXIT]]
+; CHECK:       [[IF2]]:
+; CHECK-NEXT:    [[V:%.*]] = load i64, ptr [[P]], align 8
+; CHECK-NEXT:    br label %[[EXIT]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    [[RES:%.*]] = phi i64 [ [[V]], %[[IF2]] ], [ 1, %[[IF1]] ], [ 0, %[[ENTRY]] ]
+; CHECK-NEXT:    ret i64 [[RES]]
+;
+entry:
+  call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %p, i64 8), "align"(ptr %p, i64 8) ]
+  br i1 %c1, label %if1, label %exit
+
+if1:
+  %c2 = icmp ugt i32 %x, 10
+  br i1 %c2, label %if2, label %exit
+
+if2:
+  %v = load i64, ptr %p, align 8
+  br label %exit
+
+exit:
+  %res = phi i64 [ %v, %if2 ], [ 1, %if1 ], [ 0, %entry ]
+  ret i64 %res
+}
+
+define i64 @assume_deref_align_not_dominating(i1 %c, ptr %p) {
+; CHECK-LABEL: define i64 @assume_deref_align_not_dominating(
+; CHECK-SAME: i1 [[C:%.*]], ptr [[P:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    br i1 [[C]], label %[[IF:.*]], label %[[EXIT:.*]]
+; CHECK:       [[IF]]:
+; CHECK-NEXT:    [[V:%.*]] = load i64, ptr [[P]], align 8
+; CHECK-NEXT:    br label %[[EXIT]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    [[RES:%.*]] = phi i64 [ [[V]], %[[IF]] ], [ 0, %[[ENTRY]] ]
+; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 8), "align"(ptr [[P]], i64 8) ]
+; CHECK-NEXT:    ret i64 [[RES]]
+;
+entry:
+  br i1 %c, label %if, label %exit
+
+if:
+  %v = load i64, ptr %p, align 8
+  br label %exit
+
+exit:
+  %res = phi i64 [ %v, %if ], [ 0, %entry ]
+  call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %p, i64 8), "align"(ptr %p, i64 8) ]
+  ret i64 %res
+}
+
+; FIXME: This is a miscompile.
+define i64 @deref_no_hoist(i1 %c, ptr align 8 dereferenceable(8) %p1) {
+; CHECK-LABEL: define i64 @deref_no_hoist(
+; CHECK-SAME: i1 [[C:%.*]], ptr align 8 dereferenceable(8) [[P1:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[P2:%.*]] = load ptr, ptr [[P1]], align 8, !align [[META0:![0-9]+]]
+; CHECK-NEXT:    [[V:%.*]] = load i64, ptr [[P2]], align 8
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[C]], i64 [[V]], i64 0
+; CHECK-NEXT:    ret i64 [[RES]]
+;
+entry:
+  br i1 %c, label %if, label %exit
+
+if:
+  %p2 = load ptr, ptr %p1, align 8, !dereferenceable !0, !align !0
+  %v = load i64, ptr %p2, align 8
+  br label %exit
+
+exit:
+  %res = phi i64 [ %v, %if ], [ 0, %entry ]
+  ret i64 %res
+}
+
+define i64 @deref_hoist(i1 %c, ptr align 8 dereferenceable(8) %p1) {
+; CHECK-LABEL: define i64 @deref_hoist(
+; CHECK-SAME: i1 [[C:%.*]], ptr align 8 dereferenceable(8) [[P1:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[P2:%.*]] = load ptr, ptr [[P1]], align 8, !dereferenceable [[META0]], !align [[META0]]
+; CHECK-NEXT:    [[V:%.*]] = load i64, ptr [[P2]], align 8
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[C]], i64 [[V]], i64 0
+; CHECK-NEXT:    ret i64 [[RES]]
+;
+entry:
+  %p2 = load ptr, ptr %p1, align 8, !dereferenceable !0, !align !0
+  br i1 %c, label %if, label %exit
+
+if:
+  %v = load i64, ptr %p2, align 8
+  br label %exit
+
+exit:
+  %res = phi i64 [ %v, %if ], [ 0, %entry ]
+  ret i64 %res
+}
+
+define i64 @deref_no_hoist2(i1 %c1, i32 %x, ptr align 8 dereferenceable(8) %p1) {
+; CHECK-LABEL: define i64 @deref_no_hoist2(
+; CHECK-SAME: i1 [[C1:%.*]], i32 [[X:%.*]], ptr align 8 dereferenceable(8) [[P1:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    br i1 [[C1]], label %[[IF1:.*]], label %[[EXIT:.*]]
+; CHECK:       [[IF1]]:
+; CHECK-NEXT:    [[C2:%.*]] = icmp ugt i32 [[X]], 10
+; CHECK-NEXT:    br i1 [[C2]], label %[[IF2:.*]], label %[[EXIT]]
+; CHECK:       [[IF2]]:
+; CHECK-NEXT:    [[P2:%.*]] = load ptr, ptr [[P1]], align 8, !dereferenceable [[META0]], !align [[META0]]
+; CHECK-NEXT:    [[V:%.*]] = load i64, ptr [[P2]], align 8
+; CHECK-NEXT:    br label %[[EXIT]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    [[RES:%.*]] = phi i64 [ [[V]], %[[IF2]] ], [ 1, %[[IF1]] ], [ 0, %[[ENTRY]] ]
+; CHECK-NEXT:    ret i64 [[RES]]
+;
+entry:
+  br i1 %c1, label %if1, label %exit
+
+if1:
+  %c2 = icmp ugt i32 %x, 10
+  br i1 %c2, label %if2, label %exit
+
+if2:
+  %p2 = load ptr, ptr %p1, align 8, !dereferenceable !0, !align !0
+  %v = load i64, ptr %p2, align 8
+  br label %exit
+
+exit:
+  %res = phi i64 [ %v, %if2 ], [ 1, %if1 ], [ 0, %entry ]
+  ret i64 %res
+}
+
+define i64 @deref_hoist2(i1 %c1, i32 %x, ptr align 8 dereferenceable(8) %p1) {
+; CHECK-LABEL: define i64 @deref_hoist2(
+; CHECK-SAME: i1 [[C1:%.*]], i32 [[X:%.*]], ptr align 8 dereferenceable(8) [[P1:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[P2:%.*]] = load ptr, ptr [[P1]], align 8, !dereferenceable [[META0]], !align [[META0]]
+; CHECK-NEXT:    [[C2:%.*]] = icmp ugt i32 [[X]], 10
+; CHECK-NEXT:    [[V:%.*]] = load i64, ptr [[P2]], align 8
+; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[C2]], i64 [[V]], i64 1
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[C1]], i64 [[SPEC_SELECT]], i64 0
+; CHECK-NEXT:    ret i64 [[RES]]
+;
+entry:
+  %p2 = load ptr, ptr %p1, align 8, !dereferenceable !0, !align !0
+  br i1 %c1, label %if1, label %exit
+
+if1:
+  %c2 = icmp ugt i32 %x, 10
+  br i1 %c2, label %if2, label %exit
+
+if2:
+  %v = load i64, ptr %p2, align 8
+  br label %exit
+
+exit:
+  %res = phi i64 [ %v, %if2 ], [ 1, %if1 ], [ 0, %entry ]
+  ret i64 %res
+}
+
+!0 = !{i64 8}
+;.
+; CHECK: [[META0]] = !{i64 8}
+;.


        


More information about the llvm-commits mailing list