1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 18:54:02 +01:00
llvm-mirror/test/Transforms/InstCombine/conditional-variable-length-signext-after-high-bit-extract.ll
Sanjay Patel bf8ef9fdc3 [InstCombine] use redirect of input file in regression tests; NFC
This is a repeat of 1880092722 from 2009. We should have less risk
of hitting bugs at this point because we auto-generate positive CHECK
lines only, but this makes things consistent.

Copying the original commit msg:
"Change tests from "opt %s" to "opt < %s" so that opt doesn't see the
input filename so that opt doesn't print the input filename in the
output so that grep lines in the tests don't unintentionally match
strings in the input filename."
2020-09-29 11:06:25 -04:00

1140 lines
55 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -instcombine -S | FileCheck %s
; If we extract (via lshr) some high bits, and then perform their sign-extension
; conditionally depending on whether the extracted value is negative or not
; (i.e. interpreting the highest extracted bit, which was the original signbit
; of the value from which we extracted as a signbit), then we should just
; perform extraction via `ashr`.
; Base patterns.
declare void @use1(i1)
declare void @use16(i16)
declare void @use32(i32)
declare void @use64(i64)
define i32 @t0_notrunc_add(i32 %data, i32 %nbits) {
; CHECK-LABEL: @t0_notrunc_add(
; CHECK-NEXT: [[LOW_BITS_TO_SKIP:%.*]] = sub i32 32, [[NBITS:%.*]]
; CHECK-NEXT: [[HIGH_BITS_EXTRACTED:%.*]] = lshr i32 [[DATA:%.*]], [[LOW_BITS_TO_SKIP]]
; CHECK-NEXT: [[SHOULD_SIGNEXT:%.*]] = icmp slt i32 [[DATA]], 0
; CHECK-NEXT: [[ALL_BITS_EXCEPT_LOW_NBITS:%.*]] = shl i32 -1, [[NBITS]]
; CHECK-NEXT: [[MAGIC:%.*]] = select i1 [[SHOULD_SIGNEXT]], i32 [[ALL_BITS_EXCEPT_LOW_NBITS]], i32 0
; CHECK-NEXT: call void @use32(i32 [[LOW_BITS_TO_SKIP]])
; CHECK-NEXT: call void @use32(i32 [[HIGH_BITS_EXTRACTED]])
; CHECK-NEXT: call void @use1(i1 [[SHOULD_SIGNEXT]])
; CHECK-NEXT: call void @use32(i32 [[ALL_BITS_EXCEPT_LOW_NBITS]])
; CHECK-NEXT: call void @use32(i32 [[MAGIC]])
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = ashr i32 [[DATA]], [[LOW_BITS_TO_SKIP]]
; CHECK-NEXT: ret i32 [[SIGNEXTENDED]]
;
%low_bits_to_skip = sub i32 32, %nbits
%high_bits_extracted = lshr i32 %data, %low_bits_to_skip
%should_signext = icmp slt i32 %data, 0
%all_bits_except_low_nbits = shl i32 -1, %nbits
%magic = select i1 %should_signext, i32 %all_bits_except_low_nbits, i32 0
call void @use32(i32 %low_bits_to_skip)
call void @use32(i32 %high_bits_extracted)
call void @use1(i1 %should_signext)
call void @use32(i32 %all_bits_except_low_nbits)
call void @use32(i32 %magic)
%signextended = add i32 %high_bits_extracted, %magic
ret i32 %signextended
}
define i32 @t0_notrunc_or(i32 %data, i32 %nbits) {
; CHECK-LABEL: @t0_notrunc_or(
; CHECK-NEXT: [[LOW_BITS_TO_SKIP:%.*]] = sub i32 32, [[NBITS:%.*]]
; CHECK-NEXT: [[HIGH_BITS_EXTRACTED:%.*]] = lshr i32 [[DATA:%.*]], [[LOW_BITS_TO_SKIP]]
; CHECK-NEXT: [[SHOULD_SIGNEXT:%.*]] = icmp slt i32 [[DATA]], 0
; CHECK-NEXT: [[ALL_BITS_EXCEPT_LOW_NBITS:%.*]] = shl i32 -1, [[NBITS]]
; CHECK-NEXT: [[MAGIC:%.*]] = select i1 [[SHOULD_SIGNEXT]], i32 [[ALL_BITS_EXCEPT_LOW_NBITS]], i32 0
; CHECK-NEXT: call void @use32(i32 [[LOW_BITS_TO_SKIP]])
; CHECK-NEXT: call void @use32(i32 [[HIGH_BITS_EXTRACTED]])
; CHECK-NEXT: call void @use1(i1 [[SHOULD_SIGNEXT]])
; CHECK-NEXT: call void @use32(i32 [[ALL_BITS_EXCEPT_LOW_NBITS]])
; CHECK-NEXT: call void @use32(i32 [[MAGIC]])
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = ashr i32 [[DATA]], [[LOW_BITS_TO_SKIP]]
; CHECK-NEXT: ret i32 [[SIGNEXTENDED]]
;
%low_bits_to_skip = sub i32 32, %nbits
%high_bits_extracted = lshr i32 %data, %low_bits_to_skip
%should_signext = icmp slt i32 %data, 0
%all_bits_except_low_nbits = shl i32 -1, %nbits
%magic = select i1 %should_signext, i32 %all_bits_except_low_nbits, i32 0
call void @use32(i32 %low_bits_to_skip)
call void @use32(i32 %high_bits_extracted)
call void @use1(i1 %should_signext)
call void @use32(i32 %all_bits_except_low_nbits)
call void @use32(i32 %magic)
%signextended = or i32 %high_bits_extracted, %magic
ret i32 %signextended
}
define i32 @t1_notrunc_sub(i32 %data, i32 %nbits) {
; CHECK-LABEL: @t1_notrunc_sub(
; CHECK-NEXT: [[LOW_BITS_TO_SKIP:%.*]] = sub i32 32, [[NBITS:%.*]]
; CHECK-NEXT: [[HIGH_BITS_EXTRACTED:%.*]] = lshr i32 [[DATA:%.*]], [[LOW_BITS_TO_SKIP]]
; CHECK-NEXT: [[SHOULD_SIGNEXT:%.*]] = icmp slt i32 [[DATA]], 0
; CHECK-NEXT: [[HIGHER_BIT_AFTER_SIGNBIT:%.*]] = shl i32 1, [[NBITS]]
; CHECK-NEXT: [[MAGIC:%.*]] = select i1 [[SHOULD_SIGNEXT]], i32 [[HIGHER_BIT_AFTER_SIGNBIT]], i32 0
; CHECK-NEXT: call void @use32(i32 [[LOW_BITS_TO_SKIP]])
; CHECK-NEXT: call void @use32(i32 [[HIGH_BITS_EXTRACTED]])
; CHECK-NEXT: call void @use1(i1 [[SHOULD_SIGNEXT]])
; CHECK-NEXT: call void @use32(i32 [[HIGHER_BIT_AFTER_SIGNBIT]])
; CHECK-NEXT: call void @use32(i32 [[MAGIC]])
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = ashr i32 [[DATA]], [[LOW_BITS_TO_SKIP]]
; CHECK-NEXT: ret i32 [[SIGNEXTENDED]]
;
%low_bits_to_skip = sub i32 32, %nbits
%high_bits_extracted = lshr i32 %data, %low_bits_to_skip
%should_signext = icmp slt i32 %data, 0
%higher_bit_after_signbit = shl i32 1, %nbits
%magic = select i1 %should_signext, i32 %higher_bit_after_signbit, i32 0
call void @use32(i32 %low_bits_to_skip)
call void @use32(i32 %high_bits_extracted)
call void @use1(i1 %should_signext)
call void @use32(i32 %higher_bit_after_signbit)
call void @use32(i32 %magic)
%signextended = sub i32 %high_bits_extracted, %magic
ret i32 %signextended
}
define i32 @t2_trunc_add(i64 %data, i32 %nbits) {
; CHECK-LABEL: @t2_trunc_add(
; CHECK-NEXT: [[LOW_BITS_TO_SKIP:%.*]] = sub i32 64, [[NBITS:%.*]]
; CHECK-NEXT: [[LOW_BITS_TO_SKIP_WIDE:%.*]] = zext i32 [[LOW_BITS_TO_SKIP]] to i64
; CHECK-NEXT: [[HIGH_BITS_EXTRACTED_WIDE:%.*]] = lshr i64 [[DATA:%.*]], [[LOW_BITS_TO_SKIP_WIDE]]
; CHECK-NEXT: [[HIGH_BITS_EXTRACTED:%.*]] = trunc i64 [[HIGH_BITS_EXTRACTED_WIDE]] to i32
; CHECK-NEXT: [[SHOULD_SIGNEXT:%.*]] = icmp slt i64 [[DATA]], 0
; CHECK-NEXT: [[ALL_BITS_EXCEPT_LOW_NBITS:%.*]] = shl i32 -1, [[NBITS]]
; CHECK-NEXT: call void @use32(i32 [[LOW_BITS_TO_SKIP]])
; CHECK-NEXT: call void @use64(i64 [[LOW_BITS_TO_SKIP_WIDE]])
; CHECK-NEXT: call void @use64(i64 [[HIGH_BITS_EXTRACTED_WIDE]])
; CHECK-NEXT: call void @use32(i32 [[HIGH_BITS_EXTRACTED]])
; CHECK-NEXT: call void @use1(i1 [[SHOULD_SIGNEXT]])
; CHECK-NEXT: call void @use32(i32 [[ALL_BITS_EXCEPT_LOW_NBITS]])
; CHECK-NEXT: [[TMP1:%.*]] = ashr i64 [[DATA]], [[LOW_BITS_TO_SKIP_WIDE]]
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = trunc i64 [[TMP1]] to i32
; CHECK-NEXT: ret i32 [[SIGNEXTENDED]]
;
%low_bits_to_skip = sub i32 64, %nbits
%low_bits_to_skip_wide = zext i32 %low_bits_to_skip to i64
%high_bits_extracted_wide = lshr i64 %data, %low_bits_to_skip_wide
%high_bits_extracted = trunc i64 %high_bits_extracted_wide to i32
%should_signext = icmp slt i64 %data, 0
%all_bits_except_low_nbits = shl i32 -1, %nbits
%magic = select i1 %should_signext, i32 %all_bits_except_low_nbits, i32 0 ; one-use
call void @use32(i32 %low_bits_to_skip)
call void @use64(i64 %low_bits_to_skip_wide)
call void @use64(i64 %high_bits_extracted_wide)
call void @use32(i32 %high_bits_extracted)
call void @use1(i1 %should_signext)
call void @use32(i32 %all_bits_except_low_nbits)
%signextended = add i32 %magic, %high_bits_extracted
ret i32 %signextended
}
define i32 @t2_trunc_or(i64 %data, i32 %nbits) {
; CHECK-LABEL: @t2_trunc_or(
; CHECK-NEXT: [[LOW_BITS_TO_SKIP:%.*]] = sub i32 64, [[NBITS:%.*]]
; CHECK-NEXT: [[LOW_BITS_TO_SKIP_WIDE:%.*]] = zext i32 [[LOW_BITS_TO_SKIP]] to i64
; CHECK-NEXT: [[HIGH_BITS_EXTRACTED_WIDE:%.*]] = lshr i64 [[DATA:%.*]], [[LOW_BITS_TO_SKIP_WIDE]]
; CHECK-NEXT: [[HIGH_BITS_EXTRACTED:%.*]] = trunc i64 [[HIGH_BITS_EXTRACTED_WIDE]] to i32
; CHECK-NEXT: [[SHOULD_SIGNEXT:%.*]] = icmp slt i64 [[DATA]], 0
; CHECK-NEXT: [[ALL_BITS_EXCEPT_LOW_NBITS:%.*]] = shl i32 -1, [[NBITS]]
; CHECK-NEXT: call void @use32(i32 [[LOW_BITS_TO_SKIP]])
; CHECK-NEXT: call void @use64(i64 [[LOW_BITS_TO_SKIP_WIDE]])
; CHECK-NEXT: call void @use64(i64 [[HIGH_BITS_EXTRACTED_WIDE]])
; CHECK-NEXT: call void @use32(i32 [[HIGH_BITS_EXTRACTED]])
; CHECK-NEXT: call void @use1(i1 [[SHOULD_SIGNEXT]])
; CHECK-NEXT: call void @use32(i32 [[ALL_BITS_EXCEPT_LOW_NBITS]])
; CHECK-NEXT: [[TMP1:%.*]] = ashr i64 [[DATA]], [[LOW_BITS_TO_SKIP_WIDE]]
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = trunc i64 [[TMP1]] to i32
; CHECK-NEXT: ret i32 [[SIGNEXTENDED]]
;
%low_bits_to_skip = sub i32 64, %nbits
%low_bits_to_skip_wide = zext i32 %low_bits_to_skip to i64
%high_bits_extracted_wide = lshr i64 %data, %low_bits_to_skip_wide
%high_bits_extracted = trunc i64 %high_bits_extracted_wide to i32
%should_signext = icmp slt i64 %data, 0
%all_bits_except_low_nbits = shl i32 -1, %nbits
%magic = select i1 %should_signext, i32 %all_bits_except_low_nbits, i32 0 ; one-use
call void @use32(i32 %low_bits_to_skip)
call void @use64(i64 %low_bits_to_skip_wide)
call void @use64(i64 %high_bits_extracted_wide)
call void @use32(i32 %high_bits_extracted)
call void @use1(i1 %should_signext)
call void @use32(i32 %all_bits_except_low_nbits)
%signextended = or i32 %magic, %high_bits_extracted
ret i32 %signextended
}
define i32 @t3_trunc_sub(i64 %data, i32 %nbits) {
; CHECK-LABEL: @t3_trunc_sub(
; CHECK-NEXT: [[LOW_BITS_TO_SKIP:%.*]] = sub i32 64, [[NBITS:%.*]]
; CHECK-NEXT: [[LOW_BITS_TO_SKIP_WIDE:%.*]] = zext i32 [[LOW_BITS_TO_SKIP]] to i64
; CHECK-NEXT: [[HIGH_BITS_EXTRACTED_WIDE:%.*]] = lshr i64 [[DATA:%.*]], [[LOW_BITS_TO_SKIP_WIDE]]
; CHECK-NEXT: [[HIGH_BITS_EXTRACTED:%.*]] = trunc i64 [[HIGH_BITS_EXTRACTED_WIDE]] to i32
; CHECK-NEXT: [[SHOULD_SIGNEXT:%.*]] = icmp slt i64 [[DATA]], 0
; CHECK-NEXT: [[HIGHER_BIT_AFTER_SIGNBIT:%.*]] = shl i32 1, [[NBITS]]
; CHECK-NEXT: call void @use32(i32 [[LOW_BITS_TO_SKIP]])
; CHECK-NEXT: call void @use64(i64 [[LOW_BITS_TO_SKIP_WIDE]])
; CHECK-NEXT: call void @use64(i64 [[HIGH_BITS_EXTRACTED_WIDE]])
; CHECK-NEXT: call void @use32(i32 [[HIGH_BITS_EXTRACTED]])
; CHECK-NEXT: call void @use1(i1 [[SHOULD_SIGNEXT]])
; CHECK-NEXT: call void @use32(i32 [[HIGHER_BIT_AFTER_SIGNBIT]])
; CHECK-NEXT: [[TMP1:%.*]] = ashr i64 [[DATA]], [[LOW_BITS_TO_SKIP_WIDE]]
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = trunc i64 [[TMP1]] to i32
; CHECK-NEXT: ret i32 [[SIGNEXTENDED]]
;
%low_bits_to_skip = sub i32 64, %nbits
%low_bits_to_skip_wide = zext i32 %low_bits_to_skip to i64
%high_bits_extracted_wide = lshr i64 %data, %low_bits_to_skip_wide
%high_bits_extracted = trunc i64 %high_bits_extracted_wide to i32
%should_signext = icmp slt i64 %data, 0
%higher_bit_after_signbit = shl i32 1, %nbits
%magic = select i1 %should_signext, i32 %higher_bit_after_signbit, i32 0 ; one-use
call void @use32(i32 %low_bits_to_skip)
call void @use64(i64 %low_bits_to_skip_wide)
call void @use64(i64 %high_bits_extracted_wide)
call void @use32(i32 %high_bits_extracted)
call void @use1(i1 %should_signext)
call void @use32(i32 %higher_bit_after_signbit)
%signextended = sub i32 %high_bits_extracted, %magic
ret i32 %signextended
}
; Commutativity
define i32 @t4_commutativity0(i32 %data, i32 %nbits) {
; CHECK-LABEL: @t4_commutativity0(
; CHECK-NEXT: [[LOW_BITS_TO_SKIP:%.*]] = sub i32 32, [[NBITS:%.*]]
; CHECK-NEXT: [[HIGH_BITS_EXTRACTED:%.*]] = lshr i32 [[DATA:%.*]], [[LOW_BITS_TO_SKIP]]
; CHECK-NEXT: [[SHOULD_SIGNEXT:%.*]] = icmp slt i32 [[DATA]], 0
; CHECK-NEXT: [[ALL_BITS_EXCEPT_LOW_NBITS:%.*]] = shl i32 -1, [[NBITS]]
; CHECK-NEXT: [[MAGIC:%.*]] = select i1 [[SHOULD_SIGNEXT]], i32 [[ALL_BITS_EXCEPT_LOW_NBITS]], i32 0
; CHECK-NEXT: call void @use32(i32 [[LOW_BITS_TO_SKIP]])
; CHECK-NEXT: call void @use32(i32 [[HIGH_BITS_EXTRACTED]])
; CHECK-NEXT: call void @use1(i1 [[SHOULD_SIGNEXT]])
; CHECK-NEXT: call void @use32(i32 [[ALL_BITS_EXCEPT_LOW_NBITS]])
; CHECK-NEXT: call void @use32(i32 [[MAGIC]])
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = ashr i32 [[DATA]], [[LOW_BITS_TO_SKIP]]
; CHECK-NEXT: ret i32 [[SIGNEXTENDED]]
;
%low_bits_to_skip = sub i32 32, %nbits
%high_bits_extracted = lshr i32 %data, %low_bits_to_skip
%should_signext = icmp slt i32 %data, 0
%all_bits_except_low_nbits = shl i32 -1, %nbits
%magic = select i1 %should_signext, i32 %all_bits_except_low_nbits, i32 0
call void @use32(i32 %low_bits_to_skip)
call void @use32(i32 %high_bits_extracted)
call void @use1(i1 %should_signext)
call void @use32(i32 %all_bits_except_low_nbits)
call void @use32(i32 %magic)
%signextended = add i32 %high_bits_extracted, %magic
ret i32 %signextended
}
define i32 @t5_commutativity1(i32 %data, i32 %nbits) {
; CHECK-LABEL: @t5_commutativity1(
; CHECK-NEXT: [[LOW_BITS_TO_SKIP:%.*]] = sub i32 32, [[NBITS:%.*]]
; CHECK-NEXT: [[HIGH_BITS_EXTRACTED:%.*]] = lshr i32 [[DATA:%.*]], [[LOW_BITS_TO_SKIP]]
; CHECK-NEXT: [[SHOULD_SIGNEXT:%.*]] = icmp sgt i32 [[DATA]], -1
; CHECK-NEXT: [[ALL_BITS_EXCEPT_LOW_NBITS:%.*]] = shl i32 -1, [[NBITS]]
; CHECK-NEXT: [[MAGIC:%.*]] = select i1 [[SHOULD_SIGNEXT]], i32 0, i32 [[ALL_BITS_EXCEPT_LOW_NBITS]]
; CHECK-NEXT: call void @use32(i32 [[LOW_BITS_TO_SKIP]])
; CHECK-NEXT: call void @use32(i32 [[HIGH_BITS_EXTRACTED]])
; CHECK-NEXT: call void @use1(i1 [[SHOULD_SIGNEXT]])
; CHECK-NEXT: call void @use32(i32 [[ALL_BITS_EXCEPT_LOW_NBITS]])
; CHECK-NEXT: call void @use32(i32 [[MAGIC]])
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = ashr i32 [[DATA]], [[LOW_BITS_TO_SKIP]]
; CHECK-NEXT: ret i32 [[SIGNEXTENDED]]
;
%low_bits_to_skip = sub i32 32, %nbits
%high_bits_extracted = lshr i32 %data, %low_bits_to_skip
%should_signext = icmp sgt i32 %data, -1 ; swapped
%all_bits_except_low_nbits = shl i32 -1, %nbits
%magic = select i1 %should_signext, i32 0, i32 %all_bits_except_low_nbits ; swapped
call void @use32(i32 %low_bits_to_skip)
call void @use32(i32 %high_bits_extracted)
call void @use1(i1 %should_signext)
call void @use32(i32 %all_bits_except_low_nbits)
call void @use32(i32 %magic)
%signextended = add i32 %high_bits_extracted, %magic
ret i32 %signextended
}
define i32 @t6_commutativity2(i32 %data, i32 %nbits) {
; CHECK-LABEL: @t6_commutativity2(
; CHECK-NEXT: [[LOW_BITS_TO_SKIP:%.*]] = sub i32 32, [[NBITS:%.*]]
; CHECK-NEXT: [[HIGH_BITS_EXTRACTED:%.*]] = lshr i32 [[DATA:%.*]], [[LOW_BITS_TO_SKIP]]
; CHECK-NEXT: [[SHOULD_SIGNEXT:%.*]] = icmp slt i32 [[DATA]], 0
; CHECK-NEXT: [[ALL_BITS_EXCEPT_LOW_NBITS:%.*]] = shl i32 -1, [[NBITS]]
; CHECK-NEXT: [[MAGIC:%.*]] = select i1 [[SHOULD_SIGNEXT]], i32 [[ALL_BITS_EXCEPT_LOW_NBITS]], i32 0
; CHECK-NEXT: call void @use32(i32 [[LOW_BITS_TO_SKIP]])
; CHECK-NEXT: call void @use32(i32 [[HIGH_BITS_EXTRACTED]])
; CHECK-NEXT: call void @use1(i1 [[SHOULD_SIGNEXT]])
; CHECK-NEXT: call void @use32(i32 [[ALL_BITS_EXCEPT_LOW_NBITS]])
; CHECK-NEXT: call void @use32(i32 [[MAGIC]])
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = ashr i32 [[DATA]], [[LOW_BITS_TO_SKIP]]
; CHECK-NEXT: ret i32 [[SIGNEXTENDED]]
;
%low_bits_to_skip = sub i32 32, %nbits
%high_bits_extracted = lshr i32 %data, %low_bits_to_skip
%should_signext = icmp slt i32 %data, 0
%all_bits_except_low_nbits = shl i32 -1, %nbits
%magic = select i1 %should_signext, i32 %all_bits_except_low_nbits, i32 0
call void @use32(i32 %low_bits_to_skip)
call void @use32(i32 %high_bits_extracted)
call void @use1(i1 %should_signext)
call void @use32(i32 %all_bits_except_low_nbits)
call void @use32(i32 %magic)
%signextended = add i32 %magic, %high_bits_extracted ; swapped
ret i32 %signextended
}
; Extra uses
define i32 @t7_trunc_extrause0(i64 %data, i32 %nbits) {
; CHECK-LABEL: @t7_trunc_extrause0(
; CHECK-NEXT: [[LOW_BITS_TO_SKIP:%.*]] = sub i32 64, [[NBITS:%.*]]
; CHECK-NEXT: [[LOW_BITS_TO_SKIP_WIDE:%.*]] = zext i32 [[LOW_BITS_TO_SKIP]] to i64
; CHECK-NEXT: [[HIGH_BITS_EXTRACTED_WIDE:%.*]] = lshr i64 [[DATA:%.*]], [[LOW_BITS_TO_SKIP_WIDE]]
; CHECK-NEXT: [[HIGH_BITS_EXTRACTED:%.*]] = trunc i64 [[HIGH_BITS_EXTRACTED_WIDE]] to i32
; CHECK-NEXT: [[SHOULD_SIGNEXT:%.*]] = icmp slt i64 [[DATA]], 0
; CHECK-NEXT: [[ALL_BITS_EXCEPT_LOW_NBITS:%.*]] = shl i32 -1, [[NBITS]]
; CHECK-NEXT: call void @use32(i32 [[LOW_BITS_TO_SKIP]])
; CHECK-NEXT: call void @use64(i64 [[LOW_BITS_TO_SKIP_WIDE]])
; CHECK-NEXT: call void @use64(i64 [[HIGH_BITS_EXTRACTED_WIDE]])
; CHECK-NEXT: call void @use32(i32 [[HIGH_BITS_EXTRACTED]])
; CHECK-NEXT: call void @use1(i1 [[SHOULD_SIGNEXT]])
; CHECK-NEXT: call void @use32(i32 [[ALL_BITS_EXCEPT_LOW_NBITS]])
; CHECK-NEXT: [[TMP1:%.*]] = ashr i64 [[DATA]], [[LOW_BITS_TO_SKIP_WIDE]]
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = trunc i64 [[TMP1]] to i32
; CHECK-NEXT: ret i32 [[SIGNEXTENDED]]
;
%low_bits_to_skip = sub i32 64, %nbits
%low_bits_to_skip_wide = zext i32 %low_bits_to_skip to i64
%high_bits_extracted_wide = lshr i64 %data, %low_bits_to_skip_wide
%high_bits_extracted = trunc i64 %high_bits_extracted_wide to i32 ; has extra use
%should_signext = icmp slt i64 %data, 0
%all_bits_except_low_nbits = shl i32 -1, %nbits
%magic = select i1 %should_signext, i32 %all_bits_except_low_nbits, i32 0 ; one-use
call void @use32(i32 %low_bits_to_skip)
call void @use64(i64 %low_bits_to_skip_wide)
call void @use64(i64 %high_bits_extracted_wide)
call void @use32(i32 %high_bits_extracted)
call void @use1(i1 %should_signext)
call void @use32(i32 %all_bits_except_low_nbits)
%signextended = add i32 %magic, %high_bits_extracted
ret i32 %signextended
}
define i32 @t8_trunc_extrause1(i64 %data, i32 %nbits) {
; CHECK-LABEL: @t8_trunc_extrause1(
; CHECK-NEXT: [[LOW_BITS_TO_SKIP:%.*]] = sub i32 64, [[NBITS:%.*]]
; CHECK-NEXT: [[LOW_BITS_TO_SKIP_WIDE:%.*]] = zext i32 [[LOW_BITS_TO_SKIP]] to i64
; CHECK-NEXT: [[HIGH_BITS_EXTRACTED_WIDE:%.*]] = lshr i64 [[DATA:%.*]], [[LOW_BITS_TO_SKIP_WIDE]]
; CHECK-NEXT: [[SHOULD_SIGNEXT:%.*]] = icmp slt i64 [[DATA]], 0
; CHECK-NEXT: [[ALL_BITS_EXCEPT_LOW_NBITS:%.*]] = shl i32 -1, [[NBITS]]
; CHECK-NEXT: [[MAGIC:%.*]] = select i1 [[SHOULD_SIGNEXT]], i32 [[ALL_BITS_EXCEPT_LOW_NBITS]], i32 0
; CHECK-NEXT: call void @use32(i32 [[LOW_BITS_TO_SKIP]])
; CHECK-NEXT: call void @use64(i64 [[LOW_BITS_TO_SKIP_WIDE]])
; CHECK-NEXT: call void @use64(i64 [[HIGH_BITS_EXTRACTED_WIDE]])
; CHECK-NEXT: call void @use1(i1 [[SHOULD_SIGNEXT]])
; CHECK-NEXT: call void @use32(i32 [[ALL_BITS_EXCEPT_LOW_NBITS]])
; CHECK-NEXT: call void @use32(i32 [[MAGIC]])
; CHECK-NEXT: [[TMP1:%.*]] = ashr i64 [[DATA]], [[LOW_BITS_TO_SKIP_WIDE]]
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = trunc i64 [[TMP1]] to i32
; CHECK-NEXT: ret i32 [[SIGNEXTENDED]]
;
%low_bits_to_skip = sub i32 64, %nbits
%low_bits_to_skip_wide = zext i32 %low_bits_to_skip to i64
%high_bits_extracted_wide = lshr i64 %data, %low_bits_to_skip_wide
%high_bits_extracted = trunc i64 %high_bits_extracted_wide to i32 ; one-use
%should_signext = icmp slt i64 %data, 0
%all_bits_except_low_nbits = shl i32 -1, %nbits
%magic = select i1 %should_signext, i32 %all_bits_except_low_nbits, i32 0 ; has extra use
call void @use32(i32 %low_bits_to_skip)
call void @use64(i64 %low_bits_to_skip_wide)
call void @use64(i64 %high_bits_extracted_wide)
call void @use1(i1 %should_signext)
call void @use32(i32 %all_bits_except_low_nbits)
call void @use32(i32 %magic)
%signextended = add i32 %magic, %high_bits_extracted
ret i32 %signextended
}
define i32 @n9_trunc_extrause2(i64 %data, i32 %nbits) {
; CHECK-LABEL: @n9_trunc_extrause2(
; CHECK-NEXT: [[LOW_BITS_TO_SKIP:%.*]] = sub i32 64, [[NBITS:%.*]]
; CHECK-NEXT: [[LOW_BITS_TO_SKIP_WIDE:%.*]] = zext i32 [[LOW_BITS_TO_SKIP]] to i64
; CHECK-NEXT: [[HIGH_BITS_EXTRACTED_WIDE:%.*]] = lshr i64 [[DATA:%.*]], [[LOW_BITS_TO_SKIP_WIDE]]
; CHECK-NEXT: [[HIGH_BITS_EXTRACTED:%.*]] = trunc i64 [[HIGH_BITS_EXTRACTED_WIDE]] to i32
; CHECK-NEXT: [[SHOULD_SIGNEXT:%.*]] = icmp slt i64 [[DATA]], 0
; CHECK-NEXT: [[ALL_BITS_EXCEPT_LOW_NBITS:%.*]] = shl i32 -1, [[NBITS]]
; CHECK-NEXT: [[MAGIC:%.*]] = select i1 [[SHOULD_SIGNEXT]], i32 [[ALL_BITS_EXCEPT_LOW_NBITS]], i32 0
; CHECK-NEXT: call void @use32(i32 [[LOW_BITS_TO_SKIP]])
; CHECK-NEXT: call void @use64(i64 [[LOW_BITS_TO_SKIP_WIDE]])
; CHECK-NEXT: call void @use64(i64 [[HIGH_BITS_EXTRACTED_WIDE]])
; CHECK-NEXT: call void @use32(i32 [[HIGH_BITS_EXTRACTED]])
; CHECK-NEXT: call void @use1(i1 [[SHOULD_SIGNEXT]])
; CHECK-NEXT: call void @use32(i32 [[ALL_BITS_EXCEPT_LOW_NBITS]])
; CHECK-NEXT: call void @use32(i32 [[MAGIC]])
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = add i32 [[MAGIC]], [[HIGH_BITS_EXTRACTED]]
; CHECK-NEXT: ret i32 [[SIGNEXTENDED]]
;
%low_bits_to_skip = sub i32 64, %nbits
%low_bits_to_skip_wide = zext i32 %low_bits_to_skip to i64
%high_bits_extracted_wide = lshr i64 %data, %low_bits_to_skip_wide
%high_bits_extracted = trunc i64 %high_bits_extracted_wide to i32 ; has extra use
%should_signext = icmp slt i64 %data, 0
%all_bits_except_low_nbits = shl i32 -1, %nbits
%magic = select i1 %should_signext, i32 %all_bits_except_low_nbits, i32 0 ; has extra use
call void @use32(i32 %low_bits_to_skip)
call void @use64(i64 %low_bits_to_skip_wide)
call void @use64(i64 %high_bits_extracted_wide)
call void @use32(i32 %high_bits_extracted)
call void @use1(i1 %should_signext)
call void @use32(i32 %all_bits_except_low_nbits)
call void @use32(i32 %magic)
%signextended = add i32 %magic, %high_bits_extracted
ret i32 %signextended
}
define i32 @t10_preserve_exact(i32 %data, i32 %nbits) {
; CHECK-LABEL: @t10_preserve_exact(
; CHECK-NEXT: [[LOW_BITS_TO_SKIP:%.*]] = sub i32 32, [[NBITS:%.*]]
; CHECK-NEXT: [[HIGH_BITS_EXTRACTED:%.*]] = lshr exact i32 [[DATA:%.*]], [[LOW_BITS_TO_SKIP]]
; CHECK-NEXT: [[SHOULD_SIGNEXT:%.*]] = icmp slt i32 [[DATA]], 0
; CHECK-NEXT: [[ALL_BITS_EXCEPT_LOW_NBITS:%.*]] = shl i32 -1, [[NBITS]]
; CHECK-NEXT: [[MAGIC:%.*]] = select i1 [[SHOULD_SIGNEXT]], i32 [[ALL_BITS_EXCEPT_LOW_NBITS]], i32 0
; CHECK-NEXT: call void @use32(i32 [[LOW_BITS_TO_SKIP]])
; CHECK-NEXT: call void @use32(i32 [[HIGH_BITS_EXTRACTED]])
; CHECK-NEXT: call void @use1(i1 [[SHOULD_SIGNEXT]])
; CHECK-NEXT: call void @use32(i32 [[ALL_BITS_EXCEPT_LOW_NBITS]])
; CHECK-NEXT: call void @use32(i32 [[MAGIC]])
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = ashr exact i32 [[DATA]], [[LOW_BITS_TO_SKIP]]
; CHECK-NEXT: ret i32 [[SIGNEXTENDED]]
;
%low_bits_to_skip = sub i32 32, %nbits
%high_bits_extracted = lshr exact i32 %data, %low_bits_to_skip
%should_signext = icmp slt i32 %data, 0
%all_bits_except_low_nbits = shl i32 -1, %nbits
%magic = select i1 %should_signext, i32 %all_bits_except_low_nbits, i32 0
call void @use32(i32 %low_bits_to_skip)
call void @use32(i32 %high_bits_extracted)
call void @use1(i1 %should_signext)
call void @use32(i32 %all_bits_except_low_nbits)
call void @use32(i32 %magic)
%signextended = add i32 %high_bits_extracted, %magic
ret i32 %signextended
}
define i32 @t11_different_zext_of_shamt(i32 %data, i8 %nbits) {
; CHECK-LABEL: @t11_different_zext_of_shamt(
; CHECK-NEXT: [[NBITS_16BIT:%.*]] = zext i8 [[NBITS:%.*]] to i16
; CHECK-NEXT: [[LOW_BITS_TO_SKIP:%.*]] = sub nsw i16 32, [[NBITS_16BIT]]
; CHECK-NEXT: [[LOW_BITS_TO_SKIP_32:%.*]] = zext i16 [[LOW_BITS_TO_SKIP]] to i32
; CHECK-NEXT: [[HIGH_BITS_EXTRACTED:%.*]] = lshr i32 [[DATA:%.*]], [[LOW_BITS_TO_SKIP_32]]
; CHECK-NEXT: [[SHOULD_SIGNEXT:%.*]] = icmp slt i32 [[DATA]], 0
; CHECK-NEXT: [[NBITS_32BIT:%.*]] = zext i8 [[NBITS]] to i32
; CHECK-NEXT: [[ALL_BITS_EXCEPT_LOW_NBITS:%.*]] = shl i32 -1, [[NBITS_32BIT]]
; CHECK-NEXT: [[MAGIC:%.*]] = select i1 [[SHOULD_SIGNEXT]], i32 [[ALL_BITS_EXCEPT_LOW_NBITS]], i32 0
; CHECK-NEXT: call void @use16(i16 [[NBITS_16BIT]])
; CHECK-NEXT: call void @use16(i16 [[LOW_BITS_TO_SKIP]])
; CHECK-NEXT: call void @use32(i32 [[LOW_BITS_TO_SKIP_32]])
; CHECK-NEXT: call void @use32(i32 [[HIGH_BITS_EXTRACTED]])
; CHECK-NEXT: call void @use1(i1 [[SHOULD_SIGNEXT]])
; CHECK-NEXT: call void @use32(i32 [[NBITS_32BIT]])
; CHECK-NEXT: call void @use32(i32 [[ALL_BITS_EXCEPT_LOW_NBITS]])
; CHECK-NEXT: call void @use32(i32 [[MAGIC]])
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = ashr i32 [[DATA]], [[LOW_BITS_TO_SKIP_32]]
; CHECK-NEXT: ret i32 [[SIGNEXTENDED]]
;
%nbits_16bit = zext i8 %nbits to i16
%low_bits_to_skip = sub i16 32, %nbits_16bit
%low_bits_to_skip_32 = zext i16 %low_bits_to_skip to i32
%high_bits_extracted = lshr i32 %data, %low_bits_to_skip_32
%should_signext = icmp slt i32 %data, 0
%nbits_32bit = zext i8 %nbits to i32
%all_bits_except_low_nbits = shl i32 -1, %nbits_32bit
%magic = select i1 %should_signext, i32 %all_bits_except_low_nbits, i32 0
call void @use16(i16 %nbits_16bit)
call void @use16(i16 %low_bits_to_skip)
call void @use32(i32 %low_bits_to_skip_32)
call void @use32(i32 %high_bits_extracted)
call void @use1(i1 %should_signext)
call void @use32(i32 %nbits_32bit)
call void @use32(i32 %all_bits_except_low_nbits)
call void @use32(i32 %magic)
%signextended = add i32 %high_bits_extracted, %magic
ret i32 %signextended
}
define i32 @t12_add_sext_of_magic(i32 %data, i8 %nbits) {
; CHECK-LABEL: @t12_add_sext_of_magic(
; CHECK-NEXT: [[NBITS_32BIT:%.*]] = zext i8 [[NBITS:%.*]] to i32
; CHECK-NEXT: [[LOW_BITS_TO_SKIP:%.*]] = sub nsw i32 32, [[NBITS_32BIT]]
; CHECK-NEXT: [[HIGH_BITS_EXTRACTED:%.*]] = lshr i32 [[DATA:%.*]], [[LOW_BITS_TO_SKIP]]
; CHECK-NEXT: [[SHOULD_SIGNEXT:%.*]] = icmp slt i32 [[DATA]], 0
; CHECK-NEXT: [[NBITS_16BIT:%.*]] = zext i8 [[NBITS]] to i16
; CHECK-NEXT: [[ALL_BITS_EXCEPT_LOW_NBITS:%.*]] = shl i16 -1, [[NBITS_16BIT]]
; CHECK-NEXT: [[MAGIC:%.*]] = select i1 [[SHOULD_SIGNEXT]], i16 [[ALL_BITS_EXCEPT_LOW_NBITS]], i16 0
; CHECK-NEXT: [[MAGIC_WIDE:%.*]] = sext i16 [[MAGIC]] to i32
; CHECK-NEXT: call void @use32(i32 [[NBITS_32BIT]])
; CHECK-NEXT: call void @use32(i32 [[LOW_BITS_TO_SKIP]])
; CHECK-NEXT: call void @use32(i32 [[HIGH_BITS_EXTRACTED]])
; CHECK-NEXT: call void @use1(i1 [[SHOULD_SIGNEXT]])
; CHECK-NEXT: call void @use16(i16 [[NBITS_16BIT]])
; CHECK-NEXT: call void @use16(i16 [[ALL_BITS_EXCEPT_LOW_NBITS]])
; CHECK-NEXT: call void @use16(i16 [[MAGIC]])
; CHECK-NEXT: call void @use32(i32 [[MAGIC_WIDE]])
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = ashr i32 [[DATA]], [[LOW_BITS_TO_SKIP]]
; CHECK-NEXT: ret i32 [[SIGNEXTENDED]]
;
%nbits_32bit = zext i8 %nbits to i32
%low_bits_to_skip = sub i32 32, %nbits_32bit
%high_bits_extracted = lshr i32 %data, %low_bits_to_skip
%should_signext = icmp slt i32 %data, 0
%nbits_16bit = zext i8 %nbits to i16
%all_bits_except_low_nbits = shl i16 -1, %nbits_16bit
%magic = select i1 %should_signext, i16 %all_bits_except_low_nbits, i16 0
%magic_wide = sext i16 %magic to i32
call void @use32(i32 %nbits_32bit)
call void @use32(i32 %low_bits_to_skip)
call void @use32(i32 %high_bits_extracted)
call void @use1(i1 %should_signext)
call void @use16(i16 %nbits_16bit)
call void @use16(i16 %all_bits_except_low_nbits)
call void @use16(i16 %magic)
call void @use32(i32 %magic_wide)
%signextended = add i32 %high_bits_extracted, %magic_wide
ret i32 %signextended
}
define i32 @t13_sub_zext_of_magic(i32 %data, i8 %nbits) {
; CHECK-LABEL: @t13_sub_zext_of_magic(
; CHECK-NEXT: [[NBITS_32BIT:%.*]] = zext i8 [[NBITS:%.*]] to i32
; CHECK-NEXT: [[LOW_BITS_TO_SKIP:%.*]] = sub nsw i32 32, [[NBITS_32BIT]]
; CHECK-NEXT: [[HIGH_BITS_EXTRACTED:%.*]] = lshr i32 [[DATA:%.*]], [[LOW_BITS_TO_SKIP]]
; CHECK-NEXT: [[SHOULD_SIGNEXT:%.*]] = icmp slt i32 [[DATA]], 0
; CHECK-NEXT: [[NBITS_16BIT:%.*]] = zext i8 [[NBITS]] to i16
; CHECK-NEXT: [[ALL_BITS_EXCEPT_LOW_NBITS:%.*]] = shl i16 1, [[NBITS_16BIT]]
; CHECK-NEXT: [[MAGIC:%.*]] = select i1 [[SHOULD_SIGNEXT]], i16 [[ALL_BITS_EXCEPT_LOW_NBITS]], i16 0
; CHECK-NEXT: [[MAGIC_WIDE:%.*]] = zext i16 [[MAGIC]] to i32
; CHECK-NEXT: call void @use32(i32 [[NBITS_32BIT]])
; CHECK-NEXT: call void @use32(i32 [[LOW_BITS_TO_SKIP]])
; CHECK-NEXT: call void @use32(i32 [[HIGH_BITS_EXTRACTED]])
; CHECK-NEXT: call void @use1(i1 [[SHOULD_SIGNEXT]])
; CHECK-NEXT: call void @use16(i16 [[NBITS_16BIT]])
; CHECK-NEXT: call void @use16(i16 [[ALL_BITS_EXCEPT_LOW_NBITS]])
; CHECK-NEXT: call void @use16(i16 [[MAGIC]])
; CHECK-NEXT: call void @use32(i32 [[MAGIC_WIDE]])
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = ashr i32 [[DATA]], [[LOW_BITS_TO_SKIP]]
; CHECK-NEXT: ret i32 [[SIGNEXTENDED]]
;
%nbits_32bit = zext i8 %nbits to i32
%low_bits_to_skip = sub i32 32, %nbits_32bit
%high_bits_extracted = lshr i32 %data, %low_bits_to_skip
%should_signext = icmp slt i32 %data, 0
%nbits_16bit = zext i8 %nbits to i16
%all_bits_except_low_nbits = shl i16 1, %nbits_16bit
%magic = select i1 %should_signext, i16 %all_bits_except_low_nbits, i16 0
%magic_wide = zext i16 %magic to i32
call void @use32(i32 %nbits_32bit)
call void @use32(i32 %low_bits_to_skip)
call void @use32(i32 %high_bits_extracted)
call void @use1(i1 %should_signext)
call void @use16(i16 %nbits_16bit)
call void @use16(i16 %all_bits_except_low_nbits)
call void @use16(i16 %magic)
call void @use32(i32 %magic_wide)
%signextended = sub i32 %high_bits_extracted, %magic_wide
ret i32 %signextended
}
define i32 @t14_add_sext_of_shl(i32 %data, i8 %nbits) {
; CHECK-LABEL: @t14_add_sext_of_shl(
; CHECK-NEXT: [[NBITS_32BIT:%.*]] = zext i8 [[NBITS:%.*]] to i32
; CHECK-NEXT: [[LOW_BITS_TO_SKIP:%.*]] = sub nsw i32 32, [[NBITS_32BIT]]
; CHECK-NEXT: [[HIGH_BITS_EXTRACTED:%.*]] = lshr i32 [[DATA:%.*]], [[LOW_BITS_TO_SKIP]]
; CHECK-NEXT: [[SHOULD_SIGNEXT:%.*]] = icmp slt i32 [[DATA]], 0
; CHECK-NEXT: [[NBITS_16BIT:%.*]] = zext i8 [[NBITS]] to i16
; CHECK-NEXT: [[ALL_BITS_EXCEPT_LOW_NBITS:%.*]] = shl i16 -1, [[NBITS_16BIT]]
; CHECK-NEXT: [[ALL_BITS_EXCEPT_LOW_NBITS_WIDE:%.*]] = sext i16 [[ALL_BITS_EXCEPT_LOW_NBITS]] to i32
; CHECK-NEXT: [[MAGIC:%.*]] = select i1 [[SHOULD_SIGNEXT]], i32 [[ALL_BITS_EXCEPT_LOW_NBITS_WIDE]], i32 0
; CHECK-NEXT: call void @use32(i32 [[NBITS_32BIT]])
; CHECK-NEXT: call void @use32(i32 [[LOW_BITS_TO_SKIP]])
; CHECK-NEXT: call void @use32(i32 [[HIGH_BITS_EXTRACTED]])
; CHECK-NEXT: call void @use1(i1 [[SHOULD_SIGNEXT]])
; CHECK-NEXT: call void @use16(i16 [[NBITS_16BIT]])
; CHECK-NEXT: call void @use16(i16 [[ALL_BITS_EXCEPT_LOW_NBITS]])
; CHECK-NEXT: call void @use32(i32 [[ALL_BITS_EXCEPT_LOW_NBITS_WIDE]])
; CHECK-NEXT: call void @use32(i32 [[MAGIC]])
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = ashr i32 [[DATA]], [[LOW_BITS_TO_SKIP]]
; CHECK-NEXT: ret i32 [[SIGNEXTENDED]]
;
%nbits_32bit = zext i8 %nbits to i32
%low_bits_to_skip = sub i32 32, %nbits_32bit
%high_bits_extracted = lshr i32 %data, %low_bits_to_skip
%should_signext = icmp slt i32 %data, 0
%nbits_16bit = zext i8 %nbits to i16
%all_bits_except_low_nbits = shl i16 -1, %nbits_16bit
%all_bits_except_low_nbits_wide = sext i16 %all_bits_except_low_nbits to i32
%magic = select i1 %should_signext, i32 %all_bits_except_low_nbits_wide, i32 0
call void @use32(i32 %nbits_32bit)
call void @use32(i32 %low_bits_to_skip)
call void @use32(i32 %high_bits_extracted)
call void @use1(i1 %should_signext)
call void @use16(i16 %nbits_16bit)
call void @use16(i16 %all_bits_except_low_nbits)
call void @use32(i32 %all_bits_except_low_nbits_wide)
call void @use32(i32 %magic)
%signextended = add i32 %high_bits_extracted, %magic
ret i32 %signextended
}
define i32 @t15_sub_zext_of_shl(i32 %data, i8 %nbits) {
; CHECK-LABEL: @t15_sub_zext_of_shl(
; CHECK-NEXT: [[NBITS_32BIT:%.*]] = zext i8 [[NBITS:%.*]] to i32
; CHECK-NEXT: [[LOW_BITS_TO_SKIP:%.*]] = sub nsw i32 32, [[NBITS_32BIT]]
; CHECK-NEXT: [[HIGH_BITS_EXTRACTED:%.*]] = lshr i32 [[DATA:%.*]], [[LOW_BITS_TO_SKIP]]
; CHECK-NEXT: [[SHOULD_SIGNEXT:%.*]] = icmp slt i32 [[DATA]], 0
; CHECK-NEXT: [[NBITS_16BIT:%.*]] = zext i8 [[NBITS]] to i16
; CHECK-NEXT: [[ALL_BITS_EXCEPT_LOW_NBITS:%.*]] = shl i16 1, [[NBITS_16BIT]]
; CHECK-NEXT: [[ALL_BITS_EXCEPT_LOW_NBITS_WIDE:%.*]] = zext i16 [[ALL_BITS_EXCEPT_LOW_NBITS]] to i32
; CHECK-NEXT: [[MAGIC:%.*]] = select i1 [[SHOULD_SIGNEXT]], i32 [[ALL_BITS_EXCEPT_LOW_NBITS_WIDE]], i32 0
; CHECK-NEXT: call void @use32(i32 [[NBITS_32BIT]])
; CHECK-NEXT: call void @use32(i32 [[LOW_BITS_TO_SKIP]])
; CHECK-NEXT: call void @use32(i32 [[HIGH_BITS_EXTRACTED]])
; CHECK-NEXT: call void @use1(i1 [[SHOULD_SIGNEXT]])
; CHECK-NEXT: call void @use16(i16 [[NBITS_16BIT]])
; CHECK-NEXT: call void @use16(i16 [[ALL_BITS_EXCEPT_LOW_NBITS]])
; CHECK-NEXT: call void @use32(i32 [[ALL_BITS_EXCEPT_LOW_NBITS_WIDE]])
; CHECK-NEXT: call void @use32(i32 [[MAGIC]])
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = ashr i32 [[DATA]], [[LOW_BITS_TO_SKIP]]
; CHECK-NEXT: ret i32 [[SIGNEXTENDED]]
;
%nbits_32bit = zext i8 %nbits to i32
%low_bits_to_skip = sub i32 32, %nbits_32bit
%high_bits_extracted = lshr i32 %data, %low_bits_to_skip
%should_signext = icmp slt i32 %data, 0
%nbits_16bit = zext i8 %nbits to i16
%all_bits_except_low_nbits = shl i16 1, %nbits_16bit
%all_bits_except_low_nbits_wide = zext i16 %all_bits_except_low_nbits to i32
%magic = select i1 %should_signext, i32 %all_bits_except_low_nbits_wide, i32 0
call void @use32(i32 %nbits_32bit)
call void @use32(i32 %low_bits_to_skip)
call void @use32(i32 %high_bits_extracted)
call void @use1(i1 %should_signext)
call void @use16(i16 %nbits_16bit)
call void @use16(i16 %all_bits_except_low_nbits)
call void @use32(i32 %all_bits_except_low_nbits_wide)
call void @use32(i32 %magic)
%signextended = sub i32 %high_bits_extracted, %magic
ret i32 %signextended
}
; Negative tests.
define i32 @n16(i32 %data, i32 %nbits) {
; CHECK-LABEL: @n16(
; CHECK-NEXT: [[LOW_BITS_TO_SKIP:%.*]] = sub i32 31, [[NBITS:%.*]]
; CHECK-NEXT: [[HIGH_BITS_EXTRACTED:%.*]] = lshr i32 [[DATA:%.*]], [[LOW_BITS_TO_SKIP]]
; CHECK-NEXT: [[SHOULD_SIGNEXT:%.*]] = icmp slt i32 [[DATA]], 0
; CHECK-NEXT: [[ALL_BITS_EXCEPT_LOW_NBITS:%.*]] = shl i32 -1, [[NBITS]]
; CHECK-NEXT: [[MAGIC:%.*]] = select i1 [[SHOULD_SIGNEXT]], i32 [[ALL_BITS_EXCEPT_LOW_NBITS]], i32 0
; CHECK-NEXT: call void @use32(i32 [[LOW_BITS_TO_SKIP]])
; CHECK-NEXT: call void @use32(i32 [[HIGH_BITS_EXTRACTED]])
; CHECK-NEXT: call void @use1(i1 [[SHOULD_SIGNEXT]])
; CHECK-NEXT: call void @use32(i32 [[ALL_BITS_EXCEPT_LOW_NBITS]])
; CHECK-NEXT: call void @use32(i32 [[MAGIC]])
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = add i32 [[HIGH_BITS_EXTRACTED]], [[MAGIC]]
; CHECK-NEXT: ret i32 [[SIGNEXTENDED]]
;
%low_bits_to_skip = sub i32 31, %nbits ; not 32
%high_bits_extracted = lshr i32 %data, %low_bits_to_skip
%should_signext = icmp slt i32 %data, 0
%all_bits_except_low_nbits = shl i32 -1, %nbits
%magic = select i1 %should_signext, i32 %all_bits_except_low_nbits, i32 0
call void @use32(i32 %low_bits_to_skip)
call void @use32(i32 %high_bits_extracted)
call void @use1(i1 %should_signext)
call void @use32(i32 %all_bits_except_low_nbits)
call void @use32(i32 %magic)
%signextended = add i32 %high_bits_extracted, %magic
ret i32 %signextended
}
define i32 @n17_add(i32 %data, i32 %nbits) {
; CHECK-LABEL: @n17_add(
; CHECK-NEXT: [[LOW_BITS_TO_SKIP:%.*]] = sub i32 32, [[NBITS:%.*]]
; CHECK-NEXT: [[HIGH_BITS_EXTRACTED:%.*]] = lshr i32 [[DATA:%.*]], [[LOW_BITS_TO_SKIP]]
; CHECK-NEXT: [[SHOULD_SIGNEXT:%.*]] = icmp slt i32 [[DATA]], 0
; CHECK-NEXT: [[ALL_BITS_EXCEPT_LOW_NBITS:%.*]] = shl i32 1, [[NBITS]]
; CHECK-NEXT: [[MAGIC:%.*]] = select i1 [[SHOULD_SIGNEXT]], i32 [[ALL_BITS_EXCEPT_LOW_NBITS]], i32 0
; CHECK-NEXT: call void @use32(i32 [[LOW_BITS_TO_SKIP]])
; CHECK-NEXT: call void @use32(i32 [[HIGH_BITS_EXTRACTED]])
; CHECK-NEXT: call void @use1(i1 [[SHOULD_SIGNEXT]])
; CHECK-NEXT: call void @use32(i32 [[ALL_BITS_EXCEPT_LOW_NBITS]])
; CHECK-NEXT: call void @use32(i32 [[MAGIC]])
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = add i32 [[HIGH_BITS_EXTRACTED]], [[MAGIC]]
; CHECK-NEXT: ret i32 [[SIGNEXTENDED]]
;
%low_bits_to_skip = sub i32 32, %nbits
%high_bits_extracted = lshr i32 %data, %low_bits_to_skip
%should_signext = icmp slt i32 %data, 0
%all_bits_except_low_nbits = shl i32 1, %nbits ; not -1
%magic = select i1 %should_signext, i32 %all_bits_except_low_nbits, i32 0
call void @use32(i32 %low_bits_to_skip)
call void @use32(i32 %high_bits_extracted)
call void @use1(i1 %should_signext)
call void @use32(i32 %all_bits_except_low_nbits)
call void @use32(i32 %magic)
%signextended = add i32 %high_bits_extracted, %magic
ret i32 %signextended
}
define i32 @n18(i32 %data, i32 %nbits) {
; CHECK-LABEL: @n18(
; CHECK-NEXT: [[LOW_BITS_TO_SKIP:%.*]] = sub i32 32, [[NBITS:%.*]]
; CHECK-NEXT: [[HIGH_BITS_EXTRACTED:%.*]] = lshr i32 [[DATA:%.*]], [[LOW_BITS_TO_SKIP]]
; CHECK-NEXT: [[SHOULD_SIGNEXT:%.*]] = icmp slt i32 [[DATA]], 0
; CHECK-NEXT: [[ALL_BITS_EXCEPT_LOW_NBITS:%.*]] = shl i32 -1, [[NBITS]]
; CHECK-NEXT: [[MAGIC:%.*]] = select i1 [[SHOULD_SIGNEXT]], i32 0, i32 [[ALL_BITS_EXCEPT_LOW_NBITS]]
; CHECK-NEXT: call void @use32(i32 [[LOW_BITS_TO_SKIP]])
; CHECK-NEXT: call void @use32(i32 [[HIGH_BITS_EXTRACTED]])
; CHECK-NEXT: call void @use1(i1 [[SHOULD_SIGNEXT]])
; CHECK-NEXT: call void @use32(i32 [[ALL_BITS_EXCEPT_LOW_NBITS]])
; CHECK-NEXT: call void @use32(i32 [[MAGIC]])
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = add i32 [[HIGH_BITS_EXTRACTED]], [[MAGIC]]
; CHECK-NEXT: ret i32 [[SIGNEXTENDED]]
;
%low_bits_to_skip = sub i32 32, %nbits
%high_bits_extracted = lshr i32 %data, %low_bits_to_skip
%should_signext = icmp slt i32 %data, 0
%all_bits_except_low_nbits = shl i32 -1, %nbits
%magic = select i1 %should_signext, i32 0, i32 %all_bits_except_low_nbits ; wrong order
call void @use32(i32 %low_bits_to_skip)
call void @use32(i32 %high_bits_extracted)
call void @use1(i1 %should_signext)
call void @use32(i32 %all_bits_except_low_nbits)
call void @use32(i32 %magic)
%signextended = add i32 %high_bits_extracted, %magic
ret i32 %signextended
}
define i32 @n19(i32 %data1, i32 %data2, i32 %nbits) {
; CHECK-LABEL: @n19(
; CHECK-NEXT: [[LOW_BITS_TO_SKIP:%.*]] = sub i32 32, [[NBITS:%.*]]
; CHECK-NEXT: [[HIGH_BITS_EXTRACTED:%.*]] = lshr i32 [[DATA1:%.*]], [[LOW_BITS_TO_SKIP]]
; CHECK-NEXT: [[SHOULD_SIGNEXT:%.*]] = icmp slt i32 [[DATA2:%.*]], 0
; CHECK-NEXT: [[ALL_BITS_EXCEPT_LOW_NBITS:%.*]] = shl i32 -1, [[NBITS]]
; CHECK-NEXT: [[MAGIC:%.*]] = select i1 [[SHOULD_SIGNEXT]], i32 [[ALL_BITS_EXCEPT_LOW_NBITS]], i32 0
; CHECK-NEXT: call void @use32(i32 [[LOW_BITS_TO_SKIP]])
; CHECK-NEXT: call void @use32(i32 [[HIGH_BITS_EXTRACTED]])
; CHECK-NEXT: call void @use1(i1 [[SHOULD_SIGNEXT]])
; CHECK-NEXT: call void @use32(i32 [[ALL_BITS_EXCEPT_LOW_NBITS]])
; CHECK-NEXT: call void @use32(i32 [[MAGIC]])
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = add i32 [[HIGH_BITS_EXTRACTED]], [[MAGIC]]
; CHECK-NEXT: ret i32 [[SIGNEXTENDED]]
;
%low_bits_to_skip = sub i32 32, %nbits
%high_bits_extracted = lshr i32 %data1, %low_bits_to_skip ; not %data2
%should_signext = icmp slt i32 %data2, 0 ; not %data1
%all_bits_except_low_nbits = shl i32 -1, %nbits
%magic = select i1 %should_signext, i32 %all_bits_except_low_nbits, i32 0
call void @use32(i32 %low_bits_to_skip)
call void @use32(i32 %high_bits_extracted)
call void @use1(i1 %should_signext)
call void @use32(i32 %all_bits_except_low_nbits)
call void @use32(i32 %magic)
%signextended = add i32 %high_bits_extracted, %magic
ret i32 %signextended
}
define i32 @n20(i32 %data, i32 %nbits1, i32 %nbits2) {
; CHECK-LABEL: @n20(
; CHECK-NEXT: [[LOW_BITS_TO_SKIP:%.*]] = sub i32 32, [[NBITS1:%.*]]
; CHECK-NEXT: [[HIGH_BITS_EXTRACTED:%.*]] = lshr i32 [[DATA:%.*]], [[LOW_BITS_TO_SKIP]]
; CHECK-NEXT: [[SHOULD_SIGNEXT:%.*]] = icmp slt i32 [[DATA]], 0
; CHECK-NEXT: [[ALL_BITS_EXCEPT_LOW_NBITS:%.*]] = shl i32 -1, [[NBITS2:%.*]]
; CHECK-NEXT: [[MAGIC:%.*]] = select i1 [[SHOULD_SIGNEXT]], i32 [[ALL_BITS_EXCEPT_LOW_NBITS]], i32 0
; CHECK-NEXT: call void @use32(i32 [[LOW_BITS_TO_SKIP]])
; CHECK-NEXT: call void @use32(i32 [[HIGH_BITS_EXTRACTED]])
; CHECK-NEXT: call void @use1(i1 [[SHOULD_SIGNEXT]])
; CHECK-NEXT: call void @use32(i32 [[ALL_BITS_EXCEPT_LOW_NBITS]])
; CHECK-NEXT: call void @use32(i32 [[MAGIC]])
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = add i32 [[HIGH_BITS_EXTRACTED]], [[MAGIC]]
; CHECK-NEXT: ret i32 [[SIGNEXTENDED]]
;
%low_bits_to_skip = sub i32 32, %nbits1 ; not %nbits2
%high_bits_extracted = lshr i32 %data, %low_bits_to_skip
%should_signext = icmp slt i32 %data, 0
%all_bits_except_low_nbits = shl i32 -1, %nbits2 ; not %nbits1
%magic = select i1 %should_signext, i32 %all_bits_except_low_nbits, i32 0
call void @use32(i32 %low_bits_to_skip)
call void @use32(i32 %high_bits_extracted)
call void @use1(i1 %should_signext)
call void @use32(i32 %all_bits_except_low_nbits)
call void @use32(i32 %magic)
%signextended = add i32 %high_bits_extracted, %magic
ret i32 %signextended
}
define i32 @n21(i32 %data, i32 %nbits) {
; CHECK-LABEL: @n21(
; CHECK-NEXT: [[LOW_BITS_TO_SKIP:%.*]] = sub i32 32, [[NBITS:%.*]]
; CHECK-NEXT: [[HIGH_BITS_EXTRACTED:%.*]] = lshr i32 [[DATA:%.*]], [[LOW_BITS_TO_SKIP]]
; CHECK-NEXT: [[SHOULD_SIGNEXT:%.*]] = icmp sgt i32 [[DATA]], 0
; CHECK-NEXT: [[ALL_BITS_EXCEPT_LOW_NBITS:%.*]] = shl i32 -1, [[NBITS]]
; CHECK-NEXT: [[MAGIC:%.*]] = select i1 [[SHOULD_SIGNEXT]], i32 [[ALL_BITS_EXCEPT_LOW_NBITS]], i32 0
; CHECK-NEXT: call void @use32(i32 [[LOW_BITS_TO_SKIP]])
; CHECK-NEXT: call void @use32(i32 [[HIGH_BITS_EXTRACTED]])
; CHECK-NEXT: call void @use1(i1 [[SHOULD_SIGNEXT]])
; CHECK-NEXT: call void @use32(i32 [[ALL_BITS_EXCEPT_LOW_NBITS]])
; CHECK-NEXT: call void @use32(i32 [[MAGIC]])
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = add i32 [[HIGH_BITS_EXTRACTED]], [[MAGIC]]
; CHECK-NEXT: ret i32 [[SIGNEXTENDED]]
;
%low_bits_to_skip = sub i32 32, %nbits
%high_bits_extracted = lshr i32 %data, %low_bits_to_skip
%should_signext = icmp sgt i32 %data, 0 ; this isn't a sign bit test
%all_bits_except_low_nbits = shl i32 -1, %nbits
%magic = select i1 %should_signext, i32 %all_bits_except_low_nbits, i32 0
call void @use32(i32 %low_bits_to_skip)
call void @use32(i32 %high_bits_extracted)
call void @use1(i1 %should_signext)
call void @use32(i32 %all_bits_except_low_nbits)
call void @use32(i32 %magic)
%signextended = add i32 %high_bits_extracted, %magic
ret i32 %signextended
}
define i32 @n22(i64 %data, i32 %nbits) {
; CHECK-LABEL: @n22(
; CHECK-NEXT: [[LOW_BITS_TO_SKIP:%.*]] = sub i32 63, [[NBITS:%.*]]
; CHECK-NEXT: [[LOW_BITS_TO_SKIP_WIDE:%.*]] = zext i32 [[LOW_BITS_TO_SKIP]] to i64
; CHECK-NEXT: [[HIGH_BITS_EXTRACTED_WIDE:%.*]] = lshr i64 [[DATA:%.*]], [[LOW_BITS_TO_SKIP_WIDE]]
; CHECK-NEXT: [[HIGH_BITS_EXTRACTED:%.*]] = trunc i64 [[HIGH_BITS_EXTRACTED_WIDE]] to i32
; CHECK-NEXT: [[SHOULD_SIGNEXT:%.*]] = icmp slt i64 [[DATA]], 0
; CHECK-NEXT: [[ALL_BITS_EXCEPT_LOW_NBITS:%.*]] = shl i32 -1, [[NBITS]]
; CHECK-NEXT: [[MAGIC:%.*]] = select i1 [[SHOULD_SIGNEXT]], i32 [[ALL_BITS_EXCEPT_LOW_NBITS]], i32 0
; CHECK-NEXT: call void @use32(i32 [[LOW_BITS_TO_SKIP]])
; CHECK-NEXT: call void @use64(i64 [[LOW_BITS_TO_SKIP_WIDE]])
; CHECK-NEXT: call void @use64(i64 [[HIGH_BITS_EXTRACTED_WIDE]])
; CHECK-NEXT: call void @use32(i32 [[HIGH_BITS_EXTRACTED]])
; CHECK-NEXT: call void @use1(i1 [[SHOULD_SIGNEXT]])
; CHECK-NEXT: call void @use32(i32 [[ALL_BITS_EXCEPT_LOW_NBITS]])
; CHECK-NEXT: call void @use32(i32 [[MAGIC]])
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = add i32 [[MAGIC]], [[HIGH_BITS_EXTRACTED]]
; CHECK-NEXT: ret i32 [[SIGNEXTENDED]]
;
%low_bits_to_skip = sub i32 63, %nbits ; not 64
%low_bits_to_skip_wide = zext i32 %low_bits_to_skip to i64
%high_bits_extracted_wide = lshr i64 %data, %low_bits_to_skip_wide
%high_bits_extracted = trunc i64 %high_bits_extracted_wide to i32
%should_signext = icmp slt i64 %data, 0
%all_bits_except_low_nbits = shl i32 -1, %nbits
%magic = select i1 %should_signext, i32 %all_bits_except_low_nbits, i32 0
call void @use32(i32 %low_bits_to_skip)
call void @use64(i64 %low_bits_to_skip_wide)
call void @use64(i64 %high_bits_extracted_wide)
call void @use32(i32 %high_bits_extracted)
call void @use1(i1 %should_signext)
call void @use32(i32 %all_bits_except_low_nbits)
call void @use32(i32 %magic)
%signextended = add i32 %magic, %high_bits_extracted
ret i32 %signextended
}
define i32 @n23(i32 %data, i32 %nbits) {
; CHECK-LABEL: @n23(
; CHECK-NEXT: [[LOW_BITS_TO_SKIP:%.*]] = sub i32 32, [[NBITS:%.*]]
; CHECK-NEXT: [[HIGH_BITS_EXTRACTED:%.*]] = ashr i32 [[DATA:%.*]], [[LOW_BITS_TO_SKIP]]
; CHECK-NEXT: [[SHOULD_SIGNEXT:%.*]] = icmp slt i32 [[DATA]], 0
; CHECK-NEXT: [[ALL_BITS_EXCEPT_LOW_NBITS:%.*]] = shl i32 -1, [[NBITS]]
; CHECK-NEXT: [[MAGIC:%.*]] = select i1 [[SHOULD_SIGNEXT]], i32 [[ALL_BITS_EXCEPT_LOW_NBITS]], i32 0
; CHECK-NEXT: call void @use32(i32 [[LOW_BITS_TO_SKIP]])
; CHECK-NEXT: call void @use32(i32 [[HIGH_BITS_EXTRACTED]])
; CHECK-NEXT: call void @use1(i1 [[SHOULD_SIGNEXT]])
; CHECK-NEXT: call void @use32(i32 [[ALL_BITS_EXCEPT_LOW_NBITS]])
; CHECK-NEXT: call void @use32(i32 [[MAGIC]])
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = add i32 [[HIGH_BITS_EXTRACTED]], [[MAGIC]]
; CHECK-NEXT: ret i32 [[SIGNEXTENDED]]
;
%low_bits_to_skip = sub i32 32, %nbits
%high_bits_extracted = ashr i32 %data, %low_bits_to_skip ; not `lshr`
%should_signext = icmp slt i32 %data, 0
%all_bits_except_low_nbits = shl i32 -1, %nbits
%magic = select i1 %should_signext, i32 %all_bits_except_low_nbits, i32 0
call void @use32(i32 %low_bits_to_skip)
call void @use32(i32 %high_bits_extracted)
call void @use1(i1 %should_signext)
call void @use32(i32 %all_bits_except_low_nbits)
call void @use32(i32 %magic)
%signextended = add i32 %high_bits_extracted, %magic
ret i32 %signextended
}
define i32 @n24(i32 %data, i32 %nbits) {
; CHECK-LABEL: @n24(
; CHECK-NEXT: [[LOW_BITS_TO_SKIP:%.*]] = sub i32 32, [[NBITS:%.*]]
; CHECK-NEXT: [[HIGH_BITS_EXTRACTED:%.*]] = lshr i32 [[DATA:%.*]], [[LOW_BITS_TO_SKIP]]
; CHECK-NEXT: [[SHOULD_SIGNEXT:%.*]] = icmp slt i32 [[DATA]], 0
; CHECK-NEXT: [[HIGHER_BIT_AFTER_SIGNBIT:%.*]] = shl i32 1, [[NBITS]]
; CHECK-NEXT: [[MAGIC:%.*]] = select i1 [[SHOULD_SIGNEXT]], i32 [[HIGHER_BIT_AFTER_SIGNBIT]], i32 0
; CHECK-NEXT: call void @use32(i32 [[LOW_BITS_TO_SKIP]])
; CHECK-NEXT: call void @use32(i32 [[HIGH_BITS_EXTRACTED]])
; CHECK-NEXT: call void @use1(i1 [[SHOULD_SIGNEXT]])
; CHECK-NEXT: call void @use32(i32 [[HIGHER_BIT_AFTER_SIGNBIT]])
; CHECK-NEXT: call void @use32(i32 [[MAGIC]])
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = sub i32 [[MAGIC]], [[HIGH_BITS_EXTRACTED]]
; CHECK-NEXT: ret i32 [[SIGNEXTENDED]]
;
%low_bits_to_skip = sub i32 32, %nbits
%high_bits_extracted = lshr i32 %data, %low_bits_to_skip
%should_signext = icmp slt i32 %data, 0
%higher_bit_after_signbit = shl i32 1, %nbits
%magic = select i1 %should_signext, i32 %higher_bit_after_signbit, i32 0
call void @use32(i32 %low_bits_to_skip)
call void @use32(i32 %high_bits_extracted)
call void @use1(i1 %should_signext)
call void @use32(i32 %higher_bit_after_signbit)
call void @use32(i32 %magic)
%signextended = sub i32 %magic, %high_bits_extracted ; wrong order; `sub` is not commutative
ret i32 %signextended
}
define i32 @n25_sub(i32 %data, i32 %nbits) {
; CHECK-LABEL: @n25_sub(
; CHECK-NEXT: [[LOW_BITS_TO_SKIP:%.*]] = sub i32 32, [[NBITS:%.*]]
; CHECK-NEXT: [[HIGH_BITS_EXTRACTED:%.*]] = lshr i32 [[DATA:%.*]], [[LOW_BITS_TO_SKIP]]
; CHECK-NEXT: [[SHOULD_SIGNEXT:%.*]] = icmp slt i32 [[DATA]], 0
; CHECK-NEXT: [[HIGHER_BIT_AFTER_SIGNBIT:%.*]] = shl i32 -1, [[NBITS]]
; CHECK-NEXT: [[MAGIC:%.*]] = select i1 [[SHOULD_SIGNEXT]], i32 [[HIGHER_BIT_AFTER_SIGNBIT]], i32 0
; CHECK-NEXT: call void @use32(i32 [[LOW_BITS_TO_SKIP]])
; CHECK-NEXT: call void @use32(i32 [[HIGH_BITS_EXTRACTED]])
; CHECK-NEXT: call void @use1(i1 [[SHOULD_SIGNEXT]])
; CHECK-NEXT: call void @use32(i32 [[HIGHER_BIT_AFTER_SIGNBIT]])
; CHECK-NEXT: call void @use32(i32 [[MAGIC]])
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = sub i32 [[HIGH_BITS_EXTRACTED]], [[MAGIC]]
; CHECK-NEXT: ret i32 [[SIGNEXTENDED]]
;
%low_bits_to_skip = sub i32 32, %nbits
%high_bits_extracted = lshr i32 %data, %low_bits_to_skip
%should_signext = icmp slt i32 %data, 0
%higher_bit_after_signbit = shl i32 -1, %nbits ; not 1
%magic = select i1 %should_signext, i32 %higher_bit_after_signbit, i32 0
call void @use32(i32 %low_bits_to_skip)
call void @use32(i32 %high_bits_extracted)
call void @use1(i1 %should_signext)
call void @use32(i32 %higher_bit_after_signbit)
call void @use32(i32 %magic)
%signextended = sub i32 %high_bits_extracted, %magic
ret i32 %signextended
}
define i32 @n26(i32 %data, i32 %nbits) {
; CHECK-LABEL: @n26(
; CHECK-NEXT: [[LOW_BITS_TO_SKIP:%.*]] = sub i32 32, [[NBITS:%.*]]
; CHECK-NEXT: [[HIGH_BITS_EXTRACTED:%.*]] = lshr i32 [[DATA:%.*]], [[LOW_BITS_TO_SKIP]]
; CHECK-NEXT: [[SHOULD_SIGNEXT:%.*]] = icmp slt i32 [[DATA]], 0
; CHECK-NEXT: [[ALL_BITS_EXCEPT_LOW_NBITS:%.*]] = shl i32 -1, [[NBITS]]
; CHECK-NEXT: [[MAGIC:%.*]] = select i1 [[SHOULD_SIGNEXT]], i32 [[ALL_BITS_EXCEPT_LOW_NBITS]], i32 -1
; CHECK-NEXT: call void @use32(i32 [[LOW_BITS_TO_SKIP]])
; CHECK-NEXT: call void @use32(i32 [[HIGH_BITS_EXTRACTED]])
; CHECK-NEXT: call void @use1(i1 [[SHOULD_SIGNEXT]])
; CHECK-NEXT: call void @use32(i32 [[ALL_BITS_EXCEPT_LOW_NBITS]])
; CHECK-NEXT: call void @use32(i32 [[MAGIC]])
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = add i32 [[HIGH_BITS_EXTRACTED]], [[MAGIC]]
; CHECK-NEXT: ret i32 [[SIGNEXTENDED]]
;
%low_bits_to_skip = sub i32 32, %nbits
%high_bits_extracted = lshr i32 %data, %low_bits_to_skip
%should_signext = icmp slt i32 %data, 0
%all_bits_except_low_nbits = shl i32 -1, %nbits
%magic = select i1 %should_signext, i32 %all_bits_except_low_nbits, i32 -1 ; not 0
call void @use32(i32 %low_bits_to_skip)
call void @use32(i32 %high_bits_extracted)
call void @use1(i1 %should_signext)
call void @use32(i32 %all_bits_except_low_nbits)
call void @use32(i32 %magic)
%signextended = add i32 %high_bits_extracted, %magic
ret i32 %signextended
}
define i32 @n27_add_zext_of_magic(i32 %data, i8 %nbits) {
; CHECK-LABEL: @n27_add_zext_of_magic(
; CHECK-NEXT: [[NBITS_32BIT:%.*]] = zext i8 [[NBITS:%.*]] to i32
; CHECK-NEXT: [[LOW_BITS_TO_SKIP:%.*]] = sub nsw i32 32, [[NBITS_32BIT]]
; CHECK-NEXT: [[HIGH_BITS_EXTRACTED:%.*]] = lshr i32 [[DATA:%.*]], [[LOW_BITS_TO_SKIP]]
; CHECK-NEXT: [[SHOULD_SIGNEXT:%.*]] = icmp slt i32 [[DATA]], 0
; CHECK-NEXT: [[NBITS_16BIT:%.*]] = zext i8 [[NBITS]] to i16
; CHECK-NEXT: [[ALL_BITS_EXCEPT_LOW_NBITS:%.*]] = shl i16 -1, [[NBITS_16BIT]]
; CHECK-NEXT: [[MAGIC:%.*]] = select i1 [[SHOULD_SIGNEXT]], i16 [[ALL_BITS_EXCEPT_LOW_NBITS]], i16 0
; CHECK-NEXT: [[MAGIC_WIDE:%.*]] = zext i16 [[MAGIC]] to i32
; CHECK-NEXT: call void @use32(i32 [[NBITS_32BIT]])
; CHECK-NEXT: call void @use32(i32 [[LOW_BITS_TO_SKIP]])
; CHECK-NEXT: call void @use32(i32 [[HIGH_BITS_EXTRACTED]])
; CHECK-NEXT: call void @use1(i1 [[SHOULD_SIGNEXT]])
; CHECK-NEXT: call void @use16(i16 [[NBITS_16BIT]])
; CHECK-NEXT: call void @use16(i16 [[ALL_BITS_EXCEPT_LOW_NBITS]])
; CHECK-NEXT: call void @use16(i16 [[MAGIC]])
; CHECK-NEXT: call void @use32(i32 [[MAGIC_WIDE]])
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = add i32 [[HIGH_BITS_EXTRACTED]], [[MAGIC_WIDE]]
; CHECK-NEXT: ret i32 [[SIGNEXTENDED]]
;
%nbits_32bit = zext i8 %nbits to i32
%low_bits_to_skip = sub i32 32, %nbits_32bit
%high_bits_extracted = lshr i32 %data, %low_bits_to_skip
%should_signext = icmp slt i32 %data, 0
%nbits_16bit = zext i8 %nbits to i16
%all_bits_except_low_nbits = shl i16 -1, %nbits_16bit
%magic = select i1 %should_signext, i16 %all_bits_except_low_nbits, i16 0
%magic_wide = zext i16 %magic to i32 ; not sext
call void @use32(i32 %nbits_32bit)
call void @use32(i32 %low_bits_to_skip)
call void @use32(i32 %high_bits_extracted)
call void @use1(i1 %should_signext)
call void @use16(i16 %nbits_16bit)
call void @use16(i16 %all_bits_except_low_nbits)
call void @use16(i16 %magic)
call void @use32(i32 %magic_wide)
%signextended = add i32 %high_bits_extracted, %magic_wide
ret i32 %signextended
}
define i32 @n28_sub_sext_of_magic(i32 %data, i8 %nbits) {
; CHECK-LABEL: @n28_sub_sext_of_magic(
; CHECK-NEXT: [[NBITS_32BIT:%.*]] = zext i8 [[NBITS:%.*]] to i32
; CHECK-NEXT: [[LOW_BITS_TO_SKIP:%.*]] = sub nsw i32 32, [[NBITS_32BIT]]
; CHECK-NEXT: [[HIGH_BITS_EXTRACTED:%.*]] = lshr i32 [[DATA:%.*]], [[LOW_BITS_TO_SKIP]]
; CHECK-NEXT: [[SHOULD_SIGNEXT:%.*]] = icmp slt i32 [[DATA]], 0
; CHECK-NEXT: [[NBITS_16BIT:%.*]] = zext i8 [[NBITS]] to i16
; CHECK-NEXT: [[ALL_BITS_EXCEPT_LOW_NBITS:%.*]] = shl i16 1, [[NBITS_16BIT]]
; CHECK-NEXT: [[MAGIC:%.*]] = select i1 [[SHOULD_SIGNEXT]], i16 [[ALL_BITS_EXCEPT_LOW_NBITS]], i16 0
; CHECK-NEXT: [[MAGIC_WIDE:%.*]] = sext i16 [[MAGIC]] to i32
; CHECK-NEXT: call void @use32(i32 [[NBITS_32BIT]])
; CHECK-NEXT: call void @use32(i32 [[LOW_BITS_TO_SKIP]])
; CHECK-NEXT: call void @use32(i32 [[HIGH_BITS_EXTRACTED]])
; CHECK-NEXT: call void @use1(i1 [[SHOULD_SIGNEXT]])
; CHECK-NEXT: call void @use16(i16 [[NBITS_16BIT]])
; CHECK-NEXT: call void @use16(i16 [[ALL_BITS_EXCEPT_LOW_NBITS]])
; CHECK-NEXT: call void @use16(i16 [[MAGIC]])
; CHECK-NEXT: call void @use32(i32 [[MAGIC_WIDE]])
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = sub i32 [[HIGH_BITS_EXTRACTED]], [[MAGIC_WIDE]]
; CHECK-NEXT: ret i32 [[SIGNEXTENDED]]
;
%nbits_32bit = zext i8 %nbits to i32
%low_bits_to_skip = sub i32 32, %nbits_32bit
%high_bits_extracted = lshr i32 %data, %low_bits_to_skip
%should_signext = icmp slt i32 %data, 0
%nbits_16bit = zext i8 %nbits to i16
%all_bits_except_low_nbits = shl i16 1, %nbits_16bit
%magic = select i1 %should_signext, i16 %all_bits_except_low_nbits, i16 0
%magic_wide = sext i16 %magic to i32 ; not zext
call void @use32(i32 %nbits_32bit)
call void @use32(i32 %low_bits_to_skip)
call void @use32(i32 %high_bits_extracted)
call void @use1(i1 %should_signext)
call void @use16(i16 %nbits_16bit)
call void @use16(i16 %all_bits_except_low_nbits)
call void @use16(i16 %magic)
call void @use32(i32 %magic_wide)
%signextended = sub i32 %high_bits_extracted, %magic_wide
ret i32 %signextended
}
define i32 @n290_or_with_wrong_magic(i32 %data, i32 %nbits) {
; CHECK-LABEL: @n290_or_with_wrong_magic(
; CHECK-NEXT: [[LOW_BITS_TO_SKIP:%.*]] = sub i32 32, [[NBITS:%.*]]
; CHECK-NEXT: [[HIGH_BITS_EXTRACTED:%.*]] = lshr i32 [[DATA:%.*]], [[LOW_BITS_TO_SKIP]]
; CHECK-NEXT: [[SHOULD_SIGNEXT:%.*]] = icmp slt i32 [[DATA]], 0
; CHECK-NEXT: [[ALL_BITS_EXCEPT_LOW_NBITS:%.*]] = shl i32 1, [[NBITS]]
; CHECK-NEXT: [[MAGIC:%.*]] = select i1 [[SHOULD_SIGNEXT]], i32 [[ALL_BITS_EXCEPT_LOW_NBITS]], i32 0
; CHECK-NEXT: call void @use32(i32 [[LOW_BITS_TO_SKIP]])
; CHECK-NEXT: call void @use32(i32 [[HIGH_BITS_EXTRACTED]])
; CHECK-NEXT: call void @use1(i1 [[SHOULD_SIGNEXT]])
; CHECK-NEXT: call void @use32(i32 [[ALL_BITS_EXCEPT_LOW_NBITS]])
; CHECK-NEXT: call void @use32(i32 [[MAGIC]])
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = or i32 [[HIGH_BITS_EXTRACTED]], [[MAGIC]]
; CHECK-NEXT: ret i32 [[SIGNEXTENDED]]
;
%low_bits_to_skip = sub i32 32, %nbits
%high_bits_extracted = lshr i32 %data, %low_bits_to_skip
%should_signext = icmp slt i32 %data, 0
%all_bits_except_low_nbits = shl i32 1, %nbits ; not -1
%magic = select i1 %should_signext, i32 %all_bits_except_low_nbits, i32 0
call void @use32(i32 %low_bits_to_skip)
call void @use32(i32 %high_bits_extracted)
call void @use1(i1 %should_signext)
call void @use32(i32 %all_bits_except_low_nbits)
call void @use32(i32 %magic)
%signextended = or i32 %high_bits_extracted, %magic
ret i32 %signextended
}