[llvm] r374726 - [NFC][InstCombine] More test for "sign bit test via shifts" pattern (PR43595)

Roman Lebedev via llvm-commits llvm-commits at lists.llvm.org
Sun Oct 13 10:11:17 PDT 2019


Author: lebedevri
Date: Sun Oct 13 10:11:16 2019
New Revision: 374726

URL: http://llvm.org/viewvc/llvm-project?rev=374726&view=rev
Log:
[NFC][InstCombine] More test for "sign bit test via shifts" pattern (PR43595)

While that pattern is indirectly handled via
reassociateShiftAmtsOfTwoSameDirectionShifts(),
that incursme one-use restriction on truncation,
which is pointless since we know that we'll produce a single instruction.

Additionally, *if* we are only looking for sign bit,
we don't need shifts to be identical,
which isn't the case in general,
and is the blocker for me in bug in question:

https://bugs.llvm.org/show_bug.cgi?id=43595

Modified:
    llvm/trunk/test/Transforms/InstCombine/shift-amount-reassociation-in-bittest.ll
    llvm/trunk/test/Transforms/InstCombine/shift-amount-reassociation-with-truncation-ashr.ll
    llvm/trunk/test/Transforms/InstCombine/shift-amount-reassociation-with-truncation-lshr.ll
    llvm/trunk/test/Transforms/InstCombine/shift-amount-reassociation-with-truncation-shl.ll
    llvm/trunk/test/Transforms/InstCombine/shift-amount-reassociation.ll
    llvm/trunk/test/Transforms/InstCombine/sign-bit-test-via-right-shifting-all-other-bits.ll

Modified: llvm/trunk/test/Transforms/InstCombine/shift-amount-reassociation-in-bittest.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/shift-amount-reassociation-in-bittest.ll?rev=374726&r1=374725&r2=374726&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/shift-amount-reassociation-in-bittest.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/shift-amount-reassociation-in-bittest.ll Sun Oct 13 10:11:16 2019
@@ -671,6 +671,14 @@ define <2 x i1> @n38_overshift(<2 x i32>
 ; As usual, don't crash given constantexpr's :/
 @f.a = internal global i16 0
 define i1 @constantexpr() {
+; CHECK-LABEL: @constantexpr(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i16, i16* @f.a, align 2
+; CHECK-NEXT:    [[TMP1:%.*]] = lshr i16 [[TMP0]], 1
+; CHECK-NEXT:    [[TMP2:%.*]] = and i16 [[TMP1]], shl (i16 1, i16 zext (i1 icmp ne (i16 ptrtoint (i16* @f.a to i16), i16 1) to i16))
+; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp ne i16 [[TMP2]], 0
+; CHECK-NEXT:    ret i1 [[TOBOOL]]
+;
 entry:
   %0 = load i16, i16* @f.a
   %shr = ashr i16 %0, 1

Modified: llvm/trunk/test/Transforms/InstCombine/shift-amount-reassociation-with-truncation-ashr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/shift-amount-reassociation-with-truncation-ashr.ll?rev=374726&r1=374725&r2=374726&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/shift-amount-reassociation-with-truncation-ashr.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/shift-amount-reassociation-with-truncation-ashr.ll Sun Oct 13 10:11:16 2019
@@ -166,7 +166,9 @@ define i16 @t9_ashr(i32 %x, i16 %y) {
 ; CHECK-NEXT:    [[T1:%.*]] = zext i16 [[T0]] to i32
 ; CHECK-NEXT:    [[T2:%.*]] = ashr i32 [[X:%.*]], [[T1]]
 ; CHECK-NEXT:    [[T3:%.*]] = trunc i32 [[T2]] to i16
-; CHECK-NEXT:    ret i16 [[T3]]
+; CHECK-NEXT:    [[T4:%.*]] = add i16 [[Y]], -2
+; CHECK-NEXT:    [[T5:%.*]] = ashr i16 [[T3]], [[T4]]
+; CHECK-NEXT:    ret i16 [[T5]]
 ;
   %t0 = sub i16 32, %y
   %t1 = zext i16 %t0 to i32
@@ -174,5 +176,25 @@ define i16 @t9_ashr(i32 %x, i16 %y) {
   %t3 = trunc i32 %t2 to i16
   %t4 = add i16 %y, -2
   %t5 = ashr i16 %t3, %t4
-  ret i16 %t3
+  ret i16 %t5
+}
+
+; If we have different right-shifts, in general, we can't do anything with it.
+define i16 @n10_lshr_ashr(i32 %x, i16 %y) {
+; CHECK-LABEL: @n10_lshr_ashr(
+; CHECK-NEXT:    [[T0:%.*]] = sub i16 32, [[Y:%.*]]
+; CHECK-NEXT:    [[T1:%.*]] = zext i16 [[T0]] to i32
+; CHECK-NEXT:    [[T2:%.*]] = lshr i32 [[X:%.*]], [[T1]]
+; CHECK-NEXT:    [[T3:%.*]] = trunc i32 [[T2]] to i16
+; CHECK-NEXT:    [[T4:%.*]] = add i16 [[Y]], -1
+; CHECK-NEXT:    [[T5:%.*]] = ashr i16 [[T3]], [[T4]]
+; CHECK-NEXT:    ret i16 [[T5]]
+;
+  %t0 = sub i16 32, %y
+  %t1 = zext i16 %t0 to i32
+  %t2 = lshr i32 %x, %t1
+  %t3 = trunc i32 %t2 to i16
+  %t4 = add i16 %y, -1
+  %t5 = ashr i16 %t3, %t4
+  ret i16 %t5
 }

Modified: llvm/trunk/test/Transforms/InstCombine/shift-amount-reassociation-with-truncation-lshr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/shift-amount-reassociation-with-truncation-lshr.ll?rev=374726&r1=374725&r2=374726&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/shift-amount-reassociation-with-truncation-lshr.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/shift-amount-reassociation-with-truncation-lshr.ll Sun Oct 13 10:11:16 2019
@@ -166,7 +166,9 @@ define i16 @t9_lshr(i32 %x, i16 %y) {
 ; CHECK-NEXT:    [[T1:%.*]] = zext i16 [[T0]] to i32
 ; CHECK-NEXT:    [[T2:%.*]] = lshr i32 [[X:%.*]], [[T1]]
 ; CHECK-NEXT:    [[T3:%.*]] = trunc i32 [[T2]] to i16
-; CHECK-NEXT:    ret i16 [[T3]]
+; CHECK-NEXT:    [[T4:%.*]] = add i16 [[Y]], -2
+; CHECK-NEXT:    [[T5:%.*]] = lshr i16 [[T3]], [[T4]]
+; CHECK-NEXT:    ret i16 [[T5]]
 ;
   %t0 = sub i16 32, %y
   %t1 = zext i16 %t0 to i32
@@ -174,5 +176,25 @@ define i16 @t9_lshr(i32 %x, i16 %y) {
   %t3 = trunc i32 %t2 to i16
   %t4 = add i16 %y, -2
   %t5 = lshr i16 %t3, %t4
-  ret i16 %t3
+  ret i16 %t5
+}
+
+; If we have different right-shifts, in general, we can't do anything with it.
+define i16 @n10_ashr_lshr(i32 %x, i16 %y) {
+; CHECK-LABEL: @n10_ashr_lshr(
+; CHECK-NEXT:    [[T0:%.*]] = sub i16 32, [[Y:%.*]]
+; CHECK-NEXT:    [[T1:%.*]] = zext i16 [[T0]] to i32
+; CHECK-NEXT:    [[T2:%.*]] = ashr i32 [[X:%.*]], [[T1]]
+; CHECK-NEXT:    [[T3:%.*]] = trunc i32 [[T2]] to i16
+; CHECK-NEXT:    [[T4:%.*]] = add i16 [[Y]], -1
+; CHECK-NEXT:    [[T5:%.*]] = lshr i16 [[T3]], [[T4]]
+; CHECK-NEXT:    ret i16 [[T5]]
+;
+  %t0 = sub i16 32, %y
+  %t1 = zext i16 %t0 to i32
+  %t2 = ashr i32 %x, %t1
+  %t3 = trunc i32 %t2 to i16
+  %t4 = add i16 %y, -1
+  %t5 = lshr i16 %t3, %t4
+  ret i16 %t5
 }

Modified: llvm/trunk/test/Transforms/InstCombine/shift-amount-reassociation-with-truncation-shl.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/shift-amount-reassociation-with-truncation-shl.ll?rev=374726&r1=374725&r2=374726&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/shift-amount-reassociation-with-truncation-shl.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/shift-amount-reassociation-with-truncation-shl.ll Sun Oct 13 10:11:16 2019
@@ -181,15 +181,17 @@ define i16 @n11(i32 %x, i16 %y) {
 ; CHECK-NEXT:    [[T1:%.*]] = zext i16 [[T0]] to i32
 ; CHECK-NEXT:    [[T2:%.*]] = shl i32 [[X:%.*]], [[T1]]
 ; CHECK-NEXT:    [[T3:%.*]] = trunc i32 [[T2]] to i16
-; CHECK-NEXT:    ret i16 [[T3]]
+; CHECK-NEXT:    [[T4:%.*]] = add i16 [[Y]], -31
+; CHECK-NEXT:    [[T5:%.*]] = shl i16 [[T3]], [[T4]]
+; CHECK-NEXT:    ret i16 [[T5]]
 ;
   %t0 = sub i16 30, %y
   %t1 = zext i16 %t0 to i32
   %t2 = shl i32 %x, %t1
   %t3 = trunc i32 %t2 to i16
-  %t4 = add i16 %y, -24
+  %t4 = add i16 %y, -31
   %t5 = shl i16 %t3, %t4
-  ret i16 %t3
+  ret i16 %t5
 }
 
 ; Bit width mismatch of shit amount

Modified: llvm/trunk/test/Transforms/InstCombine/shift-amount-reassociation.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/shift-amount-reassociation.ll?rev=374726&r1=374725&r2=374726&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/shift-amount-reassociation.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/shift-amount-reassociation.ll Sun Oct 13 10:11:16 2019
@@ -203,3 +203,119 @@ define <2 x i32> @t13_vec(<2 x i32> %x,
   %t3 = lshr <2 x i32> %t1, %t2
   ret <2 x i32> %t3
 }
+
+; If we have different right-shifts, in general, we can't do anything with it.
+define i32 @n13(i32 %x, i32 %y) {
+; CHECK-LABEL: @n13(
+; CHECK-NEXT:    [[T0:%.*]] = sub i32 32, [[Y:%.*]]
+; CHECK-NEXT:    [[T1:%.*]] = lshr i32 [[X:%.*]], [[T0]]
+; CHECK-NEXT:    [[T2:%.*]] = add i32 [[Y]], -2
+; CHECK-NEXT:    [[T3:%.*]] = ashr i32 [[T1]], [[T2]]
+; CHECK-NEXT:    ret i32 [[T3]]
+;
+  %t0 = sub i32 32, %y
+  %t1 = lshr i32 %x, %t0
+  %t2 = add i32 %y, -2
+  %t3 = ashr i32 %t1, %t2
+  ret i32 %t3
+}
+define i32 @n14(i32 %x, i32 %y) {
+; CHECK-LABEL: @n14(
+; CHECK-NEXT:    [[T0:%.*]] = sub i32 32, [[Y:%.*]]
+; CHECK-NEXT:    [[T1:%.*]] = lshr i32 [[X:%.*]], [[T0]]
+; CHECK-NEXT:    [[T2:%.*]] = add i32 [[Y]], -1
+; CHECK-NEXT:    [[T3:%.*]] = ashr i32 [[T1]], [[T2]]
+; CHECK-NEXT:    ret i32 [[T3]]
+;
+  %t0 = sub i32 32, %y
+  %t1 = lshr i32 %x, %t0
+  %t2 = add i32 %y, -1
+  %t3 = ashr i32 %t1, %t2
+  ret i32 %t3
+}
+define i32 @n15(i32 %x, i32 %y) {
+; CHECK-LABEL: @n15(
+; CHECK-NEXT:    [[T0:%.*]] = sub i32 32, [[Y:%.*]]
+; CHECK-NEXT:    [[T1:%.*]] = ashr i32 [[X:%.*]], [[T0]]
+; CHECK-NEXT:    [[T2:%.*]] = add i32 [[Y]], -2
+; CHECK-NEXT:    [[T3:%.*]] = lshr i32 [[T1]], [[T2]]
+; CHECK-NEXT:    ret i32 [[T3]]
+;
+  %t0 = sub i32 32, %y
+  %t1 = ashr i32 %x, %t0
+  %t2 = add i32 %y, -2
+  %t3 = lshr i32 %t1, %t2
+  ret i32 %t3
+}
+define i32 @n16(i32 %x, i32 %y) {
+; CHECK-LABEL: @n16(
+; CHECK-NEXT:    [[T0:%.*]] = sub i32 32, [[Y:%.*]]
+; CHECK-NEXT:    [[T1:%.*]] = ashr i32 [[X:%.*]], [[T0]]
+; CHECK-NEXT:    [[T2:%.*]] = add i32 [[Y]], -1
+; CHECK-NEXT:    [[T3:%.*]] = lshr i32 [[T1]], [[T2]]
+; CHECK-NEXT:    ret i32 [[T3]]
+;
+  %t0 = sub i32 32, %y
+  %t1 = ashr i32 %x, %t0
+  %t2 = add i32 %y, -1
+  %t3 = lshr i32 %t1, %t2
+  ret i32 %t3
+}
+
+; If the shift direction is different, then this should be handled elsewhere.
+define i32 @n17(i32 %x, i32 %y) {
+; CHECK-LABEL: @n17(
+; CHECK-NEXT:    [[T0:%.*]] = sub i32 32, [[Y:%.*]]
+; CHECK-NEXT:    [[T1:%.*]] = shl i32 [[X:%.*]], [[T0]]
+; CHECK-NEXT:    [[T2:%.*]] = add i32 [[Y]], -1
+; CHECK-NEXT:    [[T3:%.*]] = lshr i32 [[T1]], [[T2]]
+; CHECK-NEXT:    ret i32 [[T3]]
+;
+  %t0 = sub i32 32, %y
+  %t1 = shl i32 %x, %t0
+  %t2 = add i32 %y, -1
+  %t3 = lshr i32 %t1, %t2
+  ret i32 %t3
+}
+define i32 @n18(i32 %x, i32 %y) {
+; CHECK-LABEL: @n18(
+; CHECK-NEXT:    [[T0:%.*]] = sub i32 32, [[Y:%.*]]
+; CHECK-NEXT:    [[T1:%.*]] = shl i32 [[X:%.*]], [[T0]]
+; CHECK-NEXT:    [[T2:%.*]] = add i32 [[Y]], -1
+; CHECK-NEXT:    [[T3:%.*]] = ashr i32 [[T1]], [[T2]]
+; CHECK-NEXT:    ret i32 [[T3]]
+;
+  %t0 = sub i32 32, %y
+  %t1 = shl i32 %x, %t0
+  %t2 = add i32 %y, -1
+  %t3 = ashr i32 %t1, %t2
+  ret i32 %t3
+}
+define i32 @n19(i32 %x, i32 %y) {
+; CHECK-LABEL: @n19(
+; CHECK-NEXT:    [[T0:%.*]] = sub i32 32, [[Y:%.*]]
+; CHECK-NEXT:    [[T1:%.*]] = lshr i32 [[X:%.*]], [[T0]]
+; CHECK-NEXT:    [[T2:%.*]] = add i32 [[Y]], -1
+; CHECK-NEXT:    [[T3:%.*]] = shl i32 [[T1]], [[T2]]
+; CHECK-NEXT:    ret i32 [[T3]]
+;
+  %t0 = sub i32 32, %y
+  %t1 = lshr i32 %x, %t0
+  %t2 = add i32 %y, -1
+  %t3 = shl i32 %t1, %t2
+  ret i32 %t3
+}
+define i32 @n20(i32 %x, i32 %y) {
+; CHECK-LABEL: @n20(
+; CHECK-NEXT:    [[T0:%.*]] = sub i32 32, [[Y:%.*]]
+; CHECK-NEXT:    [[T1:%.*]] = ashr i32 [[X:%.*]], [[T0]]
+; CHECK-NEXT:    [[T2:%.*]] = add i32 [[Y]], -1
+; CHECK-NEXT:    [[T3:%.*]] = shl i32 [[T1]], [[T2]]
+; CHECK-NEXT:    ret i32 [[T3]]
+;
+  %t0 = sub i32 32, %y
+  %t1 = ashr i32 %x, %t0
+  %t2 = add i32 %y, -1
+  %t3 = shl i32 %t1, %t2
+  ret i32 %t3
+}

Modified: llvm/trunk/test/Transforms/InstCombine/sign-bit-test-via-right-shifting-all-other-bits.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/sign-bit-test-via-right-shifting-all-other-bits.ll?rev=374726&r1=374725&r2=374726&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/sign-bit-test-via-right-shifting-all-other-bits.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/sign-bit-test-via-right-shifting-all-other-bits.ll Sun Oct 13 10:11:16 2019
@@ -1,22 +1,51 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
 ; RUN: opt < %s -instcombine -S | FileCheck %s
 
+declare void @use32(i32)
+declare void @use64(i64)
+
 define i1 @highest_bit_test_via_lshr(i32 %data, i32 %nbits) {
 ; CHECK-LABEL: @highest_bit_test_via_lshr(
-; CHECK-NEXT:    [[ISNEG:%.*]] = icmp slt i32 [[DATA:%.*]], 0
+; CHECK-NEXT:    [[NUM_LOW_BITS_TO_SKIP:%.*]] = sub i32 32, [[NBITS:%.*]]
+; CHECK-NEXT:    [[HIGH_BITS_EXTRACTED:%.*]] = lshr i32 [[DATA:%.*]], [[NUM_LOW_BITS_TO_SKIP]]
+; CHECK-NEXT:    [[SKIP_ALL_BITS_TILL_SIGNBIT:%.*]] = add i32 [[NBITS]], -1
+; CHECK-NEXT:    [[SIGNBIT:%.*]] = lshr i32 [[DATA]], 31
+; CHECK-NEXT:    call void @use32(i32 [[NUM_LOW_BITS_TO_SKIP]])
+; CHECK-NEXT:    call void @use32(i32 [[HIGH_BITS_EXTRACTED]])
+; CHECK-NEXT:    call void @use32(i32 [[SKIP_ALL_BITS_TILL_SIGNBIT]])
+; CHECK-NEXT:    call void @use32(i32 [[SIGNBIT]])
+; CHECK-NEXT:    [[ISNEG:%.*]] = icmp slt i32 [[DATA]], 0
 ; CHECK-NEXT:    ret i1 [[ISNEG]]
 ;
   %num_low_bits_to_skip = sub i32 32, %nbits
   %high_bits_extracted = lshr i32 %data, %num_low_bits_to_skip
   %skip_all_bits_till_signbit = sub i32 %nbits, 1
   %signbit = lshr i32 %high_bits_extracted, %skip_all_bits_till_signbit
+
+  call void @use32(i32 %num_low_bits_to_skip)
+  call void @use32(i32 %high_bits_extracted)
+  call void @use32(i32 %skip_all_bits_till_signbit)
+  call void @use32(i32 %signbit)
+
   %isneg = icmp ne i32 %signbit, 0
   ret i1 %isneg
 }
 
 define i1 @highest_bit_test_via_lshr_with_truncation(i64 %data, i32 %nbits) {
 ; CHECK-LABEL: @highest_bit_test_via_lshr_with_truncation(
-; CHECK-NEXT:    [[ISNEG:%.*]] = icmp slt i64 [[DATA:%.*]], 0
+; CHECK-NEXT:    [[NUM_LOW_BITS_TO_SKIP:%.*]] = sub i32 64, [[NBITS:%.*]]
+; CHECK-NEXT:    [[NUM_LOW_BITS_TO_SKIP_WIDE:%.*]] = zext i32 [[NUM_LOW_BITS_TO_SKIP]] to i64
+; CHECK-NEXT:    [[HIGH_BITS_EXTRACTED:%.*]] = lshr i64 [[DATA:%.*]], [[NUM_LOW_BITS_TO_SKIP_WIDE]]
+; CHECK-NEXT:    [[HIGH_BITS_EXTRACTED_NARROW:%.*]] = trunc i64 [[HIGH_BITS_EXTRACTED]] to i32
+; CHECK-NEXT:    [[SKIP_ALL_BITS_TILL_SIGNBIT:%.*]] = add i32 [[NBITS]], -1
+; CHECK-NEXT:    [[SIGNBIT:%.*]] = lshr i32 [[HIGH_BITS_EXTRACTED_NARROW]], [[SKIP_ALL_BITS_TILL_SIGNBIT]]
+; CHECK-NEXT:    call void @use32(i32 [[NUM_LOW_BITS_TO_SKIP]])
+; CHECK-NEXT:    call void @use64(i64 [[NUM_LOW_BITS_TO_SKIP_WIDE]])
+; CHECK-NEXT:    call void @use64(i64 [[HIGH_BITS_EXTRACTED]])
+; CHECK-NEXT:    call void @use32(i32 [[HIGH_BITS_EXTRACTED_NARROW]])
+; CHECK-NEXT:    call void @use32(i32 [[SKIP_ALL_BITS_TILL_SIGNBIT]])
+; CHECK-NEXT:    call void @use32(i32 [[SIGNBIT]])
+; CHECK-NEXT:    [[ISNEG:%.*]] = icmp ne i32 [[SIGNBIT]], 0
 ; CHECK-NEXT:    ret i1 [[ISNEG]]
 ;
   %num_low_bits_to_skip = sub i32 64, %nbits
@@ -25,26 +54,60 @@ define i1 @highest_bit_test_via_lshr_wit
   %high_bits_extracted_narrow = trunc i64 %high_bits_extracted to i32
   %skip_all_bits_till_signbit = sub i32 %nbits, 1
   %signbit = lshr i32 %high_bits_extracted_narrow, %skip_all_bits_till_signbit
+
+  call void @use32(i32 %num_low_bits_to_skip)
+  call void @use64(i64 %num_low_bits_to_skip_wide)
+  call void @use64(i64 %high_bits_extracted)
+  call void @use32(i32 %high_bits_extracted_narrow)
+  call void @use32(i32 %skip_all_bits_till_signbit)
+  call void @use32(i32 %signbit)
+
   %isneg = icmp ne i32 %signbit, 0
   ret i1 %isneg
 }
 
 define i1 @highest_bit_test_via_ashr(i32 %data, i32 %nbits) {
 ; CHECK-LABEL: @highest_bit_test_via_ashr(
-; CHECK-NEXT:    [[ISNEG:%.*]] = icmp slt i32 [[DATA:%.*]], 0
+; CHECK-NEXT:    [[NUM_LOW_BITS_TO_SKIP:%.*]] = sub i32 32, [[NBITS:%.*]]
+; CHECK-NEXT:    [[HIGH_BITS_EXTRACTED:%.*]] = ashr i32 [[DATA:%.*]], [[NUM_LOW_BITS_TO_SKIP]]
+; CHECK-NEXT:    [[SKIP_ALL_BITS_TILL_SIGNBIT:%.*]] = add i32 [[NBITS]], -1
+; CHECK-NEXT:    [[SIGNBIT:%.*]] = ashr i32 [[DATA]], 31
+; CHECK-NEXT:    call void @use32(i32 [[NUM_LOW_BITS_TO_SKIP]])
+; CHECK-NEXT:    call void @use32(i32 [[HIGH_BITS_EXTRACTED]])
+; CHECK-NEXT:    call void @use32(i32 [[SKIP_ALL_BITS_TILL_SIGNBIT]])
+; CHECK-NEXT:    call void @use32(i32 [[SIGNBIT]])
+; CHECK-NEXT:    [[ISNEG:%.*]] = icmp slt i32 [[DATA]], 0
 ; CHECK-NEXT:    ret i1 [[ISNEG]]
 ;
   %num_low_bits_to_skip = sub i32 32, %nbits
   %high_bits_extracted = ashr i32 %data, %num_low_bits_to_skip
   %skip_all_bits_till_signbit = sub i32 %nbits, 1
   %signbit = ashr i32 %high_bits_extracted, %skip_all_bits_till_signbit
+
+  call void @use32(i32 %num_low_bits_to_skip)
+  call void @use32(i32 %high_bits_extracted)
+  call void @use32(i32 %skip_all_bits_till_signbit)
+  call void @use32(i32 %signbit)
+
   %isneg = icmp ne i32 %signbit, 0
   ret i1 %isneg
 }
 
 define i1 @highest_bit_test_via_ashr_with_truncation(i64 %data, i32 %nbits) {
 ; CHECK-LABEL: @highest_bit_test_via_ashr_with_truncation(
-; CHECK-NEXT:    [[ISNEG:%.*]] = icmp slt i64 [[DATA:%.*]], 0
+; CHECK-NEXT:    [[NUM_LOW_BITS_TO_SKIP:%.*]] = sub i32 64, [[NBITS:%.*]]
+; CHECK-NEXT:    [[NUM_LOW_BITS_TO_SKIP_WIDE:%.*]] = zext i32 [[NUM_LOW_BITS_TO_SKIP]] to i64
+; CHECK-NEXT:    [[HIGH_BITS_EXTRACTED:%.*]] = ashr i64 [[DATA:%.*]], [[NUM_LOW_BITS_TO_SKIP_WIDE]]
+; CHECK-NEXT:    [[HIGH_BITS_EXTRACTED_NARROW:%.*]] = trunc i64 [[HIGH_BITS_EXTRACTED]] to i32
+; CHECK-NEXT:    [[SKIP_ALL_BITS_TILL_SIGNBIT:%.*]] = add i32 [[NBITS]], -1
+; CHECK-NEXT:    [[SIGNBIT:%.*]] = ashr i32 [[HIGH_BITS_EXTRACTED_NARROW]], [[SKIP_ALL_BITS_TILL_SIGNBIT]]
+; CHECK-NEXT:    call void @use32(i32 [[NUM_LOW_BITS_TO_SKIP]])
+; CHECK-NEXT:    call void @use64(i64 [[NUM_LOW_BITS_TO_SKIP_WIDE]])
+; CHECK-NEXT:    call void @use64(i64 [[HIGH_BITS_EXTRACTED]])
+; CHECK-NEXT:    call void @use32(i32 [[HIGH_BITS_EXTRACTED_NARROW]])
+; CHECK-NEXT:    call void @use32(i32 [[SKIP_ALL_BITS_TILL_SIGNBIT]])
+; CHECK-NEXT:    call void @use32(i32 [[SIGNBIT]])
+; CHECK-NEXT:    [[ISNEG:%.*]] = icmp ne i32 [[SIGNBIT]], 0
 ; CHECK-NEXT:    ret i1 [[ISNEG]]
 ;
   %num_low_bits_to_skip = sub i32 64, %nbits
@@ -53,12 +116,143 @@ define i1 @highest_bit_test_via_ashr_wit
   %high_bits_extracted_narrow = trunc i64 %high_bits_extracted to i32
   %skip_all_bits_till_signbit = sub i32 %nbits, 1
   %signbit = ashr i32 %high_bits_extracted_narrow, %skip_all_bits_till_signbit
+
+  call void @use32(i32 %num_low_bits_to_skip)
+  call void @use64(i64 %num_low_bits_to_skip_wide)
+  call void @use64(i64 %high_bits_extracted)
+  call void @use32(i32 %high_bits_extracted_narrow)
+  call void @use32(i32 %skip_all_bits_till_signbit)
+  call void @use32(i32 %signbit)
+
   %isneg = icmp ne i32 %signbit, 0
   ret i1 %isneg
 }
 
-declare void @use32(i32)
-declare void @use64(i64)
+define i1 @highest_bit_test_via_lshr_ashr(i32 %data, i32 %nbits) {
+; CHECK-LABEL: @highest_bit_test_via_lshr_ashr(
+; CHECK-NEXT:    [[NUM_LOW_BITS_TO_SKIP:%.*]] = sub i32 32, [[NBITS:%.*]]
+; CHECK-NEXT:    [[HIGH_BITS_EXTRACTED:%.*]] = lshr i32 [[DATA:%.*]], [[NUM_LOW_BITS_TO_SKIP]]
+; CHECK-NEXT:    [[SKIP_ALL_BITS_TILL_SIGNBIT:%.*]] = add i32 [[NBITS]], -1
+; CHECK-NEXT:    [[SIGNBIT:%.*]] = ashr i32 [[HIGH_BITS_EXTRACTED]], [[SKIP_ALL_BITS_TILL_SIGNBIT]]
+; CHECK-NEXT:    call void @use32(i32 [[NUM_LOW_BITS_TO_SKIP]])
+; CHECK-NEXT:    call void @use32(i32 [[HIGH_BITS_EXTRACTED]])
+; CHECK-NEXT:    call void @use32(i32 [[SKIP_ALL_BITS_TILL_SIGNBIT]])
+; CHECK-NEXT:    call void @use32(i32 [[SIGNBIT]])
+; CHECK-NEXT:    [[ISNEG:%.*]] = icmp ne i32 [[SIGNBIT]], 0
+; CHECK-NEXT:    ret i1 [[ISNEG]]
+;
+  %num_low_bits_to_skip = sub i32 32, %nbits
+  %high_bits_extracted = lshr i32 %data, %num_low_bits_to_skip
+  %skip_all_bits_till_signbit = sub i32 %nbits, 1
+  %signbit = ashr i32 %high_bits_extracted, %skip_all_bits_till_signbit
+
+  call void @use32(i32 %num_low_bits_to_skip)
+  call void @use32(i32 %high_bits_extracted)
+  call void @use32(i32 %skip_all_bits_till_signbit)
+  call void @use32(i32 %signbit)
+
+  %isneg = icmp ne i32 %signbit, 0
+  ret i1 %isneg
+}
+
+define i1 @highest_bit_test_via_lshr_ashe_with_truncation(i64 %data, i32 %nbits) {
+; CHECK-LABEL: @highest_bit_test_via_lshr_ashe_with_truncation(
+; CHECK-NEXT:    [[NUM_LOW_BITS_TO_SKIP:%.*]] = sub i32 64, [[NBITS:%.*]]
+; CHECK-NEXT:    [[NUM_LOW_BITS_TO_SKIP_WIDE:%.*]] = zext i32 [[NUM_LOW_BITS_TO_SKIP]] to i64
+; CHECK-NEXT:    [[HIGH_BITS_EXTRACTED:%.*]] = lshr i64 [[DATA:%.*]], [[NUM_LOW_BITS_TO_SKIP_WIDE]]
+; CHECK-NEXT:    [[HIGH_BITS_EXTRACTED_NARROW:%.*]] = trunc i64 [[HIGH_BITS_EXTRACTED]] to i32
+; CHECK-NEXT:    [[SKIP_ALL_BITS_TILL_SIGNBIT:%.*]] = add i32 [[NBITS]], -1
+; CHECK-NEXT:    [[SIGNBIT:%.*]] = ashr i32 [[HIGH_BITS_EXTRACTED_NARROW]], [[SKIP_ALL_BITS_TILL_SIGNBIT]]
+; CHECK-NEXT:    call void @use32(i32 [[NUM_LOW_BITS_TO_SKIP]])
+; CHECK-NEXT:    call void @use64(i64 [[NUM_LOW_BITS_TO_SKIP_WIDE]])
+; CHECK-NEXT:    call void @use64(i64 [[HIGH_BITS_EXTRACTED]])
+; CHECK-NEXT:    call void @use32(i32 [[HIGH_BITS_EXTRACTED_NARROW]])
+; CHECK-NEXT:    call void @use32(i32 [[SKIP_ALL_BITS_TILL_SIGNBIT]])
+; CHECK-NEXT:    call void @use32(i32 [[SIGNBIT]])
+; CHECK-NEXT:    [[ISNEG:%.*]] = icmp ne i32 [[SIGNBIT]], 0
+; CHECK-NEXT:    ret i1 [[ISNEG]]
+;
+  %num_low_bits_to_skip = sub i32 64, %nbits
+  %num_low_bits_to_skip_wide = zext i32 %num_low_bits_to_skip to i64
+  %high_bits_extracted = lshr i64 %data, %num_low_bits_to_skip_wide
+  %high_bits_extracted_narrow = trunc i64 %high_bits_extracted to i32
+  %skip_all_bits_till_signbit = sub i32 %nbits, 1
+  %signbit = ashr i32 %high_bits_extracted_narrow, %skip_all_bits_till_signbit
+
+  call void @use32(i32 %num_low_bits_to_skip)
+  call void @use64(i64 %num_low_bits_to_skip_wide)
+  call void @use64(i64 %high_bits_extracted)
+  call void @use32(i32 %high_bits_extracted_narrow)
+  call void @use32(i32 %skip_all_bits_till_signbit)
+  call void @use32(i32 %signbit)
+
+  %isneg = icmp ne i32 %signbit, 0
+  ret i1 %isneg
+}
+
+define i1 @highest_bit_test_via_ashr_lshr(i32 %data, i32 %nbits) {
+; CHECK-LABEL: @highest_bit_test_via_ashr_lshr(
+; CHECK-NEXT:    [[NUM_LOW_BITS_TO_SKIP:%.*]] = sub i32 32, [[NBITS:%.*]]
+; CHECK-NEXT:    [[HIGH_BITS_EXTRACTED:%.*]] = ashr i32 [[DATA:%.*]], [[NUM_LOW_BITS_TO_SKIP]]
+; CHECK-NEXT:    [[SKIP_ALL_BITS_TILL_SIGNBIT:%.*]] = add i32 [[NBITS]], -1
+; CHECK-NEXT:    [[SIGNBIT:%.*]] = lshr i32 [[HIGH_BITS_EXTRACTED]], [[SKIP_ALL_BITS_TILL_SIGNBIT]]
+; CHECK-NEXT:    call void @use32(i32 [[NUM_LOW_BITS_TO_SKIP]])
+; CHECK-NEXT:    call void @use32(i32 [[HIGH_BITS_EXTRACTED]])
+; CHECK-NEXT:    call void @use32(i32 [[SKIP_ALL_BITS_TILL_SIGNBIT]])
+; CHECK-NEXT:    call void @use32(i32 [[SIGNBIT]])
+; CHECK-NEXT:    [[ISNEG:%.*]] = icmp ne i32 [[SIGNBIT]], 0
+; CHECK-NEXT:    ret i1 [[ISNEG]]
+;
+  %num_low_bits_to_skip = sub i32 32, %nbits
+  %high_bits_extracted = ashr i32 %data, %num_low_bits_to_skip
+  %skip_all_bits_till_signbit = sub i32 %nbits, 1
+  %signbit = lshr i32 %high_bits_extracted, %skip_all_bits_till_signbit
+
+  call void @use32(i32 %num_low_bits_to_skip)
+  call void @use32(i32 %high_bits_extracted)
+  call void @use32(i32 %skip_all_bits_till_signbit)
+  call void @use32(i32 %signbit)
+
+  %isneg = icmp ne i32 %signbit, 0
+  ret i1 %isneg
+}
+
+define i1 @highest_bit_test_via_ashr_lshr_with_truncation(i64 %data, i32 %nbits) {
+; CHECK-LABEL: @highest_bit_test_via_ashr_lshr_with_truncation(
+; CHECK-NEXT:    [[NUM_LOW_BITS_TO_SKIP:%.*]] = sub i32 64, [[NBITS:%.*]]
+; CHECK-NEXT:    [[NUM_LOW_BITS_TO_SKIP_WIDE:%.*]] = zext i32 [[NUM_LOW_BITS_TO_SKIP]] to i64
+; CHECK-NEXT:    [[HIGH_BITS_EXTRACTED:%.*]] = ashr i64 [[DATA:%.*]], [[NUM_LOW_BITS_TO_SKIP_WIDE]]
+; CHECK-NEXT:    [[HIGH_BITS_EXTRACTED_NARROW:%.*]] = trunc i64 [[HIGH_BITS_EXTRACTED]] to i32
+; CHECK-NEXT:    [[SKIP_ALL_BITS_TILL_SIGNBIT:%.*]] = add i32 [[NBITS]], -1
+; CHECK-NEXT:    [[SIGNBIT:%.*]] = lshr i32 [[HIGH_BITS_EXTRACTED_NARROW]], [[SKIP_ALL_BITS_TILL_SIGNBIT]]
+; CHECK-NEXT:    call void @use32(i32 [[NUM_LOW_BITS_TO_SKIP]])
+; CHECK-NEXT:    call void @use64(i64 [[NUM_LOW_BITS_TO_SKIP_WIDE]])
+; CHECK-NEXT:    call void @use64(i64 [[HIGH_BITS_EXTRACTED]])
+; CHECK-NEXT:    call void @use32(i32 [[HIGH_BITS_EXTRACTED_NARROW]])
+; CHECK-NEXT:    call void @use32(i32 [[SKIP_ALL_BITS_TILL_SIGNBIT]])
+; CHECK-NEXT:    call void @use32(i32 [[SIGNBIT]])
+; CHECK-NEXT:    [[ISNEG:%.*]] = icmp ne i32 [[SIGNBIT]], 0
+; CHECK-NEXT:    ret i1 [[ISNEG]]
+;
+  %num_low_bits_to_skip = sub i32 64, %nbits
+  %num_low_bits_to_skip_wide = zext i32 %num_low_bits_to_skip to i64
+  %high_bits_extracted = ashr i64 %data, %num_low_bits_to_skip_wide
+  %high_bits_extracted_narrow = trunc i64 %high_bits_extracted to i32
+  %skip_all_bits_till_signbit = sub i32 %nbits, 1
+  %signbit = lshr i32 %high_bits_extracted_narrow, %skip_all_bits_till_signbit
+
+  call void @use32(i32 %num_low_bits_to_skip)
+  call void @use64(i64 %num_low_bits_to_skip_wide)
+  call void @use64(i64 %high_bits_extracted)
+  call void @use32(i32 %high_bits_extracted_narrow)
+  call void @use32(i32 %skip_all_bits_till_signbit)
+  call void @use32(i32 %signbit)
+
+  %isneg = icmp ne i32 %signbit, 0
+  ret i1 %isneg
+}
+
+;------------------------------------------------------------------------------;
 
 define i1 @unsigned_sign_bit_extract(i32 %x) {
 ; CHECK-LABEL: @unsigned_sign_bit_extract(




More information about the llvm-commits mailing list