Nikita Popov b47ff36134
[InstCombine] Drop exact flag instead of increasing demanded bits (#70311)
Demanded bit simplification for lshr/ashr will currently demand the low
bits if the exact flag is set. This is because these bits must be zero
to satisfy the flag.

However, this means that our demanded bits simplification is worse for
lshr/ashr exact than it is for plain lshr/ashr, which is generally not
desirable.

Instead, drop the exact flag if a demanded bits simplification of the
operand succeeds, which may no longer satisfy the exact flag.

This matches what we do for the exact flag on udiv, as well as the
nuw/nsw flags on add/sub/mul.
2023-10-26 13:12:30 +02:00

111 lines
3.3 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
; Make sure instcombine don't fold select into operands. We don't want to emit
; select of two integers unless it's selecting 0 / 1.
define i32 @t1(i32 %c, i32 %x) {
; CHECK-LABEL: @t1(
; CHECK-NEXT: [[T1:%.*]] = icmp eq i32 [[C:%.*]], 0
; CHECK-NEXT: [[T2:%.*]] = lshr i32 [[X:%.*]], 18
; CHECK-NEXT: [[T3:%.*]] = select i1 [[T1]], i32 [[T2]], i32 [[X]]
; CHECK-NEXT: ret i32 [[T3]]
;
%t1 = icmp eq i32 %c, 0
%t2 = lshr i32 %x, 18
%t3 = select i1 %t1, i32 %t2, i32 %x
ret i32 %t3
}
define i32 @t2(i32 %c, i32 %x) {
; CHECK-LABEL: @t2(
; CHECK-NEXT: [[T1:%.*]] = icmp eq i32 [[C:%.*]], 0
; CHECK-NEXT: [[T2:%.*]] = and i32 [[X:%.*]], 18
; CHECK-NEXT: [[T3:%.*]] = select i1 [[T1]], i32 [[T2]], i32 [[X]]
; CHECK-NEXT: ret i32 [[T3]]
;
%t1 = icmp eq i32 %c, 0
%t2 = and i32 %x, 18
%t3 = select i1 %t1, i32 %t2, i32 %x
ret i32 %t3
}
define float @t3(float %x, float %y) {
; CHECK-LABEL: @t3(
; CHECK-NEXT: [[T1:%.*]] = fcmp ogt float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[TMP1:%.*]] = fadd fast float [[X]], 1.000000e+00
; CHECK-NEXT: [[T3:%.*]] = select i1 [[T1]], float [[TMP1]], float 2.000000e+00
; CHECK-NEXT: ret float [[T3]]
;
%t1 = fcmp ogt float %x, %y
%t2 = select i1 %t1, float %x, float 1.0
%t3 = fadd fast float %t2, 1.0
ret float %t3
}
define i8 @ashr_exact_poison_constant_fold(i1 %b, i8 %x) {
; CHECK-LABEL: @ashr_exact_poison_constant_fold(
; CHECK-NEXT: [[TMP1:%.*]] = ashr i8 [[X:%.*]], 3
; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], i8 [[TMP1]], i8 5
; CHECK-NEXT: ret i8 [[R]]
;
%s = select i1 %b, i8 %x, i8 42
%r = ashr exact i8 %s, 3
ret i8 %r
}
define i8 @ashr_exact(i1 %b, i8 %x) {
; CHECK-LABEL: @ashr_exact(
; CHECK-NEXT: [[TMP1:%.*]] = ashr exact i8 [[X:%.*]], 3
; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], i8 [[TMP1]], i8 2
; CHECK-NEXT: ret i8 [[R]]
;
%s = select i1 %b, i8 %x, i8 16
%r = ashr exact i8 %s, 3
ret i8 %r
}
define i8 @shl_nsw_nuw_poison_constant_fold(i1 %b, i8 %x) {
; CHECK-LABEL: @shl_nsw_nuw_poison_constant_fold(
; CHECK-NEXT: [[TMP1:%.*]] = shl nuw nsw i8 16, [[X:%.*]]
; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], i8 -128, i8 [[TMP1]]
; CHECK-NEXT: ret i8 [[R]]
;
%s = select i1 %b, i8 3, i8 %x
%r = shl nsw nuw i8 16, %s
ret i8 %r
}
define i8 @shl_nsw_nuw(i1 %b, i8 %x) {
; CHECK-LABEL: @shl_nsw_nuw(
; CHECK-NEXT: [[TMP1:%.*]] = shl nuw nsw i8 7, [[X:%.*]]
; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], i8 56, i8 [[TMP1]]
; CHECK-NEXT: ret i8 [[R]]
;
%s = select i1 %b, i8 3, i8 %x
%r = shl nsw nuw i8 7, %s
ret i8 %r
}
define i8 @add_nsw_poison_constant_fold(i1 %b, i8 %x) {
; CHECK-LABEL: @add_nsw_poison_constant_fold(
; CHECK-NEXT: [[TMP1:%.*]] = add nsw i8 [[X:%.*]], 64
; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], i8 [[TMP1]], i8 -127
; CHECK-NEXT: ret i8 [[R]]
;
%s = select i1 %b, i8 %x, i8 65
%r = add nsw i8 %s, 64
ret i8 %r
}
define i8 @add_nsw(i1 %b, i8 %x) {
; CHECK-LABEL: @add_nsw(
; CHECK-NEXT: [[TMP1:%.*]] = add nsw i8 [[X:%.*]], 64
; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], i8 [[TMP1]], i8 71
; CHECK-NEXT: ret i8 [[R]]
;
%s = select i1 %b, i8 %x, i8 7
%r = add nsw i8 %s, 64
ret i8 %r
}