diff options
author | Noah Goldstein <goldstein.w.n@gmail.com> | 2024-01-11 15:41:06 -0800 |
---|---|---|
committer | Noah Goldstein <goldstein.w.n@gmail.com> | 2024-01-15 12:05:38 -0800 |
commit | 73863a48352c48b0c37a49c5dcfa521eb0cfcb5b (patch) | |
tree | 24d8d655b192c6dc90f82895c58f4e724c2c459e | |
parent | f9b089a7c01dd3fe7de3d397520172ec3b8fb9f1 (diff) | |
download | llvm-73863a48352c48b0c37a49c5dcfa521eb0cfcb5b.zip llvm-73863a48352c48b0c37a49c5dcfa521eb0cfcb5b.tar.gz llvm-73863a48352c48b0c37a49c5dcfa521eb0cfcb5b.tar.bz2 |
[InstCombine] Add tests for folding `(add/sub/disjoint_or/icmp C, (ctpop (not x)))`; NFC
-rw-r--r-- | llvm/test/Transforms/InstCombine/fold-ctpop-of-not.ll | 235 |
1 files changed, 235 insertions, 0 deletions
diff --git a/llvm/test/Transforms/InstCombine/fold-ctpop-of-not.ll b/llvm/test/Transforms/InstCombine/fold-ctpop-of-not.ll new file mode 100644 index 0000000..008a6f6 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/fold-ctpop-of-not.ll @@ -0,0 +1,235 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -passes=instcombine -S | FileCheck %s + +declare void @use.i8(i8) +declare i8 @llvm.ctpop.i8(i8) +declare i2 @llvm.ctpop.i2(i2) +declare <2 x i8> @llvm.ctpop.v2i8(<2 x i8>) + +define i8 @fold_sub_c_ctpop(i8 %x) { +; CHECK-LABEL: @fold_sub_c_ctpop( +; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1 +; CHECK-NEXT: [[CNT:%.*]] = call i8 @llvm.ctpop.i8(i8 [[NX]]), !range [[RNG0:![0-9]+]] +; CHECK-NEXT: [[R:%.*]] = sub nuw nsw i8 12, [[CNT]] +; CHECK-NEXT: ret i8 [[R]] +; + %nx = xor i8 %x, -1 + %cnt = call i8 @llvm.ctpop.i8(i8 %nx) + %r = sub i8 12, %cnt + ret i8 %r +} + +define i8 @fold_sub_var_ctpop_fail(i8 %x, i8 %y) { +; CHECK-LABEL: @fold_sub_var_ctpop_fail( +; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1 +; CHECK-NEXT: [[CNT:%.*]] = call i8 @llvm.ctpop.i8(i8 [[NX]]), !range [[RNG0]] +; CHECK-NEXT: [[R:%.*]] = sub i8 [[Y:%.*]], [[CNT]] +; CHECK-NEXT: ret i8 [[R]] +; + %nx = xor i8 %x, -1 + %cnt = call i8 @llvm.ctpop.i8(i8 %nx) + %r = sub i8 %y, %cnt + ret i8 %r +} + +define <2 x i8> @fold_sub_ctpop_c(<2 x i8> %x) { +; CHECK-LABEL: @fold_sub_ctpop_c( +; CHECK-NEXT: [[NX:%.*]] = xor <2 x i8> [[X:%.*]], <i8 -1, i8 -1> +; CHECK-NEXT: [[CNT:%.*]] = call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[NX]]), !range [[RNG0]] +; CHECK-NEXT: [[R:%.*]] = add nuw nsw <2 x i8> [[CNT]], <i8 -63, i8 -64> +; CHECK-NEXT: ret <2 x i8> [[R]] +; + %nx = xor <2 x i8> %x, <i8 -1, i8 -1> + %cnt = call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %nx) + %r = sub <2 x i8> %cnt, <i8 63, i8 64> + ret <2 x i8> %r +} + +define i8 @fold_add_ctpop_c(i8 %x) { +; CHECK-LABEL: @fold_add_ctpop_c( +; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1 +; CHECK-NEXT: [[CNT:%.*]] = call i8 @llvm.ctpop.i8(i8 [[NX]]), !range [[RNG0]] +; CHECK-NEXT: [[R:%.*]] = add nuw nsw i8 [[CNT]], 63 +; CHECK-NEXT: ret i8 [[R]] +; + %nx = xor i8 %x, -1 + %cnt = call i8 @llvm.ctpop.i8(i8 %nx) + %r = add i8 %cnt, 63 + ret i8 %r +} + +define i8 @fold_distjoint_or_ctpop_c(i8 %x) { +; CHECK-LABEL: @fold_distjoint_or_ctpop_c( +; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1 +; CHECK-NEXT: [[CNT:%.*]] = call i8 @llvm.ctpop.i8(i8 [[NX]]), !range [[RNG0]] +; CHECK-NEXT: [[R:%.*]] = or disjoint i8 [[CNT]], 64 +; CHECK-NEXT: ret i8 [[R]] +; + %nx = xor i8 %x, -1 + %cnt = call i8 @llvm.ctpop.i8(i8 %nx) + %r = or i8 %cnt, 64 + ret i8 %r +} + +define i8 @fold_or_ctpop_c_fail(i8 %x) { +; CHECK-LABEL: @fold_or_ctpop_c_fail( +; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1 +; CHECK-NEXT: [[CNT:%.*]] = call i8 @llvm.ctpop.i8(i8 [[NX]]), !range [[RNG0]] +; CHECK-NEXT: [[R:%.*]] = or i8 [[CNT]], 65 +; CHECK-NEXT: ret i8 [[R]] +; + %nx = xor i8 %x, -1 + %cnt = call i8 @llvm.ctpop.i8(i8 %nx) + %r = or i8 %cnt, 65 + ret i8 %r +} + +define i8 @fold_add_ctpop_var_fail(i8 %x, i8 %y) { +; CHECK-LABEL: @fold_add_ctpop_var_fail( +; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1 +; CHECK-NEXT: [[CNT:%.*]] = call i8 @llvm.ctpop.i8(i8 [[NX]]), !range [[RNG0]] +; CHECK-NEXT: [[R:%.*]] = add i8 [[CNT]], [[Y:%.*]] +; CHECK-NEXT: ret i8 [[R]] +; + %nx = xor i8 %x, -1 + %cnt = call i8 @llvm.ctpop.i8(i8 %nx) + %r = add i8 %cnt, %y + ret i8 %r +} + +define i1 @fold_icmp_sgt_ctpop_c_i2_fail(i2 %x, i2 %C) { +; CHECK-LABEL: @fold_icmp_sgt_ctpop_c_i2_fail( +; CHECK-NEXT: ret i1 false +; + %nx = xor i2 %x, -1 + %cnt = tail call i2 @llvm.ctpop.i2(i2 %nx) + %r = icmp sgt i2 %cnt, 1 + ret i1 %r +} + +define i1 @fold_cmp_eq_ctpop_c(i8 %x) { +; CHECK-LABEL: @fold_cmp_eq_ctpop_c( +; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1 +; CHECK-NEXT: [[CNT:%.*]] = call i8 @llvm.ctpop.i8(i8 [[NX]]), !range [[RNG0]] +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[CNT]], 2 +; CHECK-NEXT: ret i1 [[R]] +; + %nx = xor i8 %x, -1 + %cnt = call i8 @llvm.ctpop.i8(i8 %nx) + %r = icmp eq i8 %cnt, 2 + ret i1 %r +} + +define i1 @fold_cmp_eq_ctpop_c_multiuse_fail(i8 %x) { +; CHECK-LABEL: @fold_cmp_eq_ctpop_c_multiuse_fail( +; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1 +; CHECK-NEXT: [[CNT:%.*]] = call i8 @llvm.ctpop.i8(i8 [[NX]]), !range [[RNG0]] +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[CNT]], 2 +; CHECK-NEXT: call void @use.i8(i8 [[CNT]]) +; CHECK-NEXT: ret i1 [[R]] +; + %nx = xor i8 %x, -1 + %cnt = call i8 @llvm.ctpop.i8(i8 %nx) + %r = icmp eq i8 %cnt, 2 + call void @use.i8(i8 %cnt) + ret i1 %r +} + +define <2 x i1> @fold_cmp_ne_ctpop_c(<2 x i8> %x) { +; CHECK-LABEL: @fold_cmp_ne_ctpop_c( +; CHECK-NEXT: [[NX:%.*]] = xor <2 x i8> [[X:%.*]], <i8 -1, i8 -1> +; CHECK-NEXT: [[CNT:%.*]] = call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[NX]]), !range [[RNG0]] +; CHECK-NEXT: [[R:%.*]] = icmp ne <2 x i8> [[CNT]], <i8 44, i8 3> +; CHECK-NEXT: ret <2 x i1> [[R]] +; + %nx = xor <2 x i8> %x, <i8 -1, i8 -1> + %cnt = call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %nx) + %r = icmp ne <2 x i8> %cnt, <i8 44, i8 3> + ret <2 x i1> %r +} + +define <2 x i1> @fold_cmp_ne_ctpop_var_fail(<2 x i8> %x, <2 x i8> %y) { +; CHECK-LABEL: @fold_cmp_ne_ctpop_var_fail( +; CHECK-NEXT: [[NX:%.*]] = xor <2 x i8> [[X:%.*]], <i8 -1, i8 -1> +; CHECK-NEXT: [[CNT:%.*]] = call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[NX]]), !range [[RNG0]] +; CHECK-NEXT: [[R:%.*]] = icmp ne <2 x i8> [[CNT]], [[Y:%.*]] +; CHECK-NEXT: ret <2 x i1> [[R]] +; + %nx = xor <2 x i8> %x, <i8 -1, i8 -1> + %cnt = call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %nx) + %r = icmp ne <2 x i8> %cnt, %y + ret <2 x i1> %r +} + +define i1 @fold_cmp_ult_ctpop_c(i8 %x, i8 %y, i1 %cond) { +; CHECK-LABEL: @fold_cmp_ult_ctpop_c( +; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1 +; CHECK-NEXT: [[NY:%.*]] = add i8 [[Y:%.*]], 15 +; CHECK-NEXT: [[N:%.*]] = select i1 [[COND:%.*]], i8 [[NX]], i8 [[NY]] +; CHECK-NEXT: [[CNT:%.*]] = call i8 @llvm.ctpop.i8(i8 [[N]]), !range [[RNG0]] +; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[CNT]], 5 +; CHECK-NEXT: ret i1 [[R]] +; + %nx = xor i8 %x, -1 + %ny = add i8 %y, 15 + %n = select i1 %cond, i8 %nx, i8 %ny + %cnt = call i8 @llvm.ctpop.i8(i8 %n) + %r = icmp ult i8 %cnt, 5 + ret i1 %r +} + +define i1 @fold_cmp_sle_ctpop_c(i8 %x, i8 %y, i1 %cond) { +; CHECK-LABEL: @fold_cmp_sle_ctpop_c( +; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1 +; CHECK-NEXT: [[NY:%.*]] = add i8 [[Y:%.*]], 15 +; CHECK-NEXT: [[N:%.*]] = select i1 [[COND:%.*]], i8 [[NX]], i8 [[NY]] +; CHECK-NEXT: [[CNT:%.*]] = call i8 @llvm.ctpop.i8(i8 [[N]]), !range [[RNG0]] +; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[CNT]], 4 +; CHECK-NEXT: ret i1 [[R]] +; + %nx = xor i8 %x, -1 + %ny = add i8 %y, 15 + %n = select i1 %cond, i8 %nx, i8 %ny + %cnt = call i8 @llvm.ctpop.i8(i8 %n) + %r = icmp sle i8 %cnt, 3 + ret i1 %r +} + +define i1 @fold_cmp_ult_ctpop_c_no_not_inst_save_fail(i8 %x) { +; CHECK-LABEL: @fold_cmp_ult_ctpop_c_no_not_inst_save_fail( +; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -2 +; CHECK-NEXT: [[CNT:%.*]] = call i8 @llvm.ctpop.i8(i8 [[NX]]), !range [[RNG0]] +; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[CNT]], 5 +; CHECK-NEXT: ret i1 [[R]] +; + %nx = xor i8 %x, -2 + %cnt = call i8 @llvm.ctpop.i8(i8 %nx) + %r = icmp ult i8 %cnt, 5 + ret i1 %r +} + +define <2 x i1> @fold_cmp_ugt_ctpop_c(<2 x i8> %x) { +; CHECK-LABEL: @fold_cmp_ugt_ctpop_c( +; CHECK-NEXT: [[NX:%.*]] = xor <2 x i8> [[X:%.*]], <i8 -1, i8 -1> +; CHECK-NEXT: [[CNT:%.*]] = call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[NX]]), !range [[RNG0]] +; CHECK-NEXT: [[R:%.*]] = icmp ugt <2 x i8> [[CNT]], <i8 8, i8 6> +; CHECK-NEXT: ret <2 x i1> [[R]] +; + %nx = xor <2 x i8> %x, <i8 -1, i8 -1> + %cnt = call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %nx) + %r = icmp ugt <2 x i8> %cnt, <i8 8, i8 6> + ret <2 x i1> %r +} + +define <2 x i1> @fold_cmp_ugt_ctpop_c_out_of_range_fail(<2 x i8> %x) { +; CHECK-LABEL: @fold_cmp_ugt_ctpop_c_out_of_range_fail( +; CHECK-NEXT: [[NX:%.*]] = xor <2 x i8> [[X:%.*]], <i8 -1, i8 -1> +; CHECK-NEXT: [[CNT:%.*]] = call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[NX]]), !range [[RNG0]] +; CHECK-NEXT: [[R:%.*]] = icmp ugt <2 x i8> [[CNT]], <i8 2, i8 10> +; CHECK-NEXT: ret <2 x i1> [[R]] +; + %nx = xor <2 x i8> %x, <i8 -1, i8 -1> + %cnt = call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %nx) + %r = icmp ugt <2 x i8> %cnt, <i8 2, i8 10> + ret <2 x i1> %r +} |