[llvm] 3b1951a - [Test] Add test showing difference in behavior of Guard Widening depending on form

Max Kazantsev via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 16 02:11:39 PDT 2023


Author: Max Kazantsev
Date: 2023-03-16T16:11:11+07:00
New Revision: 3b1951aceb8c58acd3d5c5ba2d042ad3d03c13c4

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

LOG: [Test] Add test showing difference in behavior of Guard Widening depending on form

Guards can be represented differently (as intrinsic calls and as explicit branches),
and the expectation is that Guard Widening should do the same things for them, no
matter what form it was suggested. Currently it seems to be not so.

We also don't want LICM to prevent guard widening.

Added: 
    llvm/test/Transforms/GuardWidening/two_forms_behavior_consistency.ll

Modified: 
    

Removed: 
    


################################################################################
diff  --git a/llvm/test/Transforms/GuardWidening/two_forms_behavior_consistency.ll b/llvm/test/Transforms/GuardWidening/two_forms_behavior_consistency.ll
new file mode 100644
index 0000000000000..6e95145c28256
--- /dev/null
+++ b/llvm/test/Transforms/GuardWidening/two_forms_behavior_consistency.ll
@@ -0,0 +1,132 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
+; RUN: opt -S -passes="guard-widening,make-guards-explicit,simplifycfg" < %s        | FileCheck %s --check-prefixes=INTRINSIC_FORM
+; RUN: opt -S -passes="make-guards-explicit,guard-widening,simplifycfg" < %s        | FileCheck %s --check-prefixes=BRANCH_FORM
+; RUN: opt -S -passes="make-guards-explicit,loop-mssa(licm),guard-widening,simplifycfg" < %s        | FileCheck %s --check-prefixes=BRANCH_FORM_LICM
+
+declare i1 @cond() readonly
+
+; FIXME We want to make sure that guard widening works in the same way, no matter what form of
+;       guards it is dealing with.
+; FIXME We also want to make sure that LICM doesn't mess with widenable conditions, what might
+;       make things more complex.
+define void @test_01(i32 %a, i32 %b, i32 %c, i32 %d) {
+; INTRINSIC_FORM-LABEL: define void @test_01
+; INTRINSIC_FORM-SAME: (i32 [[A:%.*]], i32 [[B:%.*]], i32 [[C:%.*]], i32 [[D:%.*]]) {
+; INTRINSIC_FORM-NEXT:  entry:
+; INTRINSIC_FORM-NEXT:    br label [[LOOP:%.*]]
+; INTRINSIC_FORM:       loop:
+; INTRINSIC_FORM-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[GUARDED:%.*]] ]
+; INTRINSIC_FORM-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
+; INTRINSIC_FORM-NEXT:    [[C1:%.*]] = icmp ult i32 [[IV]], [[A]]
+; INTRINSIC_FORM-NEXT:    [[C2:%.*]] = icmp ult i32 [[IV]], [[B]]
+; INTRINSIC_FORM-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[C1]], [[C2]]
+; INTRINSIC_FORM-NEXT:    [[C3:%.*]] = icmp ult i32 [[IV]], [[C]]
+; INTRINSIC_FORM-NEXT:    [[WIDE_CHK1:%.*]] = and i1 [[WIDE_CHK]], [[C3]]
+; INTRINSIC_FORM-NEXT:    [[C4:%.*]] = icmp ult i32 [[IV]], [[D]]
+; INTRINSIC_FORM-NEXT:    [[WIDE_CHK2:%.*]] = and i1 [[WIDE_CHK1]], [[C4]]
+; INTRINSIC_FORM-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; INTRINSIC_FORM-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK2]], [[WIDENABLE_COND]]
+; INTRINSIC_FORM-NEXT:    br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0:![0-9]+]]
+; INTRINSIC_FORM:       deopt:
+; INTRINSIC_FORM-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; INTRINSIC_FORM-NEXT:    ret void
+; INTRINSIC_FORM:       guarded:
+; INTRINSIC_FORM-NEXT:    [[LOOP_COND:%.*]] = call i1 @cond()
+; INTRINSIC_FORM-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
+; INTRINSIC_FORM:       exit:
+; INTRINSIC_FORM-NEXT:    ret void
+;
+; BRANCH_FORM-LABEL: define void @test_01
+; BRANCH_FORM-SAME: (i32 [[A:%.*]], i32 [[B:%.*]], i32 [[C:%.*]], i32 [[D:%.*]]) {
+; BRANCH_FORM-NEXT:  entry:
+; BRANCH_FORM-NEXT:    br label [[LOOP:%.*]]
+; BRANCH_FORM:       loop:
+; BRANCH_FORM-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[GUARDED5:%.*]] ]
+; BRANCH_FORM-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
+; BRANCH_FORM-NEXT:    [[C1:%.*]] = icmp ult i32 [[IV]], [[A]]
+; BRANCH_FORM-NEXT:    [[C2:%.*]] = icmp ult i32 [[IV]], [[B]]
+; BRANCH_FORM-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[C1]], [[C2]]
+; BRANCH_FORM-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; BRANCH_FORM-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
+; BRANCH_FORM-NEXT:    br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0:![0-9]+]]
+; BRANCH_FORM:       deopt:
+; BRANCH_FORM-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; BRANCH_FORM-NEXT:    ret void
+; BRANCH_FORM:       guarded:
+; BRANCH_FORM-NEXT:    [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; BRANCH_FORM-NEXT:    [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[C2]], [[WIDENABLE_COND3]]
+; BRANCH_FORM-NEXT:    [[C3:%.*]] = icmp ult i32 [[IV]], [[C]]
+; BRANCH_FORM-NEXT:    [[C4:%.*]] = icmp ult i32 [[IV]], [[D]]
+; BRANCH_FORM-NEXT:    [[WIDE_CHK13:%.*]] = and i1 [[C3]], [[C4]]
+; BRANCH_FORM-NEXT:    [[WIDENABLE_COND7:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; BRANCH_FORM-NEXT:    [[EXIPLICIT_GUARD_COND8:%.*]] = and i1 [[WIDE_CHK13]], [[WIDENABLE_COND7]]
+; BRANCH_FORM-NEXT:    br i1 [[EXIPLICIT_GUARD_COND8]], label [[GUARDED5]], label [[DEOPT6:%.*]], !prof [[PROF0]]
+; BRANCH_FORM:       deopt6:
+; BRANCH_FORM-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; BRANCH_FORM-NEXT:    ret void
+; BRANCH_FORM:       guarded5:
+; BRANCH_FORM-NEXT:    [[WIDENABLE_COND11:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; BRANCH_FORM-NEXT:    [[EXIPLICIT_GUARD_COND12:%.*]] = and i1 [[C4]], [[WIDENABLE_COND11]]
+; BRANCH_FORM-NEXT:    [[LOOP_COND:%.*]] = call i1 @cond()
+; BRANCH_FORM-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
+; BRANCH_FORM:       exit:
+; BRANCH_FORM-NEXT:    ret void
+;
+; BRANCH_FORM_LICM-LABEL: define void @test_01
+; BRANCH_FORM_LICM-SAME: (i32 [[A:%.*]], i32 [[B:%.*]], i32 [[C:%.*]], i32 [[D:%.*]]) {
+; BRANCH_FORM_LICM-NEXT:  entry:
+; BRANCH_FORM_LICM-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; BRANCH_FORM_LICM-NEXT:    [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; BRANCH_FORM_LICM-NEXT:    [[WIDENABLE_COND7:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; BRANCH_FORM_LICM-NEXT:    [[WIDENABLE_COND11:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; BRANCH_FORM_LICM-NEXT:    br label [[LOOP:%.*]]
+; BRANCH_FORM_LICM:       loop:
+; BRANCH_FORM_LICM-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[GUARDED9:%.*]] ]
+; BRANCH_FORM_LICM-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
+; BRANCH_FORM_LICM-NEXT:    [[C1:%.*]] = icmp ult i32 [[IV]], [[A]]
+; BRANCH_FORM_LICM-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[C1]], [[WIDENABLE_COND]]
+; BRANCH_FORM_LICM-NEXT:    [[C2:%.*]] = icmp ult i32 [[IV]], [[B]]
+; BRANCH_FORM_LICM-NEXT:    [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[C2]], [[WIDENABLE_COND3]]
+; BRANCH_FORM_LICM-NEXT:    [[OR_COND:%.*]] = select i1 [[EXIPLICIT_GUARD_COND]], i1 [[EXIPLICIT_GUARD_COND4]], i1 false
+; BRANCH_FORM_LICM-NEXT:    br i1 [[OR_COND]], label [[GUARDED1:%.*]], label [[DEOPT:%.*]], !prof [[PROF0:![0-9]+]]
+; BRANCH_FORM_LICM:       deopt:
+; BRANCH_FORM_LICM-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; BRANCH_FORM_LICM-NEXT:    ret void
+; BRANCH_FORM_LICM:       guarded1:
+; BRANCH_FORM_LICM-NEXT:    [[C3:%.*]] = icmp ult i32 [[IV]], [[C]]
+; BRANCH_FORM_LICM-NEXT:    [[EXIPLICIT_GUARD_COND8:%.*]] = and i1 [[C3]], [[WIDENABLE_COND7]]
+; BRANCH_FORM_LICM-NEXT:    [[C4:%.*]] = icmp ult i32 [[IV]], [[D]]
+; BRANCH_FORM_LICM-NEXT:    [[EXIPLICIT_GUARD_COND12:%.*]] = and i1 [[C4]], [[WIDENABLE_COND11]]
+; BRANCH_FORM_LICM-NEXT:    [[OR_COND13:%.*]] = select i1 [[EXIPLICIT_GUARD_COND8]], i1 [[EXIPLICIT_GUARD_COND12]], i1 false
+; BRANCH_FORM_LICM-NEXT:    br i1 [[OR_COND13]], label [[GUARDED9]], label [[DEOPT6:%.*]], !prof [[PROF0]]
+; BRANCH_FORM_LICM:       deopt6:
+; BRANCH_FORM_LICM-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; BRANCH_FORM_LICM-NEXT:    ret void
+; BRANCH_FORM_LICM:       guarded9:
+; BRANCH_FORM_LICM-NEXT:    [[LOOP_COND:%.*]] = call i1 @cond()
+; BRANCH_FORM_LICM-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
+; BRANCH_FORM_LICM:       exit:
+; BRANCH_FORM_LICM-NEXT:    ret void
+;
+entry:
+  br label %loop
+
+loop:
+  %iv = phi i32 [0, %entry], [%iv.next, %loop]
+  %iv.next = add i32 %iv, 1
+  %c1 = icmp ult i32 %iv, %a
+  call void(i1, ...) @llvm.experimental.guard(i1 %c1) [ "deopt"() ]
+  %c2 = icmp ult i32 %iv, %b
+  call void(i1, ...) @llvm.experimental.guard(i1 %c2) [ "deopt"() ]
+  %c3 = icmp ult i32 %iv, %c
+  call void(i1, ...) @llvm.experimental.guard(i1 %c3) [ "deopt"() ]
+  %c4 = icmp ult i32 %iv, %d
+  call void(i1, ...) @llvm.experimental.guard(i1 %c4) [ "deopt"() ]
+  %loop_cond = call i1 @cond()
+  br i1 %loop_cond, label %loop, label %exit
+
+exit:
+  ret void
+}
+
+declare void @llvm.experimental.guard(i1, ...)


        


More information about the llvm-commits mailing list