diff options
author | David Bolvansky <david.bolvansky@gmail.com> | 2019-08-15 18:23:37 +0000 |
---|---|---|
committer | David Bolvansky <david.bolvansky@gmail.com> | 2019-08-15 18:23:37 +0000 |
commit | 00782a4b68c71b9fb80b403b13f9ec67f07a87a4 (patch) | |
tree | 4b0fcc920be0088b0b12c8101644963d2e5027cf /llvm/test/Transforms | |
parent | 2a372ba53403cae8a387a7b5e58640779ab2f742 (diff) | |
download | bcm5719-llvm-00782a4b68c71b9fb80b403b13f9ec67f07a87a4.tar.gz bcm5719-llvm-00782a4b68c71b9fb80b403b13f9ec67f07a87a4.zip |
[NFC] Added tests for 'select with ctlz to cttz' fold
llvm-svn: 369032
Diffstat (limited to 'llvm/test/Transforms')
-rw-r--r-- | llvm/test/Transforms/InstCombine/select-ctlz-to-cttz.ll | 249 |
1 files changed, 249 insertions, 0 deletions
diff --git a/llvm/test/Transforms/InstCombine/select-ctlz-to-cttz.ll b/llvm/test/Transforms/InstCombine/select-ctlz-to-cttz.ll new file mode 100644 index 00000000000..1726f4ef55e --- /dev/null +++ b/llvm/test/Transforms/InstCombine/select-ctlz-to-cttz.ll @@ -0,0 +1,249 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -instcombine -S < %s | FileCheck %s + + +declare i32 @llvm.cttz.i32(i32, i1 immarg) +declare i32 @llvm.ctlz.i32(i32, i1 immarg) +declare i64 @llvm.cttz.i64(i64, i1 immarg) +declare i64 @llvm.ctlz.i64(i64, i1 immarg) + +declare <2 x i32> @llvm.ctlz.v2i32(<2 x i32>, i1) +declare <2 x i32> @llvm.cttz.v2i32(<2 x i32>, i1) + + +declare void @use(i32) +declare void @use2(i1) + +define i32 @select_clz_to_ctz(i32 %a) { +; CHECK-LABEL: @select_clz_to_ctz( +; CHECK-NEXT: [[SUB:%.*]] = sub i32 0, [[A:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i32 [[SUB]], [[A]] +; CHECK-NEXT: [[LZ:%.*]] = tail call i32 @llvm.ctlz.i32(i32 [[AND]], i1 true), !range !0 +; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[A]], 0 +; CHECK-NEXT: [[SUB1:%.*]] = xor i32 [[LZ]], 31 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 [[LZ]], i32 [[SUB1]] +; CHECK-NEXT: ret i32 [[COND]] +; + %sub = sub i32 0, %a + %and = and i32 %sub, %a + %lz = tail call i32 @llvm.ctlz.i32(i32 %and, i1 true) + %tobool = icmp eq i32 %a, 0 + %sub1 = xor i32 %lz, 31 + %cond = select i1 %tobool, i32 %lz, i32 %sub1 + ret i32 %cond +} + +define i32 @select_clz_to_ctz_preserve_flag(i32 %a) { +; CHECK-LABEL: @select_clz_to_ctz_preserve_flag( +; CHECK-NEXT: [[SUB:%.*]] = sub i32 0, [[A:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i32 [[SUB]], [[A]] +; CHECK-NEXT: [[LZ:%.*]] = tail call i32 @llvm.ctlz.i32(i32 [[AND]], i1 false), !range !0 +; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[A]], 0 +; CHECK-NEXT: [[SUB1:%.*]] = xor i32 [[LZ]], 31 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 [[LZ]], i32 [[SUB1]] +; CHECK-NEXT: ret i32 [[COND]] +; + %sub = sub i32 0, %a + %and = and i32 %sub, %a + %lz = tail call i32 @llvm.ctlz.i32(i32 %and, i1 false) + %tobool = icmp eq i32 %a, 0 + %sub1 = xor i32 %lz, 31 + %cond = select i1 %tobool, i32 %lz, i32 %sub1 + ret i32 %cond +} + +define <2 x i32> @select_clz_to_ctz_vec(<2 x i32> %a) { +; CHECK-LABEL: @select_clz_to_ctz_vec( +; CHECK-NEXT: [[SUB:%.*]] = sub <2 x i32> zeroinitializer, [[A:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and <2 x i32> [[SUB]], [[A]] +; CHECK-NEXT: [[LZ:%.*]] = tail call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> [[AND]], i1 true) +; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq <2 x i32> [[A]], zeroinitializer +; CHECK-NEXT: [[SUB1:%.*]] = xor <2 x i32> [[LZ]], <i32 31, i32 31> +; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[TOBOOL]], <2 x i32> [[LZ]], <2 x i32> [[SUB1]] +; CHECK-NEXT: ret <2 x i32> [[COND]] +; + %sub = sub <2 x i32> zeroinitializer, %a + %and = and <2 x i32> %sub, %a + %lz = tail call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> %and, i1 true) + %tobool = icmp eq <2 x i32> %a, zeroinitializer + %sub1 = xor <2 x i32> %lz, <i32 31, i32 31> + %cond = select <2 x i1> %tobool, <2 x i32> %lz, <2 x i32> %sub1 + ret <2 x i32> %cond +} + +define i32 @select_clz_to_ctz_extra_use(i32 %a) { +; CHECK-LABEL: @select_clz_to_ctz_extra_use( +; CHECK-NEXT: [[SUB:%.*]] = sub i32 0, [[A:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i32 [[SUB]], [[A]] +; CHECK-NEXT: [[LZ:%.*]] = tail call i32 @llvm.ctlz.i32(i32 [[AND]], i1 true), !range !0 +; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[A]], 0 +; CHECK-NEXT: [[SUB1:%.*]] = xor i32 [[LZ]], 31 +; CHECK-NEXT: call void @use(i32 [[SUB1]]) +; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 [[LZ]], i32 [[SUB1]] +; CHECK-NEXT: ret i32 [[COND]] +; + %sub = sub i32 0, %a + %and = and i32 %sub, %a + %lz = tail call i32 @llvm.ctlz.i32(i32 %and, i1 true) + %tobool = icmp eq i32 %a, 0 + %sub1 = xor i32 %lz, 31 + call void @use(i32 %sub1) + %cond = select i1 %tobool, i32 %lz, i32 %sub1 + ret i32 %cond +} + +define i32 @select_clz_to_ctz_and_commuted(i32 %a) { +; CHECK-LABEL: @select_clz_to_ctz_and_commuted( +; CHECK-NEXT: [[SUB:%.*]] = sub i32 0, [[A:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i32 [[SUB]], [[A]] +; CHECK-NEXT: [[LZ:%.*]] = tail call i32 @llvm.ctlz.i32(i32 [[AND]], i1 true), !range !0 +; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[A]], 0 +; CHECK-NEXT: [[SUB1:%.*]] = xor i32 [[LZ]], 31 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 [[LZ]], i32 [[SUB1]] +; CHECK-NEXT: ret i32 [[COND]] +; + %sub = sub i32 0, %a + %and = and i32 %a, %sub + %lz = tail call i32 @llvm.ctlz.i32(i32 %and, i1 true) + %tobool = icmp eq i32 %a, 0 + %sub1 = xor i32 %lz, 31 + %cond = select i1 %tobool, i32 %lz, i32 %sub1 + ret i32 %cond +} + +define i32 @select_clz_to_ctz_icmp_ne(i32 %a) { +; CHECK-LABEL: @select_clz_to_ctz_icmp_ne( +; CHECK-NEXT: [[SUB:%.*]] = sub i32 0, [[A:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i32 [[SUB]], [[A]] +; CHECK-NEXT: [[LZ:%.*]] = tail call i32 @llvm.ctlz.i32(i32 [[AND]], i1 true), !range !0 +; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[A]], 0 +; CHECK-NEXT: call void @use2(i1 [[TOBOOL]]) +; CHECK-NEXT: [[SUB1:%.*]] = xor i32 [[LZ]], 31 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 [[SUB1]], i32 [[LZ]] +; CHECK-NEXT: ret i32 [[COND]] +; + %sub = sub i32 0, %a + %and = and i32 %sub, %a + %lz = tail call i32 @llvm.ctlz.i32(i32 %and, i1 true) + %tobool = icmp ne i32 %a, 0 + call void @use2(i1 %tobool) + %sub1 = xor i32 %lz, 31 + %cond = select i1 %tobool, i32 %sub1, i32 %lz + ret i32 %cond +} + +define i64 @select_clz_to_ctz_i64(i64 %a) { +; CHECK-LABEL: @select_clz_to_ctz_i64( +; CHECK-NEXT: [[SUB:%.*]] = sub i64 0, [[A:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i64 [[SUB]], [[A]] +; CHECK-NEXT: [[LZ:%.*]] = tail call i64 @llvm.ctlz.i64(i64 [[AND]], i1 true), !range !1 +; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i64 [[A]], 0 +; CHECK-NEXT: [[SUB1:%.*]] = xor i64 [[LZ]], 63 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i64 [[LZ]], i64 [[SUB1]] +; CHECK-NEXT: ret i64 [[COND]] +; + %sub = sub i64 0, %a + %and = and i64 %sub, %a + %lz = tail call i64 @llvm.ctlz.i64(i64 %and, i1 true) + %tobool = icmp eq i64 %a, 0 + %sub1 = xor i64 %lz, 63 + %cond = select i1 %tobool, i64 %lz, i64 %sub1 + ret i64 %cond +} + +; Negative tests + +define i32 @select_clz_to_ctz_wrong_sub(i32 %a) { +; CHECK-LABEL: @select_clz_to_ctz_wrong_sub( +; CHECK-NEXT: [[SUB:%.*]] = sub i32 1, [[A:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i32 [[SUB]], [[A]] +; CHECK-NEXT: [[LZ:%.*]] = tail call i32 @llvm.ctlz.i32(i32 [[AND]], i1 true), !range !0 +; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[A]], 0 +; CHECK-NEXT: [[SUB1:%.*]] = xor i32 [[LZ]], 31 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 [[LZ]], i32 [[SUB1]] +; CHECK-NEXT: ret i32 [[COND]] +; + %sub = sub i32 1, %a + %and = and i32 %sub, %a + %lz = tail call i32 @llvm.ctlz.i32(i32 %and, i1 true) + %tobool = icmp eq i32 %a, 0 + %sub1 = xor i32 %lz, 31 + %cond = select i1 %tobool, i32 %lz, i32 %sub1 + ret i32 %cond +} + +define i64 @select_clz_to_ctz_i64_wrong_xor(i64 %a) { +; CHECK-LABEL: @select_clz_to_ctz_i64_wrong_xor( +; CHECK-NEXT: [[SUB:%.*]] = sub i64 0, [[A:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i64 [[SUB]], [[A]] +; CHECK-NEXT: [[LZ:%.*]] = tail call i64 @llvm.ctlz.i64(i64 [[AND]], i1 true), !range !1 +; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i64 [[A]], 0 +; CHECK-NEXT: [[SUB11:%.*]] = or i64 [[LZ]], 64 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i64 [[LZ]], i64 [[SUB11]] +; CHECK-NEXT: ret i64 [[COND]] +; + %sub = sub i64 0, %a + %and = and i64 %sub, %a + %lz = tail call i64 @llvm.ctlz.i64(i64 %and, i1 true) + %tobool = icmp eq i64 %a, 0 + %sub1 = xor i64 %lz, 64 + %cond = select i1 %tobool, i64 %lz, i64 %sub1 + ret i64 %cond +} + +define i64 @select_clz_to_ctz_i64_wrong_icmp_cst(i64 %a) { +; CHECK-LABEL: @select_clz_to_ctz_i64_wrong_icmp_cst( +; CHECK-NEXT: [[SUB:%.*]] = sub i64 0, [[A:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i64 [[SUB]], [[A]] +; CHECK-NEXT: [[LZ:%.*]] = tail call i64 @llvm.ctlz.i64(i64 [[AND]], i1 true), !range !1 +; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i64 [[A]], 1 +; CHECK-NEXT: [[SUB1:%.*]] = xor i64 [[LZ]], 63 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i64 [[LZ]], i64 [[SUB1]] +; CHECK-NEXT: ret i64 [[COND]] +; + %sub = sub i64 0, %a + %and = and i64 %sub, %a + %lz = tail call i64 @llvm.ctlz.i64(i64 %and, i1 true) + %tobool = icmp eq i64 %a, 1 + %sub1 = xor i64 %lz, 63 + %cond = select i1 %tobool, i64 %lz, i64 %sub1 + ret i64 %cond +} + +define i64 @select_clz_to_ctz_i64_wrong_icmp_pred(i64 %a) { +; CHECK-LABEL: @select_clz_to_ctz_i64_wrong_icmp_pred( +; CHECK-NEXT: [[SUB:%.*]] = sub i64 0, [[A:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i64 [[SUB]], [[A]] +; CHECK-NEXT: [[LZ:%.*]] = tail call i64 @llvm.ctlz.i64(i64 [[AND]], i1 true), !range !1 +; CHECK-NEXT: [[TOBOOL:%.*]] = icmp slt i64 [[A]], 0 +; CHECK-NEXT: [[SUB1:%.*]] = xor i64 [[LZ]], 63 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i64 [[LZ]], i64 [[SUB1]] +; CHECK-NEXT: ret i64 [[COND]] +; + %sub = sub i64 0, %a + %and = and i64 %sub, %a + %lz = tail call i64 @llvm.ctlz.i64(i64 %and, i1 true) + %tobool = icmp slt i64 %a, 0 + %sub1 = xor i64 %lz, 63 + %cond = select i1 %tobool, i64 %lz, i64 %sub1 + ret i64 %cond +} + +define <2 x i32> @select_clz_to_ctz_vec_with_undef(<2 x i32> %a) { +; CHECK-LABEL: @select_clz_to_ctz_vec_with_undef( +; CHECK-NEXT: [[SUB:%.*]] = sub <2 x i32> zeroinitializer, [[A:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and <2 x i32> [[SUB]], [[A]] +; CHECK-NEXT: [[LZ:%.*]] = tail call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> [[AND]], i1 true) +; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq <2 x i32> [[A]], zeroinitializer +; CHECK-NEXT: [[SUB1:%.*]] = xor <2 x i32> [[LZ]], <i32 31, i32 undef> +; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[TOBOOL]], <2 x i32> [[LZ]], <2 x i32> [[SUB1]] +; CHECK-NEXT: ret <2 x i32> [[COND]] +; + %sub = sub <2 x i32> zeroinitializer, %a + %and = and <2 x i32> %sub, %a + %lz = tail call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> %and, i1 true) + %tobool = icmp eq <2 x i32> %a, zeroinitializer + %sub1 = xor <2 x i32> %lz, <i32 31, i32 undef> + %cond = select <2 x i1> %tobool, <2 x i32> %lz, <2 x i32> %sub1 + ret <2 x i32> %cond +} |