%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
+}
; 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
%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
%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(