mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-01 05:01:59 +01:00
7ec4b0ea72
In certain situations after inlining and simplification we end up with code that is _almost_ a min/max pattern, but contains constants that have been demand-bit optimised to the wrong values, ending up with code like: %1 = icmp slt i32 %shr, -128 %2 = select i1 %1, i32 128, i32 %shr %.inv = icmp sgt i32 %shr, 127 %spec.select.i = select i1 %.inv, i32 127, i32 %2 %conv7 = trunc i32 %spec.select.i to i8 This should be turned into a min/max pattern, but the -128 in the first select was instead transformed into 128, as only the bottom byte was ever demanded. To fix this, I've put in further canonicalisation for the immediates of selects, preferring to use the same value as the icmp if available. Differential Revision: https://reviews.llvm.org/D71516
71 lines
2.4 KiB
LLVM
71 lines
2.4 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt < %s -instcombine -S | FileCheck %s
|
|
|
|
define i8 @single(i32 %A) {
|
|
; CHECK-LABEL: @single(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i32 [[A:%.*]], -128
|
|
; CHECK-NEXT: [[L2:%.*]] = select i1 [[TMP0]], i32 [[A]], i32 -128
|
|
; CHECK-NEXT: [[CONV7:%.*]] = trunc i32 [[L2]] to i8
|
|
; CHECK-NEXT: ret i8 [[CONV7]]
|
|
;
|
|
entry:
|
|
%l1 = icmp slt i32 %A, -128
|
|
%l2 = select i1 %l1, i32 128, i32 %A
|
|
%conv7 = trunc i32 %l2 to i8
|
|
ret i8 %conv7
|
|
}
|
|
|
|
define i8 @double(i32 %A) {
|
|
; CHECK-LABEL: @double(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i32 [[A:%.*]], -128
|
|
; CHECK-NEXT: [[L2:%.*]] = select i1 [[TMP0]], i32 [[A]], i32 -128
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[L2]], 127
|
|
; CHECK-NEXT: [[SPEC_SELECT_I:%.*]] = select i1 [[TMP1]], i32 [[L2]], i32 127
|
|
; CHECK-NEXT: [[CONV7:%.*]] = trunc i32 [[SPEC_SELECT_I]] to i8
|
|
; CHECK-NEXT: ret i8 [[CONV7]]
|
|
;
|
|
entry:
|
|
%l1 = icmp slt i32 %A, -128
|
|
%l2 = select i1 %l1, i32 128, i32 %A
|
|
%.inv = icmp sgt i32 %A, 127
|
|
%spec.select.i = select i1 %.inv, i32 127, i32 %l2
|
|
%conv7 = trunc i32 %spec.select.i to i8
|
|
ret i8 %conv7
|
|
}
|
|
|
|
define i8 @thisdoesnotloop(i32 %A, i32 %B) {
|
|
; CHECK-LABEL: @thisdoesnotloop(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[L1:%.*]] = icmp slt i32 [[A:%.*]], -128
|
|
; CHECK-NEXT: [[L2:%.*]] = select i1 [[L1]], i32 -128, i32 [[B:%.*]]
|
|
; CHECK-NEXT: [[CONV7:%.*]] = trunc i32 [[L2]] to i8
|
|
; CHECK-NEXT: ret i8 [[CONV7]]
|
|
;
|
|
entry:
|
|
%l1 = icmp slt i32 %A, -128
|
|
%l2 = select i1 %l1, i32 128, i32 %B
|
|
%conv7 = trunc i32 %l2 to i8
|
|
ret i8 %conv7
|
|
}
|
|
|
|
define i8 @original(i32 %A, i32 %B) {
|
|
; CHECK-LABEL: @original(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[A:%.*]], -128
|
|
; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 [[A]], i32 -128
|
|
; CHECK-NEXT: [[TMP3:%.*]] = icmp slt i32 [[TMP2]], 127
|
|
; CHECK-NEXT: [[SPEC_SELECT_I:%.*]] = select i1 [[TMP3]], i32 [[TMP2]], i32 127
|
|
; CHECK-NEXT: [[CONV7:%.*]] = trunc i32 [[SPEC_SELECT_I]] to i8
|
|
; CHECK-NEXT: ret i8 [[CONV7]]
|
|
;
|
|
%cmp4.i = icmp slt i32 127, %A
|
|
%cmp6.i = icmp sle i32 -128, %A
|
|
%retval.0.i = select i1 %cmp4.i, i32 127, i32 -128
|
|
%not.cmp4.i = xor i1 %cmp4.i, true
|
|
%cleanup.dest.slot.0.i = and i1 %cmp6.i, %not.cmp4.i
|
|
%spec.select.i = select i1 %cleanup.dest.slot.0.i, i32 %A, i32 %retval.0.i
|
|
%conv7 = trunc i32 %spec.select.i to i8
|
|
ret i8 %conv7
|
|
}
|