2019-10-07 22:53:16 +02:00
|
|
|
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
2020-09-29 17:02:03 +02:00
|
|
|
; RUN: opt < %s -instcombine -S | FileCheck %s
|
2019-10-07 22:53:16 +02:00
|
|
|
|
|
|
|
; 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]])
|
[InstCombine] Fold conditional sign-extend of high-bit-extract into high-bit-extract-with-signext (PR42389)
This can come up in Bit Stream abstractions.
The pattern looks big/scary, but it can't be simplified any further.
It only is so simple because a number of my preparatory folds had
happened already (shift amount reassociation / shift amount
reassociation in bit test, sign bit test detection).
Highlights:
* There are two main flavors: https://rise4fun.com/Alive/zWi
The difference is add vs. sub, and left-shift of -1 vs. 1
* Since we only change the shift opcode,
we can preserve the exact-ness: https://rise4fun.com/Alive/4u4
* There can be truncation after high-bit-extraction:
https://rise4fun.com/Alive/slHc1 (the main pattern i'm after!)
Which means that we need to ignore zext of shift amounts and of NBits.
* The sign-extending magic can be extended itself (in add pattern
via sext, in sub pattern via zext. not the other way around!)
https://rise4fun.com/Alive/NhG
(or those sext/zext can be sinked into `select`!)
Which again means we should pay attention when matching NBits.
* We can have both truncation of extraction and widening of magic:
https://rise4fun.com/Alive/XTw
In other words, i don't believe we need to have any checks on
bitwidths of any of these constructs.
This is worsened in general by the fact that we may have `sext` instead
of `zext` for shift amounts, and we don't yet canonicalize to `zext`,
although we should. I have not done anything about that here.
Also, we really should have something to weed out `sub` like these,
by folding them into `add` variant.
https://bugs.llvm.org/show_bug.cgi?id=42389
llvm-svn: 373964
2019-10-07 22:53:27 +02:00
|
|
|
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = ashr i32 [[DATA]], [[LOW_BITS_TO_SKIP]]
|
2019-10-07 22:53:16 +02:00
|
|
|
; 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
|
|
|
|
}
|
|
|
|
|
2019-10-20 22:51:37 +02:00
|
|
|
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]])
|
2019-10-20 22:52:06 +02:00
|
|
|
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = ashr i32 [[DATA]], [[LOW_BITS_TO_SKIP]]
|
2019-10-20 22:51:37 +02:00
|
|
|
; 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
|
|
|
|
}
|
|
|
|
|
2019-10-07 22:53:16 +02:00
|
|
|
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]])
|
[InstCombine] Fold conditional sign-extend of high-bit-extract into high-bit-extract-with-signext (PR42389)
This can come up in Bit Stream abstractions.
The pattern looks big/scary, but it can't be simplified any further.
It only is so simple because a number of my preparatory folds had
happened already (shift amount reassociation / shift amount
reassociation in bit test, sign bit test detection).
Highlights:
* There are two main flavors: https://rise4fun.com/Alive/zWi
The difference is add vs. sub, and left-shift of -1 vs. 1
* Since we only change the shift opcode,
we can preserve the exact-ness: https://rise4fun.com/Alive/4u4
* There can be truncation after high-bit-extraction:
https://rise4fun.com/Alive/slHc1 (the main pattern i'm after!)
Which means that we need to ignore zext of shift amounts and of NBits.
* The sign-extending magic can be extended itself (in add pattern
via sext, in sub pattern via zext. not the other way around!)
https://rise4fun.com/Alive/NhG
(or those sext/zext can be sinked into `select`!)
Which again means we should pay attention when matching NBits.
* We can have both truncation of extraction and widening of magic:
https://rise4fun.com/Alive/XTw
In other words, i don't believe we need to have any checks on
bitwidths of any of these constructs.
This is worsened in general by the fact that we may have `sext` instead
of `zext` for shift amounts, and we don't yet canonicalize to `zext`,
although we should. I have not done anything about that here.
Also, we really should have something to weed out `sub` like these,
by folding them into `add` variant.
https://bugs.llvm.org/show_bug.cgi?id=42389
llvm-svn: 373964
2019-10-07 22:53:27 +02:00
|
|
|
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = ashr i32 [[DATA]], [[LOW_BITS_TO_SKIP]]
|
2019-10-07 22:53:16 +02:00
|
|
|
; 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]])
|
[InstCombine] Fold conditional sign-extend of high-bit-extract into high-bit-extract-with-signext (PR42389)
This can come up in Bit Stream abstractions.
The pattern looks big/scary, but it can't be simplified any further.
It only is so simple because a number of my preparatory folds had
happened already (shift amount reassociation / shift amount
reassociation in bit test, sign bit test detection).
Highlights:
* There are two main flavors: https://rise4fun.com/Alive/zWi
The difference is add vs. sub, and left-shift of -1 vs. 1
* Since we only change the shift opcode,
we can preserve the exact-ness: https://rise4fun.com/Alive/4u4
* There can be truncation after high-bit-extraction:
https://rise4fun.com/Alive/slHc1 (the main pattern i'm after!)
Which means that we need to ignore zext of shift amounts and of NBits.
* The sign-extending magic can be extended itself (in add pattern
via sext, in sub pattern via zext. not the other way around!)
https://rise4fun.com/Alive/NhG
(or those sext/zext can be sinked into `select`!)
Which again means we should pay attention when matching NBits.
* We can have both truncation of extraction and widening of magic:
https://rise4fun.com/Alive/XTw
In other words, i don't believe we need to have any checks on
bitwidths of any of these constructs.
This is worsened in general by the fact that we may have `sext` instead
of `zext` for shift amounts, and we don't yet canonicalize to `zext`,
although we should. I have not done anything about that here.
Also, we really should have something to weed out `sub` like these,
by folding them into `add` variant.
https://bugs.llvm.org/show_bug.cgi?id=42389
llvm-svn: 373964
2019-10-07 22:53:27 +02:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = ashr i64 [[DATA]], [[LOW_BITS_TO_SKIP_WIDE]]
|
|
|
|
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = trunc i64 [[TMP1]] to i32
|
2019-10-07 22:53:16 +02:00
|
|
|
; 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
|
|
|
|
}
|
|
|
|
|
2019-10-20 22:51:37 +02:00
|
|
|
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]])
|
2019-10-20 22:52:06 +02:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = ashr i64 [[DATA]], [[LOW_BITS_TO_SKIP_WIDE]]
|
|
|
|
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = trunc i64 [[TMP1]] to i32
|
2019-10-20 22:51:37 +02:00
|
|
|
; 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
|
|
|
|
}
|
|
|
|
|
2019-10-07 22:53:16 +02:00
|
|
|
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]])
|
[InstCombine] Fold conditional sign-extend of high-bit-extract into high-bit-extract-with-signext (PR42389)
This can come up in Bit Stream abstractions.
The pattern looks big/scary, but it can't be simplified any further.
It only is so simple because a number of my preparatory folds had
happened already (shift amount reassociation / shift amount
reassociation in bit test, sign bit test detection).
Highlights:
* There are two main flavors: https://rise4fun.com/Alive/zWi
The difference is add vs. sub, and left-shift of -1 vs. 1
* Since we only change the shift opcode,
we can preserve the exact-ness: https://rise4fun.com/Alive/4u4
* There can be truncation after high-bit-extraction:
https://rise4fun.com/Alive/slHc1 (the main pattern i'm after!)
Which means that we need to ignore zext of shift amounts and of NBits.
* The sign-extending magic can be extended itself (in add pattern
via sext, in sub pattern via zext. not the other way around!)
https://rise4fun.com/Alive/NhG
(or those sext/zext can be sinked into `select`!)
Which again means we should pay attention when matching NBits.
* We can have both truncation of extraction and widening of magic:
https://rise4fun.com/Alive/XTw
In other words, i don't believe we need to have any checks on
bitwidths of any of these constructs.
This is worsened in general by the fact that we may have `sext` instead
of `zext` for shift amounts, and we don't yet canonicalize to `zext`,
although we should. I have not done anything about that here.
Also, we really should have something to weed out `sub` like these,
by folding them into `add` variant.
https://bugs.llvm.org/show_bug.cgi?id=42389
llvm-svn: 373964
2019-10-07 22:53:27 +02:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = ashr i64 [[DATA]], [[LOW_BITS_TO_SKIP_WIDE]]
|
|
|
|
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = trunc i64 [[TMP1]] to i32
|
2019-10-07 22:53:16 +02:00
|
|
|
; 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]])
|
[InstCombine] Fold conditional sign-extend of high-bit-extract into high-bit-extract-with-signext (PR42389)
This can come up in Bit Stream abstractions.
The pattern looks big/scary, but it can't be simplified any further.
It only is so simple because a number of my preparatory folds had
happened already (shift amount reassociation / shift amount
reassociation in bit test, sign bit test detection).
Highlights:
* There are two main flavors: https://rise4fun.com/Alive/zWi
The difference is add vs. sub, and left-shift of -1 vs. 1
* Since we only change the shift opcode,
we can preserve the exact-ness: https://rise4fun.com/Alive/4u4
* There can be truncation after high-bit-extraction:
https://rise4fun.com/Alive/slHc1 (the main pattern i'm after!)
Which means that we need to ignore zext of shift amounts and of NBits.
* The sign-extending magic can be extended itself (in add pattern
via sext, in sub pattern via zext. not the other way around!)
https://rise4fun.com/Alive/NhG
(or those sext/zext can be sinked into `select`!)
Which again means we should pay attention when matching NBits.
* We can have both truncation of extraction and widening of magic:
https://rise4fun.com/Alive/XTw
In other words, i don't believe we need to have any checks on
bitwidths of any of these constructs.
This is worsened in general by the fact that we may have `sext` instead
of `zext` for shift amounts, and we don't yet canonicalize to `zext`,
although we should. I have not done anything about that here.
Also, we really should have something to weed out `sub` like these,
by folding them into `add` variant.
https://bugs.llvm.org/show_bug.cgi?id=42389
llvm-svn: 373964
2019-10-07 22:53:27 +02:00
|
|
|
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = ashr i32 [[DATA]], [[LOW_BITS_TO_SKIP]]
|
2019-10-07 22:53:16 +02:00
|
|
|
; 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]])
|
[InstCombine] Fold conditional sign-extend of high-bit-extract into high-bit-extract-with-signext (PR42389)
This can come up in Bit Stream abstractions.
The pattern looks big/scary, but it can't be simplified any further.
It only is so simple because a number of my preparatory folds had
happened already (shift amount reassociation / shift amount
reassociation in bit test, sign bit test detection).
Highlights:
* There are two main flavors: https://rise4fun.com/Alive/zWi
The difference is add vs. sub, and left-shift of -1 vs. 1
* Since we only change the shift opcode,
we can preserve the exact-ness: https://rise4fun.com/Alive/4u4
* There can be truncation after high-bit-extraction:
https://rise4fun.com/Alive/slHc1 (the main pattern i'm after!)
Which means that we need to ignore zext of shift amounts and of NBits.
* The sign-extending magic can be extended itself (in add pattern
via sext, in sub pattern via zext. not the other way around!)
https://rise4fun.com/Alive/NhG
(or those sext/zext can be sinked into `select`!)
Which again means we should pay attention when matching NBits.
* We can have both truncation of extraction and widening of magic:
https://rise4fun.com/Alive/XTw
In other words, i don't believe we need to have any checks on
bitwidths of any of these constructs.
This is worsened in general by the fact that we may have `sext` instead
of `zext` for shift amounts, and we don't yet canonicalize to `zext`,
although we should. I have not done anything about that here.
Also, we really should have something to weed out `sub` like these,
by folding them into `add` variant.
https://bugs.llvm.org/show_bug.cgi?id=42389
llvm-svn: 373964
2019-10-07 22:53:27 +02:00
|
|
|
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = ashr i32 [[DATA]], [[LOW_BITS_TO_SKIP]]
|
2019-10-07 22:53:16 +02:00
|
|
|
; 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]])
|
[InstCombine] Fold conditional sign-extend of high-bit-extract into high-bit-extract-with-signext (PR42389)
This can come up in Bit Stream abstractions.
The pattern looks big/scary, but it can't be simplified any further.
It only is so simple because a number of my preparatory folds had
happened already (shift amount reassociation / shift amount
reassociation in bit test, sign bit test detection).
Highlights:
* There are two main flavors: https://rise4fun.com/Alive/zWi
The difference is add vs. sub, and left-shift of -1 vs. 1
* Since we only change the shift opcode,
we can preserve the exact-ness: https://rise4fun.com/Alive/4u4
* There can be truncation after high-bit-extraction:
https://rise4fun.com/Alive/slHc1 (the main pattern i'm after!)
Which means that we need to ignore zext of shift amounts and of NBits.
* The sign-extending magic can be extended itself (in add pattern
via sext, in sub pattern via zext. not the other way around!)
https://rise4fun.com/Alive/NhG
(or those sext/zext can be sinked into `select`!)
Which again means we should pay attention when matching NBits.
* We can have both truncation of extraction and widening of magic:
https://rise4fun.com/Alive/XTw
In other words, i don't believe we need to have any checks on
bitwidths of any of these constructs.
This is worsened in general by the fact that we may have `sext` instead
of `zext` for shift amounts, and we don't yet canonicalize to `zext`,
although we should. I have not done anything about that here.
Also, we really should have something to weed out `sub` like these,
by folding them into `add` variant.
https://bugs.llvm.org/show_bug.cgi?id=42389
llvm-svn: 373964
2019-10-07 22:53:27 +02:00
|
|
|
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = ashr i32 [[DATA]], [[LOW_BITS_TO_SKIP]]
|
2019-10-07 22:53:16 +02:00
|
|
|
; 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]])
|
[InstCombine] Fold conditional sign-extend of high-bit-extract into high-bit-extract-with-signext (PR42389)
This can come up in Bit Stream abstractions.
The pattern looks big/scary, but it can't be simplified any further.
It only is so simple because a number of my preparatory folds had
happened already (shift amount reassociation / shift amount
reassociation in bit test, sign bit test detection).
Highlights:
* There are two main flavors: https://rise4fun.com/Alive/zWi
The difference is add vs. sub, and left-shift of -1 vs. 1
* Since we only change the shift opcode,
we can preserve the exact-ness: https://rise4fun.com/Alive/4u4
* There can be truncation after high-bit-extraction:
https://rise4fun.com/Alive/slHc1 (the main pattern i'm after!)
Which means that we need to ignore zext of shift amounts and of NBits.
* The sign-extending magic can be extended itself (in add pattern
via sext, in sub pattern via zext. not the other way around!)
https://rise4fun.com/Alive/NhG
(or those sext/zext can be sinked into `select`!)
Which again means we should pay attention when matching NBits.
* We can have both truncation of extraction and widening of magic:
https://rise4fun.com/Alive/XTw
In other words, i don't believe we need to have any checks on
bitwidths of any of these constructs.
This is worsened in general by the fact that we may have `sext` instead
of `zext` for shift amounts, and we don't yet canonicalize to `zext`,
although we should. I have not done anything about that here.
Also, we really should have something to weed out `sub` like these,
by folding them into `add` variant.
https://bugs.llvm.org/show_bug.cgi?id=42389
llvm-svn: 373964
2019-10-07 22:53:27 +02:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = ashr i64 [[DATA]], [[LOW_BITS_TO_SKIP_WIDE]]
|
|
|
|
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = trunc i64 [[TMP1]] to i32
|
2019-10-07 22:53:16 +02:00
|
|
|
; 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]])
|
[InstCombine] Fold conditional sign-extend of high-bit-extract into high-bit-extract-with-signext (PR42389)
This can come up in Bit Stream abstractions.
The pattern looks big/scary, but it can't be simplified any further.
It only is so simple because a number of my preparatory folds had
happened already (shift amount reassociation / shift amount
reassociation in bit test, sign bit test detection).
Highlights:
* There are two main flavors: https://rise4fun.com/Alive/zWi
The difference is add vs. sub, and left-shift of -1 vs. 1
* Since we only change the shift opcode,
we can preserve the exact-ness: https://rise4fun.com/Alive/4u4
* There can be truncation after high-bit-extraction:
https://rise4fun.com/Alive/slHc1 (the main pattern i'm after!)
Which means that we need to ignore zext of shift amounts and of NBits.
* The sign-extending magic can be extended itself (in add pattern
via sext, in sub pattern via zext. not the other way around!)
https://rise4fun.com/Alive/NhG
(or those sext/zext can be sinked into `select`!)
Which again means we should pay attention when matching NBits.
* We can have both truncation of extraction and widening of magic:
https://rise4fun.com/Alive/XTw
In other words, i don't believe we need to have any checks on
bitwidths of any of these constructs.
This is worsened in general by the fact that we may have `sext` instead
of `zext` for shift amounts, and we don't yet canonicalize to `zext`,
although we should. I have not done anything about that here.
Also, we really should have something to weed out `sub` like these,
by folding them into `add` variant.
https://bugs.llvm.org/show_bug.cgi?id=42389
llvm-svn: 373964
2019-10-07 22:53:27 +02:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = ashr i64 [[DATA]], [[LOW_BITS_TO_SKIP_WIDE]]
|
|
|
|
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = trunc i64 [[TMP1]] to i32
|
2019-10-07 22:53:16 +02:00
|
|
|
; 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]])
|
[InstCombine] Fold conditional sign-extend of high-bit-extract into high-bit-extract-with-signext (PR42389)
This can come up in Bit Stream abstractions.
The pattern looks big/scary, but it can't be simplified any further.
It only is so simple because a number of my preparatory folds had
happened already (shift amount reassociation / shift amount
reassociation in bit test, sign bit test detection).
Highlights:
* There are two main flavors: https://rise4fun.com/Alive/zWi
The difference is add vs. sub, and left-shift of -1 vs. 1
* Since we only change the shift opcode,
we can preserve the exact-ness: https://rise4fun.com/Alive/4u4
* There can be truncation after high-bit-extraction:
https://rise4fun.com/Alive/slHc1 (the main pattern i'm after!)
Which means that we need to ignore zext of shift amounts and of NBits.
* The sign-extending magic can be extended itself (in add pattern
via sext, in sub pattern via zext. not the other way around!)
https://rise4fun.com/Alive/NhG
(or those sext/zext can be sinked into `select`!)
Which again means we should pay attention when matching NBits.
* We can have both truncation of extraction and widening of magic:
https://rise4fun.com/Alive/XTw
In other words, i don't believe we need to have any checks on
bitwidths of any of these constructs.
This is worsened in general by the fact that we may have `sext` instead
of `zext` for shift amounts, and we don't yet canonicalize to `zext`,
although we should. I have not done anything about that here.
Also, we really should have something to weed out `sub` like these,
by folding them into `add` variant.
https://bugs.llvm.org/show_bug.cgi?id=42389
llvm-svn: 373964
2019-10-07 22:53:27 +02:00
|
|
|
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = ashr exact i32 [[DATA]], [[LOW_BITS_TO_SKIP]]
|
2019-10-07 22:53:16 +02:00
|
|
|
; 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]])
|
[InstCombine] Fold conditional sign-extend of high-bit-extract into high-bit-extract-with-signext (PR42389)
This can come up in Bit Stream abstractions.
The pattern looks big/scary, but it can't be simplified any further.
It only is so simple because a number of my preparatory folds had
happened already (shift amount reassociation / shift amount
reassociation in bit test, sign bit test detection).
Highlights:
* There are two main flavors: https://rise4fun.com/Alive/zWi
The difference is add vs. sub, and left-shift of -1 vs. 1
* Since we only change the shift opcode,
we can preserve the exact-ness: https://rise4fun.com/Alive/4u4
* There can be truncation after high-bit-extraction:
https://rise4fun.com/Alive/slHc1 (the main pattern i'm after!)
Which means that we need to ignore zext of shift amounts and of NBits.
* The sign-extending magic can be extended itself (in add pattern
via sext, in sub pattern via zext. not the other way around!)
https://rise4fun.com/Alive/NhG
(or those sext/zext can be sinked into `select`!)
Which again means we should pay attention when matching NBits.
* We can have both truncation of extraction and widening of magic:
https://rise4fun.com/Alive/XTw
In other words, i don't believe we need to have any checks on
bitwidths of any of these constructs.
This is worsened in general by the fact that we may have `sext` instead
of `zext` for shift amounts, and we don't yet canonicalize to `zext`,
although we should. I have not done anything about that here.
Also, we really should have something to weed out `sub` like these,
by folding them into `add` variant.
https://bugs.llvm.org/show_bug.cgi?id=42389
llvm-svn: 373964
2019-10-07 22:53:27 +02:00
|
|
|
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = ashr i32 [[DATA]], [[LOW_BITS_TO_SKIP_32]]
|
2019-10-07 22:53:16 +02:00
|
|
|
; 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]])
|
[InstCombine] Fold conditional sign-extend of high-bit-extract into high-bit-extract-with-signext (PR42389)
This can come up in Bit Stream abstractions.
The pattern looks big/scary, but it can't be simplified any further.
It only is so simple because a number of my preparatory folds had
happened already (shift amount reassociation / shift amount
reassociation in bit test, sign bit test detection).
Highlights:
* There are two main flavors: https://rise4fun.com/Alive/zWi
The difference is add vs. sub, and left-shift of -1 vs. 1
* Since we only change the shift opcode,
we can preserve the exact-ness: https://rise4fun.com/Alive/4u4
* There can be truncation after high-bit-extraction:
https://rise4fun.com/Alive/slHc1 (the main pattern i'm after!)
Which means that we need to ignore zext of shift amounts and of NBits.
* The sign-extending magic can be extended itself (in add pattern
via sext, in sub pattern via zext. not the other way around!)
https://rise4fun.com/Alive/NhG
(or those sext/zext can be sinked into `select`!)
Which again means we should pay attention when matching NBits.
* We can have both truncation of extraction and widening of magic:
https://rise4fun.com/Alive/XTw
In other words, i don't believe we need to have any checks on
bitwidths of any of these constructs.
This is worsened in general by the fact that we may have `sext` instead
of `zext` for shift amounts, and we don't yet canonicalize to `zext`,
although we should. I have not done anything about that here.
Also, we really should have something to weed out `sub` like these,
by folding them into `add` variant.
https://bugs.llvm.org/show_bug.cgi?id=42389
llvm-svn: 373964
2019-10-07 22:53:27 +02:00
|
|
|
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = ashr i32 [[DATA]], [[LOW_BITS_TO_SKIP]]
|
2019-10-07 22:53:16 +02:00
|
|
|
; 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]])
|
[InstCombine] Fold conditional sign-extend of high-bit-extract into high-bit-extract-with-signext (PR42389)
This can come up in Bit Stream abstractions.
The pattern looks big/scary, but it can't be simplified any further.
It only is so simple because a number of my preparatory folds had
happened already (shift amount reassociation / shift amount
reassociation in bit test, sign bit test detection).
Highlights:
* There are two main flavors: https://rise4fun.com/Alive/zWi
The difference is add vs. sub, and left-shift of -1 vs. 1
* Since we only change the shift opcode,
we can preserve the exact-ness: https://rise4fun.com/Alive/4u4
* There can be truncation after high-bit-extraction:
https://rise4fun.com/Alive/slHc1 (the main pattern i'm after!)
Which means that we need to ignore zext of shift amounts and of NBits.
* The sign-extending magic can be extended itself (in add pattern
via sext, in sub pattern via zext. not the other way around!)
https://rise4fun.com/Alive/NhG
(or those sext/zext can be sinked into `select`!)
Which again means we should pay attention when matching NBits.
* We can have both truncation of extraction and widening of magic:
https://rise4fun.com/Alive/XTw
In other words, i don't believe we need to have any checks on
bitwidths of any of these constructs.
This is worsened in general by the fact that we may have `sext` instead
of `zext` for shift amounts, and we don't yet canonicalize to `zext`,
although we should. I have not done anything about that here.
Also, we really should have something to weed out `sub` like these,
by folding them into `add` variant.
https://bugs.llvm.org/show_bug.cgi?id=42389
llvm-svn: 373964
2019-10-07 22:53:27 +02:00
|
|
|
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = ashr i32 [[DATA]], [[LOW_BITS_TO_SKIP]]
|
2019-10-07 22:53:16 +02:00
|
|
|
; 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]])
|
[InstCombine] Fold conditional sign-extend of high-bit-extract into high-bit-extract-with-signext (PR42389)
This can come up in Bit Stream abstractions.
The pattern looks big/scary, but it can't be simplified any further.
It only is so simple because a number of my preparatory folds had
happened already (shift amount reassociation / shift amount
reassociation in bit test, sign bit test detection).
Highlights:
* There are two main flavors: https://rise4fun.com/Alive/zWi
The difference is add vs. sub, and left-shift of -1 vs. 1
* Since we only change the shift opcode,
we can preserve the exact-ness: https://rise4fun.com/Alive/4u4
* There can be truncation after high-bit-extraction:
https://rise4fun.com/Alive/slHc1 (the main pattern i'm after!)
Which means that we need to ignore zext of shift amounts and of NBits.
* The sign-extending magic can be extended itself (in add pattern
via sext, in sub pattern via zext. not the other way around!)
https://rise4fun.com/Alive/NhG
(or those sext/zext can be sinked into `select`!)
Which again means we should pay attention when matching NBits.
* We can have both truncation of extraction and widening of magic:
https://rise4fun.com/Alive/XTw
In other words, i don't believe we need to have any checks on
bitwidths of any of these constructs.
This is worsened in general by the fact that we may have `sext` instead
of `zext` for shift amounts, and we don't yet canonicalize to `zext`,
although we should. I have not done anything about that here.
Also, we really should have something to weed out `sub` like these,
by folding them into `add` variant.
https://bugs.llvm.org/show_bug.cgi?id=42389
llvm-svn: 373964
2019-10-07 22:53:27 +02:00
|
|
|
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = ashr i32 [[DATA]], [[LOW_BITS_TO_SKIP]]
|
2019-10-07 22:53:16 +02:00
|
|
|
; 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]])
|
[InstCombine] Fold conditional sign-extend of high-bit-extract into high-bit-extract-with-signext (PR42389)
This can come up in Bit Stream abstractions.
The pattern looks big/scary, but it can't be simplified any further.
It only is so simple because a number of my preparatory folds had
happened already (shift amount reassociation / shift amount
reassociation in bit test, sign bit test detection).
Highlights:
* There are two main flavors: https://rise4fun.com/Alive/zWi
The difference is add vs. sub, and left-shift of -1 vs. 1
* Since we only change the shift opcode,
we can preserve the exact-ness: https://rise4fun.com/Alive/4u4
* There can be truncation after high-bit-extraction:
https://rise4fun.com/Alive/slHc1 (the main pattern i'm after!)
Which means that we need to ignore zext of shift amounts and of NBits.
* The sign-extending magic can be extended itself (in add pattern
via sext, in sub pattern via zext. not the other way around!)
https://rise4fun.com/Alive/NhG
(or those sext/zext can be sinked into `select`!)
Which again means we should pay attention when matching NBits.
* We can have both truncation of extraction and widening of magic:
https://rise4fun.com/Alive/XTw
In other words, i don't believe we need to have any checks on
bitwidths of any of these constructs.
This is worsened in general by the fact that we may have `sext` instead
of `zext` for shift amounts, and we don't yet canonicalize to `zext`,
although we should. I have not done anything about that here.
Also, we really should have something to weed out `sub` like these,
by folding them into `add` variant.
https://bugs.llvm.org/show_bug.cgi?id=42389
llvm-svn: 373964
2019-10-07 22:53:27 +02:00
|
|
|
; CHECK-NEXT: [[SIGNEXTENDED:%.*]] = ashr i32 [[DATA]], [[LOW_BITS_TO_SKIP]]
|
2019-10-07 22:53:16 +02:00
|
|
|
; 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
|
|
|
|
}
|
2019-10-20 22:51:37 +02:00
|
|
|
|
|
|
|
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
|
|
|
|
}
|