[llvm] r369032 - [NFC] Added tests for 'select with ctlz to cttz' fold

David Bolvansky via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 15 11:23:37 PDT 2019


Author: xbolva00
Date: Thu Aug 15 11:23:37 2019
New Revision: 369032

URL: http://llvm.org/viewvc/llvm-project?rev=369032&view=rev
Log:
[NFC] Added tests for 'select with ctlz to cttz' fold

Added:
    llvm/trunk/test/Transforms/InstCombine/select-ctlz-to-cttz.ll

Added: llvm/trunk/test/Transforms/InstCombine/select-ctlz-to-cttz.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/select-ctlz-to-cttz.ll?rev=369032&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/select-ctlz-to-cttz.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/select-ctlz-to-cttz.ll Thu Aug 15 11:23:37 2019
@@ -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
+}




More information about the llvm-commits mailing list