2019-04-17 12:52:47 +08:00
|
|
|
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
|
|
; RUN: opt < %s -instcombine -S | FileCheck %s
|
|
|
|
|
|
|
|
define i64 @test_sext_zext(i16 %A) {
|
|
|
|
; CHECK-LABEL: @test_sext_zext(
|
2019-12-31 03:56:57 +08:00
|
|
|
; CHECK-NEXT: [[C2:%.*]] = zext i16 [[A:%.*]] to i64
|
2019-04-17 12:52:47 +08:00
|
|
|
; CHECK-NEXT: ret i64 [[C2]]
|
|
|
|
;
|
|
|
|
%c1 = zext i16 %A to i32
|
|
|
|
%c2 = sext i32 %c1 to i64
|
|
|
|
ret i64 %c2
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i64> @test2(<2 x i1> %A) {
|
|
|
|
; CHECK-LABEL: @test2(
|
2019-12-31 03:56:57 +08:00
|
|
|
; CHECK-NEXT: [[XOR:%.*]] = xor <2 x i1> [[A:%.*]], <i1 true, i1 true>
|
2019-04-17 12:52:47 +08:00
|
|
|
; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i1> [[XOR]] to <2 x i64>
|
|
|
|
; CHECK-NEXT: ret <2 x i64> [[ZEXT]]
|
|
|
|
;
|
|
|
|
%xor = xor <2 x i1> %A, <i1 true, i1 true>
|
|
|
|
%zext = zext <2 x i1> %xor to <2 x i64>
|
|
|
|
ret <2 x i64> %zext
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i64> @test3(<2 x i64> %A) {
|
|
|
|
; CHECK-LABEL: @test3(
|
2019-12-31 03:56:57 +08:00
|
|
|
; CHECK-NEXT: [[ZEXT:%.*]] = and <2 x i64> [[A:%.*]], <i64 23, i64 42>
|
|
|
|
; CHECK-NEXT: ret <2 x i64> [[ZEXT]]
|
2019-04-17 12:52:47 +08:00
|
|
|
;
|
|
|
|
%trunc = trunc <2 x i64> %A to <2 x i32>
|
|
|
|
%and = and <2 x i32> %trunc, <i32 23, i32 42>
|
|
|
|
%zext = zext <2 x i32> %and to <2 x i64>
|
|
|
|
ret <2 x i64> %zext
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i64> @test4(<2 x i64> %A) {
|
|
|
|
; CHECK-LABEL: @test4(
|
2019-12-31 03:56:57 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i64> [[A:%.*]], <i64 23, i64 42>
|
|
|
|
; CHECK-NEXT: [[ZEXT:%.*]] = xor <2 x i64> [[TMP1]], <i64 23, i64 42>
|
|
|
|
; CHECK-NEXT: ret <2 x i64> [[ZEXT]]
|
2019-04-17 12:52:47 +08:00
|
|
|
;
|
|
|
|
%trunc = trunc <2 x i64> %A to <2 x i32>
|
|
|
|
%and = and <2 x i32> %trunc, <i32 23, i32 42>
|
|
|
|
%xor = xor <2 x i32> %and, <i32 23, i32 42>
|
|
|
|
%zext = zext <2 x i32> %xor to <2 x i64>
|
|
|
|
ret <2 x i64> %zext
|
|
|
|
}
|
|
|
|
|
|
|
|
define i64 @fold_xor_zext_sandwich(i1 %a) {
|
|
|
|
; CHECK-LABEL: @fold_xor_zext_sandwich(
|
2019-12-31 03:56:57 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = xor i1 [[A:%.*]], true
|
2019-04-17 12:52:47 +08:00
|
|
|
; CHECK-NEXT: [[ZEXT2:%.*]] = zext i1 [[TMP1]] to i64
|
|
|
|
; CHECK-NEXT: ret i64 [[ZEXT2]]
|
|
|
|
;
|
|
|
|
%zext1 = zext i1 %a to i32
|
|
|
|
%xor = xor i32 %zext1, 1
|
|
|
|
%zext2 = zext i32 %xor to i64
|
|
|
|
ret i64 %zext2
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i64> @fold_xor_zext_sandwich_vec(<2 x i1> %a) {
|
|
|
|
; CHECK-LABEL: @fold_xor_zext_sandwich_vec(
|
2019-12-31 03:56:57 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = xor <2 x i1> [[A:%.*]], <i1 true, i1 true>
|
2019-04-17 12:52:47 +08:00
|
|
|
; CHECK-NEXT: [[ZEXT2:%.*]] = zext <2 x i1> [[TMP1]] to <2 x i64>
|
|
|
|
; CHECK-NEXT: ret <2 x i64> [[ZEXT2]]
|
|
|
|
;
|
|
|
|
%zext1 = zext <2 x i1> %a to <2 x i32>
|
|
|
|
%xor = xor <2 x i32> %zext1, <i32 1, i32 1>
|
|
|
|
%zext2 = zext <2 x i32> %xor to <2 x i64>
|
|
|
|
ret <2 x i64> %zext2
|
|
|
|
}
|
|
|
|
|
|
|
|
; Assert that zexts in and(zext(icmp), zext(icmp)) can be folded.
|
|
|
|
|
|
|
|
define i8 @fold_and_zext_icmp(i64 %a, i64 %b, i64 %c) {
|
|
|
|
; CHECK-LABEL: @fold_and_zext_icmp(
|
2019-12-31 03:56:57 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i64 [[A:%.*]], [[B:%.*]]
|
|
|
|
; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i64 [[A]], [[C:%.*]]
|
2019-04-17 12:52:47 +08:00
|
|
|
; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP1]], [[TMP2]]
|
|
|
|
; CHECK-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i8
|
|
|
|
; CHECK-NEXT: ret i8 [[TMP4]]
|
|
|
|
;
|
|
|
|
%1 = icmp sgt i64 %a, %b
|
|
|
|
%2 = zext i1 %1 to i8
|
|
|
|
%3 = icmp slt i64 %a, %c
|
|
|
|
%4 = zext i1 %3 to i8
|
|
|
|
%5 = and i8 %2, %4
|
|
|
|
ret i8 %5
|
|
|
|
}
|
|
|
|
|
|
|
|
; Assert that zexts in or(zext(icmp), zext(icmp)) can be folded.
|
|
|
|
|
|
|
|
define i8 @fold_or_zext_icmp(i64 %a, i64 %b, i64 %c) {
|
|
|
|
; CHECK-LABEL: @fold_or_zext_icmp(
|
2019-12-31 03:56:57 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i64 [[A:%.*]], [[B:%.*]]
|
|
|
|
; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i64 [[A]], [[C:%.*]]
|
2019-04-17 12:52:47 +08:00
|
|
|
; CHECK-NEXT: [[TMP3:%.*]] = or i1 [[TMP1]], [[TMP2]]
|
|
|
|
; CHECK-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i8
|
|
|
|
; CHECK-NEXT: ret i8 [[TMP4]]
|
|
|
|
;
|
|
|
|
%1 = icmp sgt i64 %a, %b
|
|
|
|
%2 = zext i1 %1 to i8
|
|
|
|
%3 = icmp slt i64 %a, %c
|
|
|
|
%4 = zext i1 %3 to i8
|
|
|
|
%5 = or i8 %2, %4
|
|
|
|
ret i8 %5
|
|
|
|
}
|
|
|
|
|
|
|
|
; Assert that zexts in xor(zext(icmp), zext(icmp)) can be folded.
|
|
|
|
|
|
|
|
define i8 @fold_xor_zext_icmp(i64 %a, i64 %b, i64 %c) {
|
|
|
|
; CHECK-LABEL: @fold_xor_zext_icmp(
|
2019-12-31 03:56:57 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i64 [[A:%.*]], [[B:%.*]]
|
|
|
|
; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i64 [[A]], [[C:%.*]]
|
2019-04-17 12:52:47 +08:00
|
|
|
; CHECK-NEXT: [[TMP3:%.*]] = xor i1 [[TMP1]], [[TMP2]]
|
|
|
|
; CHECK-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i8
|
|
|
|
; CHECK-NEXT: ret i8 [[TMP4]]
|
|
|
|
;
|
|
|
|
%1 = icmp sgt i64 %a, %b
|
|
|
|
%2 = zext i1 %1 to i8
|
|
|
|
%3 = icmp slt i64 %a, %c
|
|
|
|
%4 = zext i1 %3 to i8
|
|
|
|
%5 = xor i8 %2, %4
|
|
|
|
ret i8 %5
|
|
|
|
}
|
|
|
|
|
|
|
|
; Assert that zexts in logic(zext(icmp), zext(icmp)) are also folded accross
|
|
|
|
; nested logical operators.
|
|
|
|
|
|
|
|
define i8 @fold_nested_logic_zext_icmp(i64 %a, i64 %b, i64 %c, i64 %d) {
|
|
|
|
; CHECK-LABEL: @fold_nested_logic_zext_icmp(
|
2019-12-31 03:56:57 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i64 [[A:%.*]], [[B:%.*]]
|
|
|
|
; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i64 [[A]], [[C:%.*]]
|
2019-04-17 12:52:47 +08:00
|
|
|
; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP1]], [[TMP2]]
|
2019-12-31 03:56:57 +08:00
|
|
|
; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i64 [[A]], [[D:%.*]]
|
2019-04-17 12:52:47 +08:00
|
|
|
; CHECK-NEXT: [[TMP5:%.*]] = or i1 [[TMP3]], [[TMP4]]
|
|
|
|
; CHECK-NEXT: [[TMP6:%.*]] = zext i1 [[TMP5]] to i8
|
|
|
|
; CHECK-NEXT: ret i8 [[TMP6]]
|
|
|
|
;
|
|
|
|
%1 = icmp sgt i64 %a, %b
|
|
|
|
%2 = zext i1 %1 to i8
|
|
|
|
%3 = icmp slt i64 %a, %c
|
|
|
|
%4 = zext i1 %3 to i8
|
|
|
|
%5 = and i8 %2, %4
|
|
|
|
%6 = icmp eq i64 %a, %d
|
|
|
|
%7 = zext i1 %6 to i8
|
|
|
|
%8 = or i8 %5, %7
|
|
|
|
ret i8 %8
|
|
|
|
}
|
|
|
|
|
|
|
|
; This test is for Integer BitWidth > 64 && BitWidth <= 1024.
|
|
|
|
|
|
|
|
define i1024 @sext_zext_apint1(i77 %A) {
|
|
|
|
; CHECK-LABEL: @sext_zext_apint1(
|
2019-12-31 03:56:57 +08:00
|
|
|
; CHECK-NEXT: [[C2:%.*]] = zext i77 [[A:%.*]] to i1024
|
2019-04-17 12:52:47 +08:00
|
|
|
; CHECK-NEXT: ret i1024 [[C2]]
|
|
|
|
;
|
|
|
|
%c1 = zext i77 %A to i533
|
|
|
|
%c2 = sext i533 %c1 to i1024
|
|
|
|
ret i1024 %c2
|
|
|
|
}
|
|
|
|
|
|
|
|
; This test is for Integer BitWidth <= 64 && BitWidth % 2 != 0.
|
|
|
|
|
|
|
|
define i47 @sext_zext_apint2(i11 %A) {
|
|
|
|
; CHECK-LABEL: @sext_zext_apint2(
|
2019-12-31 03:56:57 +08:00
|
|
|
; CHECK-NEXT: [[C2:%.*]] = zext i11 [[A:%.*]] to i47
|
2019-04-17 12:52:47 +08:00
|
|
|
; CHECK-NEXT: ret i47 [[C2]]
|
|
|
|
;
|
|
|
|
%c1 = zext i11 %A to i39
|
|
|
|
%c2 = sext i39 %c1 to i47
|
|
|
|
ret i47 %c2
|
|
|
|
}
|
|
|
|
|
2019-12-31 03:56:57 +08:00
|
|
|
declare void @use1(i1)
|
|
|
|
declare void @use32(i32)
|
|
|
|
|
|
|
|
define i32 @masked_bit_set(i32 %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @masked_bit_set(
|
[InstCombine] fold zext of masked bit set/clear
This does not solve PR17101, but it is one of the
underlying diffs noted here:
https://bugs.llvm.org/show_bug.cgi?id=17101#c8
We could ease the one-use checks for the 'clear'
(no 'not' op) half of the transform, but I do not
know if that asymmetry would make things better
or worse.
Proofs:
https://rise4fun.com/Alive/uVB
Name: masked bit set
%sh1 = shl i32 1, %y
%and = and i32 %sh1, %x
%cmp = icmp ne i32 %and, 0
%r = zext i1 %cmp to i32
=>
%s = lshr i32 %x, %y
%r = and i32 %s, 1
Name: masked bit clear
%sh1 = shl i32 1, %y
%and = and i32 %sh1, %x
%cmp = icmp eq i32 %and, 0
%r = zext i1 %cmp to i32
=>
%xn = xor i32 %x, -1
%s = lshr i32 %xn, %y
%r = and i32 %s, 1
Note: this is a re-post of a patch that I committed at:
rGa041c4ec6f7a
The commit was reverted because it exposed another bug:
rGb212eb7159b40
But that has since been corrected with:
rG8a156d1c2795189 ( D101191 )
Differential Revision: https://reviews.llvm.org/D72396
2021-05-29 20:52:26 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], 1
|
|
|
|
; CHECK-NEXT: ret i32 [[TMP2]]
|
2019-12-31 03:56:57 +08:00
|
|
|
;
|
|
|
|
%sh1 = shl i32 1, %y
|
|
|
|
%and = and i32 %sh1, %x
|
|
|
|
%cmp = icmp ne i32 %and, 0
|
|
|
|
%r = zext i1 %cmp to i32
|
|
|
|
ret i32 %r
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i32> @masked_bit_clear(<2 x i32> %x, <2 x i32> %y) {
|
|
|
|
; CHECK-LABEL: @masked_bit_clear(
|
[InstCombine] fold zext of masked bit set/clear
This does not solve PR17101, but it is one of the
underlying diffs noted here:
https://bugs.llvm.org/show_bug.cgi?id=17101#c8
We could ease the one-use checks for the 'clear'
(no 'not' op) half of the transform, but I do not
know if that asymmetry would make things better
or worse.
Proofs:
https://rise4fun.com/Alive/uVB
Name: masked bit set
%sh1 = shl i32 1, %y
%and = and i32 %sh1, %x
%cmp = icmp ne i32 %and, 0
%r = zext i1 %cmp to i32
=>
%s = lshr i32 %x, %y
%r = and i32 %s, 1
Name: masked bit clear
%sh1 = shl i32 1, %y
%and = and i32 %sh1, %x
%cmp = icmp eq i32 %and, 0
%r = zext i1 %cmp to i32
=>
%xn = xor i32 %x, -1
%s = lshr i32 %xn, %y
%r = and i32 %s, 1
Note: this is a re-post of a patch that I committed at:
rGa041c4ec6f7a
The commit was reverted because it exposed another bug:
rGb212eb7159b40
But that has since been corrected with:
rG8a156d1c2795189 ( D101191 )
Differential Revision: https://reviews.llvm.org/D72396
2021-05-29 20:52:26 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = xor <2 x i32> [[X:%.*]], <i32 -1, i32 -1>
|
|
|
|
; CHECK-NEXT: [[TMP2:%.*]] = lshr <2 x i32> [[TMP1]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: [[TMP3:%.*]] = and <2 x i32> [[TMP2]], <i32 1, i32 1>
|
|
|
|
; CHECK-NEXT: ret <2 x i32> [[TMP3]]
|
2019-12-31 03:56:57 +08:00
|
|
|
;
|
|
|
|
%sh1 = shl <2 x i32> <i32 1, i32 1>, %y
|
|
|
|
%and = and <2 x i32> %sh1, %x
|
|
|
|
%cmp = icmp eq <2 x i32> %and, zeroinitializer
|
|
|
|
%r = zext <2 x i1> %cmp to <2 x i32>
|
|
|
|
ret <2 x i32> %r
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i32> @masked_bit_set_commute(<2 x i32> %px, <2 x i32> %y) {
|
|
|
|
; CHECK-LABEL: @masked_bit_set_commute(
|
|
|
|
; CHECK-NEXT: [[X:%.*]] = srem <2 x i32> <i32 42, i32 3>, [[PX:%.*]]
|
[InstCombine] fold zext of masked bit set/clear
This does not solve PR17101, but it is one of the
underlying diffs noted here:
https://bugs.llvm.org/show_bug.cgi?id=17101#c8
We could ease the one-use checks for the 'clear'
(no 'not' op) half of the transform, but I do not
know if that asymmetry would make things better
or worse.
Proofs:
https://rise4fun.com/Alive/uVB
Name: masked bit set
%sh1 = shl i32 1, %y
%and = and i32 %sh1, %x
%cmp = icmp ne i32 %and, 0
%r = zext i1 %cmp to i32
=>
%s = lshr i32 %x, %y
%r = and i32 %s, 1
Name: masked bit clear
%sh1 = shl i32 1, %y
%and = and i32 %sh1, %x
%cmp = icmp eq i32 %and, 0
%r = zext i1 %cmp to i32
=>
%xn = xor i32 %x, -1
%s = lshr i32 %xn, %y
%r = and i32 %s, 1
Note: this is a re-post of a patch that I committed at:
rGa041c4ec6f7a
The commit was reverted because it exposed another bug:
rGb212eb7159b40
But that has since been corrected with:
rG8a156d1c2795189 ( D101191 )
Differential Revision: https://reviews.llvm.org/D72396
2021-05-29 20:52:26 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i32> [[X]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i32> [[TMP1]], <i32 1, i32 1>
|
|
|
|
; CHECK-NEXT: ret <2 x i32> [[TMP2]]
|
2019-12-31 03:56:57 +08:00
|
|
|
;
|
|
|
|
%x = srem <2 x i32> <i32 42, i32 3>, %px ; thwart complexity-based canonicalization
|
|
|
|
%sh1 = shl <2 x i32> <i32 1, i32 1>, %y
|
|
|
|
%and = and <2 x i32> %x, %sh1
|
|
|
|
%cmp = icmp ne <2 x i32> %and, zeroinitializer
|
|
|
|
%r = zext <2 x i1> %cmp to <2 x i32>
|
|
|
|
ret <2 x i32> %r
|
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @masked_bit_clear_commute(i32 %px, i32 %y) {
|
|
|
|
; CHECK-LABEL: @masked_bit_clear_commute(
|
|
|
|
; CHECK-NEXT: [[X:%.*]] = srem i32 42, [[PX:%.*]]
|
[InstCombine] fold zext of masked bit set/clear
This does not solve PR17101, but it is one of the
underlying diffs noted here:
https://bugs.llvm.org/show_bug.cgi?id=17101#c8
We could ease the one-use checks for the 'clear'
(no 'not' op) half of the transform, but I do not
know if that asymmetry would make things better
or worse.
Proofs:
https://rise4fun.com/Alive/uVB
Name: masked bit set
%sh1 = shl i32 1, %y
%and = and i32 %sh1, %x
%cmp = icmp ne i32 %and, 0
%r = zext i1 %cmp to i32
=>
%s = lshr i32 %x, %y
%r = and i32 %s, 1
Name: masked bit clear
%sh1 = shl i32 1, %y
%and = and i32 %sh1, %x
%cmp = icmp eq i32 %and, 0
%r = zext i1 %cmp to i32
=>
%xn = xor i32 %x, -1
%s = lshr i32 %xn, %y
%r = and i32 %s, 1
Note: this is a re-post of a patch that I committed at:
rGa041c4ec6f7a
The commit was reverted because it exposed another bug:
rGb212eb7159b40
But that has since been corrected with:
rG8a156d1c2795189 ( D101191 )
Differential Revision: https://reviews.llvm.org/D72396
2021-05-29 20:52:26 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[X]], -1
|
|
|
|
; CHECK-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: [[TMP3:%.*]] = and i32 [[TMP2]], 1
|
|
|
|
; CHECK-NEXT: ret i32 [[TMP3]]
|
2019-12-31 03:56:57 +08:00
|
|
|
;
|
|
|
|
%x = srem i32 42, %px ; thwart complexity-based canonicalization
|
|
|
|
%sh1 = shl i32 1, %y
|
|
|
|
%and = and i32 %x, %sh1
|
|
|
|
%cmp = icmp eq i32 %and, 0
|
|
|
|
%r = zext i1 %cmp to i32
|
|
|
|
ret i32 %r
|
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @masked_bit_set_use1(i32 %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @masked_bit_set_use1(
|
|
|
|
; CHECK-NEXT: [[SH1:%.*]] = shl i32 1, [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: call void @use32(i32 [[SH1]])
|
[InstCombine] fold zext of masked bit set/clear
This does not solve PR17101, but it is one of the
underlying diffs noted here:
https://bugs.llvm.org/show_bug.cgi?id=17101#c8
We could ease the one-use checks for the 'clear'
(no 'not' op) half of the transform, but I do not
know if that asymmetry would make things better
or worse.
Proofs:
https://rise4fun.com/Alive/uVB
Name: masked bit set
%sh1 = shl i32 1, %y
%and = and i32 %sh1, %x
%cmp = icmp ne i32 %and, 0
%r = zext i1 %cmp to i32
=>
%s = lshr i32 %x, %y
%r = and i32 %s, 1
Name: masked bit clear
%sh1 = shl i32 1, %y
%and = and i32 %sh1, %x
%cmp = icmp eq i32 %and, 0
%r = zext i1 %cmp to i32
=>
%xn = xor i32 %x, -1
%s = lshr i32 %xn, %y
%r = and i32 %s, 1
Note: this is a re-post of a patch that I committed at:
rGa041c4ec6f7a
The commit was reverted because it exposed another bug:
rGb212eb7159b40
But that has since been corrected with:
rG8a156d1c2795189 ( D101191 )
Differential Revision: https://reviews.llvm.org/D72396
2021-05-29 20:52:26 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], [[Y]]
|
|
|
|
; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], 1
|
|
|
|
; CHECK-NEXT: ret i32 [[TMP2]]
|
2019-12-31 03:56:57 +08:00
|
|
|
;
|
|
|
|
%sh1 = shl i32 1, %y
|
|
|
|
call void @use32(i32 %sh1)
|
|
|
|
%and = and i32 %sh1, %x
|
|
|
|
%cmp = icmp ne i32 %and, 0
|
|
|
|
%r = zext i1 %cmp to i32
|
|
|
|
ret i32 %r
|
|
|
|
}
|
|
|
|
|
[InstCombine] fold zext of masked bit set/clear
This does not solve PR17101, but it is one of the
underlying diffs noted here:
https://bugs.llvm.org/show_bug.cgi?id=17101#c8
We could ease the one-use checks for the 'clear'
(no 'not' op) half of the transform, but I do not
know if that asymmetry would make things better
or worse.
Proofs:
https://rise4fun.com/Alive/uVB
Name: masked bit set
%sh1 = shl i32 1, %y
%and = and i32 %sh1, %x
%cmp = icmp ne i32 %and, 0
%r = zext i1 %cmp to i32
=>
%s = lshr i32 %x, %y
%r = and i32 %s, 1
Name: masked bit clear
%sh1 = shl i32 1, %y
%and = and i32 %sh1, %x
%cmp = icmp eq i32 %and, 0
%r = zext i1 %cmp to i32
=>
%xn = xor i32 %x, -1
%s = lshr i32 %xn, %y
%r = and i32 %s, 1
Note: this is a re-post of a patch that I committed at:
rGa041c4ec6f7a
The commit was reverted because it exposed another bug:
rGb212eb7159b40
But that has since been corrected with:
rG8a156d1c2795189 ( D101191 )
Differential Revision: https://reviews.llvm.org/D72396
2021-05-29 20:52:26 +08:00
|
|
|
; Negative test
|
|
|
|
|
2019-12-31 03:56:57 +08:00
|
|
|
define i32 @masked_bit_set_use2(i32 %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @masked_bit_set_use2(
|
|
|
|
; CHECK-NEXT: [[SH1:%.*]] = shl i32 1, [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: [[AND:%.*]] = and i32 [[SH1]], [[X:%.*]]
|
|
|
|
; CHECK-NEXT: call void @use32(i32 [[AND]])
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[AND]], 0
|
|
|
|
; CHECK-NEXT: [[R:%.*]] = zext i1 [[CMP]] to i32
|
|
|
|
; CHECK-NEXT: ret i32 [[R]]
|
|
|
|
;
|
|
|
|
%sh1 = shl i32 1, %y
|
|
|
|
%and = and i32 %sh1, %x
|
|
|
|
call void @use32(i32 %and)
|
|
|
|
%cmp = icmp ne i32 %and, 0
|
|
|
|
%r = zext i1 %cmp to i32
|
|
|
|
ret i32 %r
|
|
|
|
}
|
|
|
|
|
[InstCombine] fold zext of masked bit set/clear
This does not solve PR17101, but it is one of the
underlying diffs noted here:
https://bugs.llvm.org/show_bug.cgi?id=17101#c8
We could ease the one-use checks for the 'clear'
(no 'not' op) half of the transform, but I do not
know if that asymmetry would make things better
or worse.
Proofs:
https://rise4fun.com/Alive/uVB
Name: masked bit set
%sh1 = shl i32 1, %y
%and = and i32 %sh1, %x
%cmp = icmp ne i32 %and, 0
%r = zext i1 %cmp to i32
=>
%s = lshr i32 %x, %y
%r = and i32 %s, 1
Name: masked bit clear
%sh1 = shl i32 1, %y
%and = and i32 %sh1, %x
%cmp = icmp eq i32 %and, 0
%r = zext i1 %cmp to i32
=>
%xn = xor i32 %x, -1
%s = lshr i32 %xn, %y
%r = and i32 %s, 1
Note: this is a re-post of a patch that I committed at:
rGa041c4ec6f7a
The commit was reverted because it exposed another bug:
rGb212eb7159b40
But that has since been corrected with:
rG8a156d1c2795189 ( D101191 )
Differential Revision: https://reviews.llvm.org/D72396
2021-05-29 20:52:26 +08:00
|
|
|
; Negative test
|
|
|
|
|
2019-12-31 03:56:57 +08:00
|
|
|
define i32 @masked_bit_set_use3(i32 %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @masked_bit_set_use3(
|
|
|
|
; CHECK-NEXT: [[SH1:%.*]] = shl i32 1, [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: [[AND:%.*]] = and i32 [[SH1]], [[X:%.*]]
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[AND]], 0
|
|
|
|
; CHECK-NEXT: call void @use1(i1 [[CMP]])
|
|
|
|
; CHECK-NEXT: [[R:%.*]] = zext i1 [[CMP]] to i32
|
|
|
|
; CHECK-NEXT: ret i32 [[R]]
|
|
|
|
;
|
|
|
|
%sh1 = shl i32 1, %y
|
|
|
|
%and = and i32 %sh1, %x
|
|
|
|
%cmp = icmp ne i32 %and, 0
|
|
|
|
call void @use1(i1 %cmp)
|
|
|
|
%r = zext i1 %cmp to i32
|
|
|
|
ret i32 %r
|
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @masked_bit_clear_use1(i32 %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @masked_bit_clear_use1(
|
|
|
|
; CHECK-NEXT: [[SH1:%.*]] = shl i32 1, [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: call void @use32(i32 [[SH1]])
|
[InstCombine] fold zext of masked bit set/clear
This does not solve PR17101, but it is one of the
underlying diffs noted here:
https://bugs.llvm.org/show_bug.cgi?id=17101#c8
We could ease the one-use checks for the 'clear'
(no 'not' op) half of the transform, but I do not
know if that asymmetry would make things better
or worse.
Proofs:
https://rise4fun.com/Alive/uVB
Name: masked bit set
%sh1 = shl i32 1, %y
%and = and i32 %sh1, %x
%cmp = icmp ne i32 %and, 0
%r = zext i1 %cmp to i32
=>
%s = lshr i32 %x, %y
%r = and i32 %s, 1
Name: masked bit clear
%sh1 = shl i32 1, %y
%and = and i32 %sh1, %x
%cmp = icmp eq i32 %and, 0
%r = zext i1 %cmp to i32
=>
%xn = xor i32 %x, -1
%s = lshr i32 %xn, %y
%r = and i32 %s, 1
Note: this is a re-post of a patch that I committed at:
rGa041c4ec6f7a
The commit was reverted because it exposed another bug:
rGb212eb7159b40
But that has since been corrected with:
rG8a156d1c2795189 ( D101191 )
Differential Revision: https://reviews.llvm.org/D72396
2021-05-29 20:52:26 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[X:%.*]], -1
|
|
|
|
; CHECK-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], [[Y]]
|
|
|
|
; CHECK-NEXT: [[TMP3:%.*]] = and i32 [[TMP2]], 1
|
|
|
|
; CHECK-NEXT: ret i32 [[TMP3]]
|
2019-12-31 03:56:57 +08:00
|
|
|
;
|
|
|
|
%sh1 = shl i32 1, %y
|
|
|
|
call void @use32(i32 %sh1)
|
|
|
|
%and = and i32 %sh1, %x
|
2020-01-01 01:00:07 +08:00
|
|
|
%cmp = icmp eq i32 %and, 0
|
2019-12-31 03:56:57 +08:00
|
|
|
%r = zext i1 %cmp to i32
|
|
|
|
ret i32 %r
|
|
|
|
}
|
|
|
|
|
[InstCombine] fold zext of masked bit set/clear
This does not solve PR17101, but it is one of the
underlying diffs noted here:
https://bugs.llvm.org/show_bug.cgi?id=17101#c8
We could ease the one-use checks for the 'clear'
(no 'not' op) half of the transform, but I do not
know if that asymmetry would make things better
or worse.
Proofs:
https://rise4fun.com/Alive/uVB
Name: masked bit set
%sh1 = shl i32 1, %y
%and = and i32 %sh1, %x
%cmp = icmp ne i32 %and, 0
%r = zext i1 %cmp to i32
=>
%s = lshr i32 %x, %y
%r = and i32 %s, 1
Name: masked bit clear
%sh1 = shl i32 1, %y
%and = and i32 %sh1, %x
%cmp = icmp eq i32 %and, 0
%r = zext i1 %cmp to i32
=>
%xn = xor i32 %x, -1
%s = lshr i32 %xn, %y
%r = and i32 %s, 1
Note: this is a re-post of a patch that I committed at:
rGa041c4ec6f7a
The commit was reverted because it exposed another bug:
rGb212eb7159b40
But that has since been corrected with:
rG8a156d1c2795189 ( D101191 )
Differential Revision: https://reviews.llvm.org/D72396
2021-05-29 20:52:26 +08:00
|
|
|
; Negative test
|
|
|
|
|
2019-12-31 03:56:57 +08:00
|
|
|
define i32 @masked_bit_clear_use2(i32 %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @masked_bit_clear_use2(
|
|
|
|
; CHECK-NEXT: [[SH1:%.*]] = shl i32 1, [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: [[AND:%.*]] = and i32 [[SH1]], [[X:%.*]]
|
|
|
|
; CHECK-NEXT: call void @use32(i32 [[AND]])
|
2020-01-01 01:00:07 +08:00
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0
|
2019-12-31 03:56:57 +08:00
|
|
|
; CHECK-NEXT: [[R:%.*]] = zext i1 [[CMP]] to i32
|
|
|
|
; CHECK-NEXT: ret i32 [[R]]
|
|
|
|
;
|
|
|
|
%sh1 = shl i32 1, %y
|
|
|
|
%and = and i32 %sh1, %x
|
|
|
|
call void @use32(i32 %and)
|
2020-01-01 01:00:07 +08:00
|
|
|
%cmp = icmp eq i32 %and, 0
|
2019-12-31 03:56:57 +08:00
|
|
|
%r = zext i1 %cmp to i32
|
|
|
|
ret i32 %r
|
|
|
|
}
|
|
|
|
|
[InstCombine] fold zext of masked bit set/clear
This does not solve PR17101, but it is one of the
underlying diffs noted here:
https://bugs.llvm.org/show_bug.cgi?id=17101#c8
We could ease the one-use checks for the 'clear'
(no 'not' op) half of the transform, but I do not
know if that asymmetry would make things better
or worse.
Proofs:
https://rise4fun.com/Alive/uVB
Name: masked bit set
%sh1 = shl i32 1, %y
%and = and i32 %sh1, %x
%cmp = icmp ne i32 %and, 0
%r = zext i1 %cmp to i32
=>
%s = lshr i32 %x, %y
%r = and i32 %s, 1
Name: masked bit clear
%sh1 = shl i32 1, %y
%and = and i32 %sh1, %x
%cmp = icmp eq i32 %and, 0
%r = zext i1 %cmp to i32
=>
%xn = xor i32 %x, -1
%s = lshr i32 %xn, %y
%r = and i32 %s, 1
Note: this is a re-post of a patch that I committed at:
rGa041c4ec6f7a
The commit was reverted because it exposed another bug:
rGb212eb7159b40
But that has since been corrected with:
rG8a156d1c2795189 ( D101191 )
Differential Revision: https://reviews.llvm.org/D72396
2021-05-29 20:52:26 +08:00
|
|
|
; Negative test
|
|
|
|
|
2019-12-31 03:56:57 +08:00
|
|
|
define i32 @masked_bit_clear_use3(i32 %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @masked_bit_clear_use3(
|
|
|
|
; CHECK-NEXT: [[SH1:%.*]] = shl i32 1, [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: [[AND:%.*]] = and i32 [[SH1]], [[X:%.*]]
|
2020-01-01 01:00:07 +08:00
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0
|
2019-12-31 03:56:57 +08:00
|
|
|
; CHECK-NEXT: call void @use1(i1 [[CMP]])
|
|
|
|
; CHECK-NEXT: [[R:%.*]] = zext i1 [[CMP]] to i32
|
|
|
|
; CHECK-NEXT: ret i32 [[R]]
|
|
|
|
;
|
|
|
|
%sh1 = shl i32 1, %y
|
|
|
|
%and = and i32 %sh1, %x
|
2020-01-01 01:00:07 +08:00
|
|
|
%cmp = icmp eq i32 %and, 0
|
2019-12-31 03:56:57 +08:00
|
|
|
call void @use1(i1 %cmp)
|
|
|
|
%r = zext i1 %cmp to i32
|
|
|
|
ret i32 %r
|
|
|
|
}
|
2020-01-01 01:00:07 +08:00
|
|
|
|
[InstCombine] fold zext of masked bit set/clear
This does not solve PR17101, but it is one of the
underlying diffs noted here:
https://bugs.llvm.org/show_bug.cgi?id=17101#c8
We could ease the one-use checks for the 'clear'
(no 'not' op) half of the transform, but I do not
know if that asymmetry would make things better
or worse.
Proofs:
https://rise4fun.com/Alive/uVB
Name: masked bit set
%sh1 = shl i32 1, %y
%and = and i32 %sh1, %x
%cmp = icmp ne i32 %and, 0
%r = zext i1 %cmp to i32
=>
%s = lshr i32 %x, %y
%r = and i32 %s, 1
Name: masked bit clear
%sh1 = shl i32 1, %y
%and = and i32 %sh1, %x
%cmp = icmp eq i32 %and, 0
%r = zext i1 %cmp to i32
=>
%xn = xor i32 %x, -1
%s = lshr i32 %xn, %y
%r = and i32 %s, 1
Note: this is a re-post of a patch that I committed at:
rGa041c4ec6f7a
The commit was reverted because it exposed another bug:
rGb212eb7159b40
But that has since been corrected with:
rG8a156d1c2795189 ( D101191 )
Differential Revision: https://reviews.llvm.org/D72396
2021-05-29 20:52:26 +08:00
|
|
|
; Negative test
|
|
|
|
|
2020-01-01 01:00:07 +08:00
|
|
|
define i32 @masked_bits_set(i32 %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @masked_bits_set(
|
|
|
|
; CHECK-NEXT: [[SH1:%.*]] = shl i32 3, [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: [[AND:%.*]] = and i32 [[SH1]], [[X:%.*]]
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[AND]], 0
|
|
|
|
; CHECK-NEXT: [[R:%.*]] = zext i1 [[CMP]] to i32
|
|
|
|
; CHECK-NEXT: ret i32 [[R]]
|
|
|
|
;
|
|
|
|
%sh1 = shl i32 3, %y
|
|
|
|
%and = and i32 %sh1, %x
|
|
|
|
%cmp = icmp ne i32 %and, 0
|
|
|
|
%r = zext i1 %cmp to i32
|
|
|
|
ret i32 %r
|
|
|
|
}
|
|
|
|
|
[InstCombine] fold zext of masked bit set/clear
This does not solve PR17101, but it is one of the
underlying diffs noted here:
https://bugs.llvm.org/show_bug.cgi?id=17101#c8
We could ease the one-use checks for the 'clear'
(no 'not' op) half of the transform, but I do not
know if that asymmetry would make things better
or worse.
Proofs:
https://rise4fun.com/Alive/uVB
Name: masked bit set
%sh1 = shl i32 1, %y
%and = and i32 %sh1, %x
%cmp = icmp ne i32 %and, 0
%r = zext i1 %cmp to i32
=>
%s = lshr i32 %x, %y
%r = and i32 %s, 1
Name: masked bit clear
%sh1 = shl i32 1, %y
%and = and i32 %sh1, %x
%cmp = icmp eq i32 %and, 0
%r = zext i1 %cmp to i32
=>
%xn = xor i32 %x, -1
%s = lshr i32 %xn, %y
%r = and i32 %s, 1
Note: this is a re-post of a patch that I committed at:
rGa041c4ec6f7a
The commit was reverted because it exposed another bug:
rGb212eb7159b40
But that has since been corrected with:
rG8a156d1c2795189 ( D101191 )
Differential Revision: https://reviews.llvm.org/D72396
2021-05-29 20:52:26 +08:00
|
|
|
; Negative test
|
|
|
|
|
2020-01-01 01:00:07 +08:00
|
|
|
define i32 @div_bit_set(i32 %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @div_bit_set(
|
|
|
|
; CHECK-NEXT: [[SH1:%.*]] = shl i32 1, [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: [[AND:%.*]] = sdiv i32 [[SH1]], [[X:%.*]]
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[AND]], 0
|
|
|
|
; CHECK-NEXT: [[R:%.*]] = zext i1 [[CMP]] to i32
|
|
|
|
; CHECK-NEXT: ret i32 [[R]]
|
|
|
|
;
|
|
|
|
%sh1 = shl i32 1, %y
|
|
|
|
%and = sdiv i32 %sh1, %x
|
|
|
|
%cmp = icmp ne i32 %and, 0
|
|
|
|
%r = zext i1 %cmp to i32
|
|
|
|
ret i32 %r
|
|
|
|
}
|
|
|
|
|
[InstCombine] fold zext of masked bit set/clear
This does not solve PR17101, but it is one of the
underlying diffs noted here:
https://bugs.llvm.org/show_bug.cgi?id=17101#c8
We could ease the one-use checks for the 'clear'
(no 'not' op) half of the transform, but I do not
know if that asymmetry would make things better
or worse.
Proofs:
https://rise4fun.com/Alive/uVB
Name: masked bit set
%sh1 = shl i32 1, %y
%and = and i32 %sh1, %x
%cmp = icmp ne i32 %and, 0
%r = zext i1 %cmp to i32
=>
%s = lshr i32 %x, %y
%r = and i32 %s, 1
Name: masked bit clear
%sh1 = shl i32 1, %y
%and = and i32 %sh1, %x
%cmp = icmp eq i32 %and, 0
%r = zext i1 %cmp to i32
=>
%xn = xor i32 %x, -1
%s = lshr i32 %xn, %y
%r = and i32 %s, 1
Note: this is a re-post of a patch that I committed at:
rGa041c4ec6f7a
The commit was reverted because it exposed another bug:
rGb212eb7159b40
But that has since been corrected with:
rG8a156d1c2795189 ( D101191 )
Differential Revision: https://reviews.llvm.org/D72396
2021-05-29 20:52:26 +08:00
|
|
|
; Negative test
|
|
|
|
|
2020-01-01 01:00:07 +08:00
|
|
|
define i32 @masked_bit_set_nonzero_cmp(i32 %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @masked_bit_set_nonzero_cmp(
|
|
|
|
; CHECK-NEXT: [[SH1:%.*]] = shl i32 1, [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: [[AND:%.*]] = and i32 [[SH1]], [[X:%.*]]
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[AND]], 1
|
|
|
|
; CHECK-NEXT: [[R:%.*]] = zext i1 [[CMP]] to i32
|
|
|
|
; CHECK-NEXT: ret i32 [[R]]
|
|
|
|
;
|
|
|
|
%sh1 = shl i32 1, %y
|
|
|
|
%and = and i32 %sh1, %x
|
|
|
|
%cmp = icmp ne i32 %and, 1
|
|
|
|
%r = zext i1 %cmp to i32
|
|
|
|
ret i32 %r
|
|
|
|
}
|
|
|
|
|
[InstCombine] fold zext of masked bit set/clear
This does not solve PR17101, but it is one of the
underlying diffs noted here:
https://bugs.llvm.org/show_bug.cgi?id=17101#c8
We could ease the one-use checks for the 'clear'
(no 'not' op) half of the transform, but I do not
know if that asymmetry would make things better
or worse.
Proofs:
https://rise4fun.com/Alive/uVB
Name: masked bit set
%sh1 = shl i32 1, %y
%and = and i32 %sh1, %x
%cmp = icmp ne i32 %and, 0
%r = zext i1 %cmp to i32
=>
%s = lshr i32 %x, %y
%r = and i32 %s, 1
Name: masked bit clear
%sh1 = shl i32 1, %y
%and = and i32 %sh1, %x
%cmp = icmp eq i32 %and, 0
%r = zext i1 %cmp to i32
=>
%xn = xor i32 %x, -1
%s = lshr i32 %xn, %y
%r = and i32 %s, 1
Note: this is a re-post of a patch that I committed at:
rGa041c4ec6f7a
The commit was reverted because it exposed another bug:
rGb212eb7159b40
But that has since been corrected with:
rG8a156d1c2795189 ( D101191 )
Differential Revision: https://reviews.llvm.org/D72396
2021-05-29 20:52:26 +08:00
|
|
|
; Negative test
|
|
|
|
|
2020-01-01 01:00:07 +08:00
|
|
|
define i32 @masked_bit_wrong_pred(i32 %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @masked_bit_wrong_pred(
|
|
|
|
; CHECK-NEXT: [[SH1:%.*]] = shl i32 1, [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: [[AND:%.*]] = and i32 [[SH1]], [[X:%.*]]
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[AND]], 0
|
|
|
|
; CHECK-NEXT: [[R:%.*]] = zext i1 [[CMP]] to i32
|
|
|
|
; CHECK-NEXT: ret i32 [[R]]
|
|
|
|
;
|
|
|
|
%sh1 = shl i32 1, %y
|
|
|
|
%and = and i32 %sh1, %x
|
|
|
|
%cmp = icmp sgt i32 %and, 0
|
|
|
|
%r = zext i1 %cmp to i32
|
|
|
|
ret i32 %r
|
|
|
|
}
|
2021-06-19 09:01:34 +08:00
|
|
|
|
2021-09-08 21:33:30 +08:00
|
|
|
define i32 @zext_or_masked_bit_test(i32 %a, i32 %b, i32 %x) {
|
|
|
|
; CHECK-LABEL: @zext_or_masked_bit_test(
|
[InstCombine] remove a buggy set of zext-icmp transforms
The motivating case is an infinite loop shown with a reduced test from:
https://llvm.org/PR51762
To solve this, I'm proposing we delete the most obviously broken part of this code.
The bug example shows a fundamental problem: we ask computeKnownBits if a transform
will be profitable, alter the code by creating new instructions, then rely on
computeKnownBits to return the same answer to actually eliminate instructions.
But there's no guarantee that the results will be the same between the 1st and 2nd
calls. In the infinite loop example, we get different answers, so we add
instructions that conflict with some other transform, and we're stuck.
There's at least one other problem visible in the test diff for
`@zext_or_masked_bit_test_uses`: the code doesn't check uses properly, so we can
end up with extra instructions created.
Last, it's not clear if this set of transforms actually improves analysis or
codegen. I spot-checked a few targets and don't see a clear win:
https://godbolt.org/z/x87EWovso
If we do see a regression from this change, codegen seems like the right place to
add a cmp -> bit-hack fold.
If this is too big of a step, we could limit the computeKnownBits calls by not
passing a context instruction and/or limiting the recursion. I checked that those
would stop the infinite loop for PR51762, but that won't guarantee that some other
example does not fall into the same loop.
Differential Revision: https://reviews.llvm.org/D109440
2021-09-09 20:45:56 +08:00
|
|
|
; CHECK-NEXT: [[SHL:%.*]] = shl i32 1, [[B:%.*]]
|
|
|
|
; CHECK-NEXT: [[AND:%.*]] = and i32 [[SHL]], [[A:%.*]]
|
|
|
|
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[AND]], 0
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], [[B]]
|
|
|
|
; CHECK-NEXT: [[OR:%.*]] = or i1 [[TOBOOL]], [[CMP]]
|
|
|
|
; CHECK-NEXT: [[Z:%.*]] = zext i1 [[OR]] to i32
|
|
|
|
; CHECK-NEXT: ret i32 [[Z]]
|
2021-06-19 09:01:34 +08:00
|
|
|
;
|
|
|
|
%shl = shl i32 1, %b
|
|
|
|
%and = and i32 %shl, %a
|
|
|
|
%tobool = icmp ne i32 %and, 0
|
2021-09-08 21:33:30 +08:00
|
|
|
%cmp = icmp eq i32 %x, %b
|
2021-06-19 09:01:34 +08:00
|
|
|
%or = or i1 %tobool, %cmp
|
2021-09-08 21:33:30 +08:00
|
|
|
%z = zext i1 %or to i32
|
|
|
|
ret i32 %z
|
2021-06-19 09:01:34 +08:00
|
|
|
}
|
|
|
|
|
2021-09-08 21:40:25 +08:00
|
|
|
define i32 @zext_or_masked_bit_test_uses(i32 %a, i32 %b, i32 %x) {
|
|
|
|
; CHECK-LABEL: @zext_or_masked_bit_test_uses(
|
|
|
|
; CHECK-NEXT: [[SHL:%.*]] = shl i32 1, [[B:%.*]]
|
|
|
|
; CHECK-NEXT: [[AND:%.*]] = and i32 [[SHL]], [[A:%.*]]
|
|
|
|
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[AND]], 0
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], [[B]]
|
|
|
|
; CHECK-NEXT: [[OR:%.*]] = or i1 [[TOBOOL]], [[CMP]]
|
|
|
|
; CHECK-NEXT: call void @use1(i1 [[OR]])
|
[InstCombine] remove a buggy set of zext-icmp transforms
The motivating case is an infinite loop shown with a reduced test from:
https://llvm.org/PR51762
To solve this, I'm proposing we delete the most obviously broken part of this code.
The bug example shows a fundamental problem: we ask computeKnownBits if a transform
will be profitable, alter the code by creating new instructions, then rely on
computeKnownBits to return the same answer to actually eliminate instructions.
But there's no guarantee that the results will be the same between the 1st and 2nd
calls. In the infinite loop example, we get different answers, so we add
instructions that conflict with some other transform, and we're stuck.
There's at least one other problem visible in the test diff for
`@zext_or_masked_bit_test_uses`: the code doesn't check uses properly, so we can
end up with extra instructions created.
Last, it's not clear if this set of transforms actually improves analysis or
codegen. I spot-checked a few targets and don't see a clear win:
https://godbolt.org/z/x87EWovso
If we do see a regression from this change, codegen seems like the right place to
add a cmp -> bit-hack fold.
If this is too big of a step, we could limit the computeKnownBits calls by not
passing a context instruction and/or limiting the recursion. I checked that those
would stop the infinite loop for PR51762, but that won't guarantee that some other
example does not fall into the same loop.
Differential Revision: https://reviews.llvm.org/D109440
2021-09-09 20:45:56 +08:00
|
|
|
; CHECK-NEXT: [[Z:%.*]] = zext i1 [[OR]] to i32
|
|
|
|
; CHECK-NEXT: ret i32 [[Z]]
|
2021-09-08 21:40:25 +08:00
|
|
|
;
|
|
|
|
%shl = shl i32 1, %b
|
|
|
|
%and = and i32 %shl, %a
|
|
|
|
%tobool = icmp ne i32 %and, 0
|
|
|
|
%cmp = icmp eq i32 %x, %b
|
|
|
|
%or = or i1 %tobool, %cmp
|
|
|
|
call void @use1(i1 %or)
|
|
|
|
%z = zext i1 %or to i32
|
|
|
|
ret i32 %z
|
|
|
|
}
|