From e406de77c6f33a6d3bf0b432bad1217b37605c15 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 11 Jan 2021 20:17:10 +0100 Subject: [PATCH] [PredicateInfo][SCCP][NewGVN] Add tests for logical and/or (NFC) Duplicate some existing and/or tests using logical form. --- llvm/test/Transforms/NewGVN/condprop.ll | 98 +++++++++++- llvm/test/Transforms/SCCP/conditions-ranges.ll | 170 +++++++++++++++++++++ .../Transforms/Util/PredicateInfo/testandor.ll | 92 ++++++++++- 3 files changed, 354 insertions(+), 6 deletions(-) diff --git a/llvm/test/Transforms/NewGVN/condprop.ll b/llvm/test/Transforms/NewGVN/condprop.ll index faef4b1..8c77f7f 100644 --- a/llvm/test/Transforms/NewGVN/condprop.ll +++ b/llvm/test/Transforms/NewGVN/condprop.ll @@ -5,8 +5,8 @@ declare void @foo(i1) declare void @bar(i32) -define void @test3(i32 %x, i32 %y) { -; CHECK-LABEL: @test3( +define void @test_and(i32 %x, i32 %y) { +; CHECK-LABEL: @test_and( ; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0 ; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0 ; CHECK-NEXT: [[Z:%.*]] = and i1 [[XZ]], [[YZ]] @@ -35,6 +35,100 @@ nope: call void @foo(i1 %z) ret void } + +define void @test_and_logical(i32 %x, i32 %y) { +; CHECK-LABEL: @test_and_logical( +; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0 +; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0 +; CHECK-NEXT: [[Z:%.*]] = select i1 [[XZ]], i1 [[YZ]], i1 false +; CHECK-NEXT: br i1 [[Z]], label [[BOTH_ZERO:%.*]], label [[NOPE:%.*]] +; CHECK: both_zero: +; CHECK-NEXT: call void @foo(i1 [[XZ]]) +; CHECK-NEXT: call void @foo(i1 [[YZ]]) +; CHECK-NEXT: call void @bar(i32 [[X]]) +; CHECK-NEXT: call void @bar(i32 [[Y]]) +; CHECK-NEXT: ret void +; CHECK: nope: +; CHECK-NEXT: call void @foo(i1 false) +; CHECK-NEXT: ret void +; + %xz = icmp eq i32 %x, 0 + %yz = icmp eq i32 %y, 0 + %z = select i1 %xz, i1 %yz, i1 false + br i1 %z, label %both_zero, label %nope +both_zero: + call void @foo(i1 %xz) + call void @foo(i1 %yz) + call void @bar(i32 %x) + call void @bar(i32 %y) + ret void +nope: + call void @foo(i1 %z) + ret void +} + +define void @test_or(i32 %x, i32 %y) { +; CHECK-LABEL: @test_or( +; CHECK-NEXT: [[XZ:%.*]] = icmp ne i32 [[X:%.*]], 0 +; CHECK-NEXT: [[YZ:%.*]] = icmp ne i32 [[Y:%.*]], 0 +; CHECK-NEXT: [[Z:%.*]] = or i1 [[XZ]], [[YZ]] +; CHECK-NEXT: br i1 [[Z]], label [[NOPE:%.*]], label [[BOTH_ZERO:%.*]] +; CHECK: both_zero: +; CHECK-NEXT: call void @foo(i1 false) +; CHECK-NEXT: call void @foo(i1 false) +; CHECK-NEXT: call void @bar(i32 0) +; CHECK-NEXT: call void @bar(i32 0) +; CHECK-NEXT: ret void +; CHECK: nope: +; CHECK-NEXT: call void @foo(i1 true) +; CHECK-NEXT: ret void +; + %xz = icmp ne i32 %x, 0 + %yz = icmp ne i32 %y, 0 + %z = or i1 %xz, %yz + br i1 %z, label %nope, label %both_zero +both_zero: + call void @foo(i1 %xz) + call void @foo(i1 %yz) + call void @bar(i32 %x) + call void @bar(i32 %y) + ret void +nope: + call void @foo(i1 %z) + ret void +} + +define void @test_or_logical(i32 %x, i32 %y) { +; CHECK-LABEL: @test_or_logical( +; CHECK-NEXT: [[XZ:%.*]] = icmp ne i32 [[X:%.*]], 0 +; CHECK-NEXT: [[YZ:%.*]] = icmp ne i32 [[Y:%.*]], 0 +; CHECK-NEXT: [[Z:%.*]] = select i1 [[XZ]], i1 true, i1 [[YZ]] +; CHECK-NEXT: br i1 [[Z]], label [[NOPE:%.*]], label [[BOTH_ZERO:%.*]] +; CHECK: both_zero: +; CHECK-NEXT: call void @foo(i1 [[XZ]]) +; CHECK-NEXT: call void @foo(i1 [[YZ]]) +; CHECK-NEXT: call void @bar(i32 [[X]]) +; CHECK-NEXT: call void @bar(i32 [[Y]]) +; CHECK-NEXT: ret void +; CHECK: nope: +; CHECK-NEXT: call void @foo(i1 true) +; CHECK-NEXT: ret void +; + %xz = icmp ne i32 %x, 0 + %yz = icmp ne i32 %y, 0 + %z = select i1 %xz, i1 true, i1 %yz + br i1 %z, label %nope, label %both_zero +both_zero: + call void @foo(i1 %xz) + call void @foo(i1 %yz) + call void @bar(i32 %x) + call void @bar(i32 %y) + ret void +nope: + call void @foo(i1 %z) + ret void +} + define void @test4(i1 %b, i32 %x) { ; CHECK-LABEL: @test4( ; CHECK-NEXT: br i1 [[B:%.*]], label [[SW:%.*]], label [[CASE3:%.*]] diff --git a/llvm/test/Transforms/SCCP/conditions-ranges.ll b/llvm/test/Transforms/SCCP/conditions-ranges.ll index 2317242..0a43070 100644 --- a/llvm/test/Transforms/SCCP/conditions-ranges.ll +++ b/llvm/test/Transforms/SCCP/conditions-ranges.ll @@ -886,6 +886,91 @@ false: ret void } +define void @f16_conditions_and_logical(i32 %a, i32 %b) { +; CHECK-LABEL: @f16_conditions_and_logical( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[LT:%.*]] = icmp ult i32 [[A:%.*]], 100 +; CHECK-NEXT: [[GT:%.*]] = icmp ugt i32 [[A]], 20 +; CHECK-NEXT: [[BC:%.*]] = select i1 [[LT]], i1 [[GT]], i1 false +; CHECK-NEXT: br i1 [[BC]], label [[TRUE:%.*]], label [[FALSE:%.*]] +; CHECK: true: +; CHECK-NEXT: [[F_1:%.*]] = icmp eq i32 [[A]], 0 +; CHECK-NEXT: call void @use(i1 [[F_1]]) +; CHECK-NEXT: [[F_2:%.*]] = icmp eq i32 [[A]], 20 +; CHECK-NEXT: call void @use(i1 [[F_2]]) +; CHECK-NEXT: [[F_3:%.*]] = icmp ugt i32 [[A]], 100 +; CHECK-NEXT: call void @use(i1 [[F_3]]) +; CHECK-NEXT: [[T_1:%.*]] = icmp ult i32 [[A]], 100 +; CHECK-NEXT: call void @use(i1 [[T_1]]) +; CHECK-NEXT: [[T_2:%.*]] = icmp ne i32 [[A]], 20 +; CHECK-NEXT: call void @use(i1 [[T_2]]) +; CHECK-NEXT: [[C_1:%.*]] = icmp eq i32 [[A]], 21 +; CHECK-NEXT: call void @use(i1 [[C_1]]) +; CHECK-NEXT: [[C_2:%.*]] = icmp ugt i32 [[A]], 21 +; CHECK-NEXT: call void @use(i1 [[C_2]]) +; CHECK-NEXT: [[C_3:%.*]] = icmp ugt i32 [[A]], 50 +; CHECK-NEXT: call void @use(i1 [[C_3]]) +; CHECK-NEXT: ret void +; CHECK: false: +; CHECK-NEXT: [[F_4:%.*]] = icmp eq i32 [[A]], 50 +; CHECK-NEXT: call void @use(i1 [[F_4]]) +; CHECK-NEXT: [[T_3:%.*]] = icmp ne i32 [[A]], 50 +; CHECK-NEXT: call void @use(i1 [[T_3]]) +; CHECK-NEXT: [[C_4:%.*]] = icmp eq i32 [[A]], 10 +; CHECK-NEXT: call void @use(i1 [[C_4]]) +; CHECK-NEXT: [[C_5:%.*]] = icmp eq i32 [[B:%.*]], 100 +; CHECK-NEXT: call void @use(i1 [[C_5]]) +; CHECK-NEXT: ret void +; +entry: + %lt = icmp ult i32 %a, 100 + %gt = icmp ugt i32 %a, 20 + %bc = select i1 %lt, i1 %gt, i1 false + br i1 %bc, label %true, label %false + +true: ; %a in [21, 100) + ; Conditions below are false. + %f.1 = icmp eq i32 %a, 0 + call void @use(i1 %f.1) + %f.2 = icmp eq i32 %a, 20 + call void @use(i1 %f.2) + %f.3 = icmp ugt i32 %a, 100 + call void @use(i1 %f.3) + + ; Conditions below are true. + %t.1 = icmp ult i32 %a, 100 + call void @use(i1 %t.1) + %t.2 = icmp ne i32 %a, 20 + call void @use(i1 %t.2) + + ; Conditions below cannot be simplified. + %c.1 = icmp eq i32 %a, 21 + call void @use(i1 %c.1) + %c.2 = icmp ugt i32 %a, 21 + call void @use(i1 %c.2) + %c.3 = icmp ugt i32 %a, 50 + call void @use(i1 %c.3) + ret void + +false: +; TODO: Currently there is no conditional range info in the false branch for branch conditions with an AND. +; %a should be in in [100, 21) + ; Conditions below are false; + %f.4 = icmp eq i32 %a, 50 + call void @use(i1 %f.4) + + ; Conditions below are true; + %t.3 = icmp ne i32 %a, 50 + call void @use(i1 %t.3) + + ; Conditions below cannot be simplified. + %c.4 = icmp eq i32 %a, 10 + call void @use(i1 %c.4) + %c.5 = icmp eq i32 %b, 100 + call void @use(i1 %c.5) + ret void +} + define void @f17_conditions_or(i32 %a, i32 %b) { ; CHECK-LABEL: @f17_conditions_or( ; CHECK-NEXT: entry: @@ -966,6 +1051,91 @@ true: ret void } +define void @f17_conditions_or_logical(i32 %a, i32 %b) { +; CHECK-LABEL: @f17_conditions_or_logical( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[GT:%.*]] = icmp uge i32 [[A:%.*]], 100 +; CHECK-NEXT: [[LT:%.*]] = icmp ule i32 [[A]], 20 +; CHECK-NEXT: [[BC:%.*]] = select i1 [[LT]], i1 true, i1 [[GT]] +; CHECK-NEXT: br i1 [[BC]], label [[TRUE:%.*]], label [[FALSE:%.*]] +; CHECK: false: +; CHECK-NEXT: [[F_1:%.*]] = icmp eq i32 [[A]], 0 +; CHECK-NEXT: call void @use(i1 [[F_1]]) +; CHECK-NEXT: [[F_2:%.*]] = icmp eq i32 [[A]], 20 +; CHECK-NEXT: call void @use(i1 [[F_2]]) +; CHECK-NEXT: [[F_3:%.*]] = icmp ugt i32 [[A]], 100 +; CHECK-NEXT: call void @use(i1 [[F_3]]) +; CHECK-NEXT: [[T_1:%.*]] = icmp ult i32 [[A]], 100 +; CHECK-NEXT: call void @use(i1 [[T_1]]) +; CHECK-NEXT: [[T_2:%.*]] = icmp ne i32 [[A]], 20 +; CHECK-NEXT: call void @use(i1 [[T_2]]) +; CHECK-NEXT: [[C_1:%.*]] = icmp eq i32 [[A]], 21 +; CHECK-NEXT: call void @use(i1 [[C_1]]) +; CHECK-NEXT: [[C_2:%.*]] = icmp ugt i32 [[A]], 21 +; CHECK-NEXT: call void @use(i1 [[C_2]]) +; CHECK-NEXT: [[C_3:%.*]] = icmp ugt i32 [[A]], 50 +; CHECK-NEXT: call void @use(i1 [[C_3]]) +; CHECK-NEXT: ret void +; CHECK: true: +; CHECK-NEXT: [[F_4:%.*]] = icmp eq i32 [[A]], 50 +; CHECK-NEXT: call void @use(i1 [[F_4]]) +; CHECK-NEXT: [[T_3:%.*]] = icmp ne i32 [[A]], 50 +; CHECK-NEXT: call void @use(i1 [[T_3]]) +; CHECK-NEXT: [[C_4:%.*]] = icmp eq i32 [[A]], 10 +; CHECK-NEXT: call void @use(i1 [[C_4]]) +; CHECK-NEXT: [[C_5:%.*]] = icmp eq i32 [[B:%.*]], 100 +; CHECK-NEXT: call void @use(i1 [[C_5]]) +; CHECK-NEXT: ret void +; +entry: + %gt = icmp uge i32 %a, 100 + %lt = icmp ule i32 %a, 20 + %bc = select i1 %lt, i1 true, i1 %gt + br i1 %bc, label %true, label %false + +false: ; %a in [21, 100) + ; Conditions below are false. + %f.1 = icmp eq i32 %a, 0 + call void @use(i1 %f.1) + %f.2 = icmp eq i32 %a, 20 + call void @use(i1 %f.2) + %f.3 = icmp ugt i32 %a, 100 + call void @use(i1 %f.3) + + ; Conditions below are true. + %t.1 = icmp ult i32 %a, 100 + call void @use(i1 %t.1) + %t.2 = icmp ne i32 %a, 20 + call void @use(i1 %t.2) + + ; Conditions below cannot be simplified. + %c.1 = icmp eq i32 %a, 21 + call void @use(i1 %c.1) + %c.2 = icmp ugt i32 %a, 21 + call void @use(i1 %c.2) + %c.3 = icmp ugt i32 %a, 50 + call void @use(i1 %c.3) + ret void + +true: +; TODO: Currently there is no conditional range info in the false branch for branch conditions with an AND. +; %a should be in in [100, 21) + ; Conditions below are false; + %f.4 = icmp eq i32 %a, 50 + call void @use(i1 %f.4) + + ; Conditions below are true; + %t.3 = icmp ne i32 %a, 50 + call void @use(i1 %t.3) + + ; Conditions below cannot be simplified. + %c.4 = icmp eq i32 %a, 10 + call void @use(i1 %c.4) + %c.5 = icmp eq i32 %b, 100 + call void @use(i1 %c.5) + ret void +} + define void @f18_conditions_chained_and(i32 %a, i32 %b) { ; CHECK-LABEL: @f18_conditions_chained_and( ; CHECK-NEXT: entry: diff --git a/llvm/test/Transforms/Util/PredicateInfo/testandor.ll b/llvm/test/Transforms/Util/PredicateInfo/testandor.ll index 8ce56ac..9dbb749 100644 --- a/llvm/test/Transforms/Util/PredicateInfo/testandor.ll +++ b/llvm/test/Transforms/Util/PredicateInfo/testandor.ll @@ -5,8 +5,8 @@ declare void @foo(i1) declare void @bar(i32) declare void @llvm.assume(i1) -define void @testor(i32 %x, i32 %y) { -; CHECK-LABEL: @testor( +define void @test_or(i32 %x, i32 %y) { +; CHECK-LABEL: @test_or( ; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0 ; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0 ; CHECK-NEXT: [[Z:%.*]] = or i1 [[XZ]], [[YZ]] @@ -49,8 +49,50 @@ neither: call void @foo(i1 %z) ret void } -define void @testand(i32 %x, i32 %y) { -; CHECK-LABEL: @testand( + +define void @test_or_logical(i32 %x, i32 %y) { +; CHECK-LABEL: @test_or_logical( +; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0 +; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0 +; CHECK-NEXT: [[Z:%.*]] = select i1 [[XZ]], i1 true, i1 [[YZ]] +; CHECK: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[Z]]) +; CHECK-NEXT: br i1 [[Z]], label [[ONEOF:%.*]], label [[NEITHER:%.*]] +; CHECK: oneof: +; CHECK-NEXT: call void @foo(i1 [[XZ]]) +; CHECK-NEXT: call void @foo(i1 [[YZ]]) +; CHECK-NEXT: call void @bar(i32 [[X]]) +; CHECK-NEXT: call void @bar(i32 [[Y]]) +; CHECK-NEXT: ret void +; CHECK: neither: +; CHECK-NEXT: call void @foo(i1 [[XZ]]) +; CHECK-NEXT: call void @foo(i1 [[YZ]]) +; CHECK-NEXT: call void @bar(i32 [[X]]) +; CHECK-NEXT: call void @bar(i32 [[Y]]) +; CHECK-NEXT: call void @foo(i1 [[Z_0]]) +; CHECK-NEXT: ret void +; + %xz = icmp eq i32 %x, 0 + %yz = icmp eq i32 %y, 0 + %z = select i1 %xz, i1 true, i1 %yz + br i1 %z, label %oneof, label %neither +oneof: +;; Should not insert on the true edge for or + call void @foo(i1 %xz) + call void @foo(i1 %yz) + call void @bar(i32 %x) + call void @bar(i32 %y) + ret void +neither: + call void @foo(i1 %xz) + call void @foo(i1 %yz) + call void @bar(i32 %x) + call void @bar(i32 %y) + call void @foo(i1 %z) + ret void +} + +define void @test_and(i32 %x, i32 %y) { +; CHECK-LABEL: @test_and( ; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0 ; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0 ; CHECK-NEXT: [[Z:%.*]] = and i1 [[XZ]], [[YZ]] @@ -93,6 +135,48 @@ nope: call void @foo(i1 %z) ret void } + +define void @test_and_logical(i32 %x, i32 %y) { +; CHECK-LABEL: @test_and_logical( +; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0 +; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0 +; CHECK-NEXT: [[Z:%.*]] = select i1 [[XZ]], i1 [[YZ]], i1 false +; CHECK: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[Z]]) +; CHECK-NEXT: br i1 [[Z]], label [[BOTH:%.*]], label [[NOPE:%.*]] +; CHECK: both: +; CHECK-NEXT: call void @foo(i1 [[XZ]]) +; CHECK-NEXT: call void @foo(i1 [[YZ]]) +; CHECK-NEXT: call void @bar(i32 [[X]]) +; CHECK-NEXT: call void @bar(i32 [[Y]]) +; CHECK-NEXT: ret void +; CHECK: nope: +; CHECK-NEXT: call void @foo(i1 [[XZ]]) +; CHECK-NEXT: call void @foo(i1 [[YZ]]) +; CHECK-NEXT: call void @bar(i32 [[X]]) +; CHECK-NEXT: call void @bar(i32 [[Y]]) +; CHECK-NEXT: call void @foo(i1 [[Z_0]]) +; CHECK-NEXT: ret void +; + %xz = icmp eq i32 %x, 0 + %yz = icmp eq i32 %y, 0 + %z = select i1 %xz, i1 %yz, i1 false + br i1 %z, label %both, label %nope +both: + call void @foo(i1 %xz) + call void @foo(i1 %yz) + call void @bar(i32 %x) + call void @bar(i32 %y) + ret void +nope: +;; Should not insert on the false edge for and + call void @foo(i1 %xz) + call void @foo(i1 %yz) + call void @bar(i32 %x) + call void @bar(i32 %y) + call void @foo(i1 %z) + ret void +} + define void @testandsame(i32 %x, i32 %y) { ; CHECK-LABEL: @testandsame( ; CHECK-NEXT: [[XGT:%.*]] = icmp sgt i32 [[X:%.*]], 0 -- 2.7.4