1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-24 19:52:54 +01:00

[InstSimplify] peek through unsigned FP casts for sign-bit compares (PR36682)

This pattern came up in PR36682 / D44390
https://bugs.llvm.org/show_bug.cgi?id=36682
https://reviews.llvm.org/D44390
https://godbolt.org/g/oKvT5H

See also D44421, D44424

Reviewers: spatel, majnemer, efriedma, arsenm

Reviewed By: spatel

Subscribers: wdng, llvm-commits

Differential Revision: https://reviews.llvm.org/D44425

llvm-svn: 327642
This commit is contained in:
Roman Lebedev 2018-03-15 16:17:46 +00:00
parent b88e67a623
commit 88fbd9ced7
2 changed files with 30 additions and 63 deletions

View File

@ -2490,6 +2490,18 @@ static Value *simplifyICmpWithConstant(CmpInst::Predicate Pred, Value *LHS,
Value *RHS) {
Type *ITy = GetCompareTy(RHS); // The return type.
Value *X;
// Sign-bit checks can be optimized to true/false after unsigned
// floating-point casts:
// icmp slt (bitcast (uitofp X)), 0 --> false
// icmp sgt (bitcast (uitofp X)), -1 --> true
if (match(LHS, m_BitCast(m_UIToFP(m_Value(X))))) {
if (Pred == ICmpInst::ICMP_SLT && match(RHS, m_Zero()))
return ConstantInt::getFalse(ITy);
if (Pred == ICmpInst::ICMP_SGT && match(RHS, m_AllOnes()))
return ConstantInt::getTrue(ITy);
}
const APInt *C;
if (!match(RHS, m_APInt(C)))
return nullptr;

View File

@ -1,20 +1,17 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -instsimplify -S | FileCheck %s
; target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
; This is related to https://bugs.llvm.org/show_bug.cgi?id=36682
; FIXME: All of these can be simplified to a constant true or false value.
; All of these can be simplified to a constant true or false value.
; * slt i32 %b, 0 -> false
; * sgt i32 %b, -1 -> true
; FIXME: m_Zero does not handle undef elements in vectors.
define i1 @i32_cast_cmp_slt_int_0_uitofp_float(i32 %i) {
; CHECK-LABEL: @i32_cast_cmp_slt_int_0_uitofp_float(
; CHECK-NEXT: [[F:%.*]] = uitofp i32 [[I:%.*]] to float
; CHECK-NEXT: [[B:%.*]] = bitcast float [[F]] to i32
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[B]], 0
; CHECK-NEXT: ret i1 [[CMP]]
; CHECK-NEXT: ret i1 false
;
%f = uitofp i32 %i to float
%b = bitcast float %f to i32
@ -24,10 +21,7 @@ define i1 @i32_cast_cmp_slt_int_0_uitofp_float(i32 %i) {
define <2 x i1> @i32_cast_cmp_slt_int_0_uitofp_float_vec(<2 x i32> %i) {
; CHECK-LABEL: @i32_cast_cmp_slt_int_0_uitofp_float_vec(
; CHECK-NEXT: [[F:%.*]] = uitofp <2 x i32> [[I:%.*]] to <2 x float>
; CHECK-NEXT: [[B:%.*]] = bitcast <2 x float> [[F]] to <2 x i32>
; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i32> [[B]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[CMP]]
; CHECK-NEXT: ret <2 x i1> zeroinitializer
;
%f = uitofp <2 x i32> %i to <2 x float>
%b = bitcast <2 x float> %f to <2 x i32>
@ -50,10 +44,7 @@ define <3 x i1> @i32_cast_cmp_slt_int_0_uitofp_float_vec_undef(<3 x i32> %i) {
define i1 @i32_cast_cmp_sgt_int_m1_uitofp_float(i32 %i) {
; CHECK-LABEL: @i32_cast_cmp_sgt_int_m1_uitofp_float(
; CHECK-NEXT: [[F:%.*]] = uitofp i32 [[I:%.*]] to float
; CHECK-NEXT: [[B:%.*]] = bitcast float [[F]] to i32
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[B]], -1
; CHECK-NEXT: ret i1 [[CMP]]
; CHECK-NEXT: ret i1 true
;
%f = uitofp i32 %i to float
%b = bitcast float %f to i32
@ -63,10 +54,7 @@ define i1 @i32_cast_cmp_sgt_int_m1_uitofp_float(i32 %i) {
define <2 x i1> @i32_cast_cmp_sgt_int_m1_uitofp_float_vec(<2 x i32> %i) {
; CHECK-LABEL: @i32_cast_cmp_sgt_int_m1_uitofp_float_vec(
; CHECK-NEXT: [[F:%.*]] = uitofp <2 x i32> [[I:%.*]] to <2 x float>
; CHECK-NEXT: [[B:%.*]] = bitcast <2 x float> [[F]] to <2 x i32>
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i32> [[B]], <i32 -1, i32 -1>
; CHECK-NEXT: ret <2 x i1> [[CMP]]
; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
;
%f = uitofp <2 x i32> %i to <2 x float>
%b = bitcast <2 x float> %f to <2 x i32>
@ -76,10 +64,7 @@ define <2 x i1> @i32_cast_cmp_sgt_int_m1_uitofp_float_vec(<2 x i32> %i) {
define <3 x i1> @i32_cast_cmp_sgt_int_m1_uitofp_float_vec_undef(<3 x i32> %i) {
; CHECK-LABEL: @i32_cast_cmp_sgt_int_m1_uitofp_float_vec_undef(
; CHECK-NEXT: [[F:%.*]] = uitofp <3 x i32> [[I:%.*]] to <3 x float>
; CHECK-NEXT: [[B:%.*]] = bitcast <3 x float> [[F]] to <3 x i32>
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <3 x i32> [[B]], <i32 -1, i32 undef, i32 -1>
; CHECK-NEXT: ret <3 x i1> [[CMP]]
; CHECK-NEXT: ret <3 x i1> <i1 true, i1 true, i1 true>
;
%f = uitofp <3 x i32> %i to <3 x float>
%b = bitcast <3 x float> %f to <3 x i32>
@ -89,10 +74,7 @@ define <3 x i1> @i32_cast_cmp_sgt_int_m1_uitofp_float_vec_undef(<3 x i32> %i) {
define i1 @i32_cast_cmp_slt_int_0_uitofp_double(i32 %i) {
; CHECK-LABEL: @i32_cast_cmp_slt_int_0_uitofp_double(
; CHECK-NEXT: [[F:%.*]] = uitofp i32 [[I:%.*]] to double
; CHECK-NEXT: [[B:%.*]] = bitcast double [[F]] to i64
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[B]], 0
; CHECK-NEXT: ret i1 [[CMP]]
; CHECK-NEXT: ret i1 false
;
%f = uitofp i32 %i to double
%b = bitcast double %f to i64
@ -102,10 +84,7 @@ define i1 @i32_cast_cmp_slt_int_0_uitofp_double(i32 %i) {
define <2 x i1> @i32_cast_cmp_slt_int_0_uitofp_double_vec(<2 x i32> %i) {
; CHECK-LABEL: @i32_cast_cmp_slt_int_0_uitofp_double_vec(
; CHECK-NEXT: [[F:%.*]] = uitofp <2 x i32> [[I:%.*]] to <2 x double>
; CHECK-NEXT: [[B:%.*]] = bitcast <2 x double> [[F]] to <2 x i64>
; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i64> [[B]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[CMP]]
; CHECK-NEXT: ret <2 x i1> zeroinitializer
;
%f = uitofp <2 x i32> %i to <2 x double>
%b = bitcast <2 x double> %f to <2 x i64>
@ -128,10 +107,7 @@ define <3 x i1> @i32_cast_cmp_slt_int_0_uitofp_double_vec_undef(<3 x i32> %i) {
define i1 @i32_cast_cmp_sgt_int_m1_uitofp_double(i32 %i) {
; CHECK-LABEL: @i32_cast_cmp_sgt_int_m1_uitofp_double(
; CHECK-NEXT: [[F:%.*]] = uitofp i32 [[I:%.*]] to double
; CHECK-NEXT: [[B:%.*]] = bitcast double [[F]] to i64
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[B]], -1
; CHECK-NEXT: ret i1 [[CMP]]
; CHECK-NEXT: ret i1 true
;
%f = uitofp i32 %i to double
%b = bitcast double %f to i64
@ -141,10 +117,7 @@ define i1 @i32_cast_cmp_sgt_int_m1_uitofp_double(i32 %i) {
define <2 x i1> @i32_cast_cmp_sgt_int_m1_uitofp_double_vec(<2 x i32> %i) {
; CHECK-LABEL: @i32_cast_cmp_sgt_int_m1_uitofp_double_vec(
; CHECK-NEXT: [[F:%.*]] = uitofp <2 x i32> [[I:%.*]] to <2 x double>
; CHECK-NEXT: [[B:%.*]] = bitcast <2 x double> [[F]] to <2 x i64>
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i64> [[B]], <i64 -1, i64 -1>
; CHECK-NEXT: ret <2 x i1> [[CMP]]
; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
;
%f = uitofp <2 x i32> %i to <2 x double>
%b = bitcast <2 x double> %f to <2 x i64>
@ -154,10 +127,7 @@ define <2 x i1> @i32_cast_cmp_sgt_int_m1_uitofp_double_vec(<2 x i32> %i) {
define <3 x i1> @i32_cast_cmp_sgt_int_m1_uitofp_double_vec_undef(<3 x i32> %i) {
; CHECK-LABEL: @i32_cast_cmp_sgt_int_m1_uitofp_double_vec_undef(
; CHECK-NEXT: [[F:%.*]] = uitofp <3 x i32> [[I:%.*]] to <3 x double>
; CHECK-NEXT: [[B:%.*]] = bitcast <3 x double> [[F]] to <3 x i64>
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <3 x i64> [[B]], <i64 -1, i64 undef, i64 -1>
; CHECK-NEXT: ret <3 x i1> [[CMP]]
; CHECK-NEXT: ret <3 x i1> <i1 true, i1 true, i1 true>
;
%f = uitofp <3 x i32> %i to <3 x double>
%b = bitcast <3 x double> %f to <3 x i64>
@ -167,10 +137,7 @@ define <3 x i1> @i32_cast_cmp_sgt_int_m1_uitofp_double_vec_undef(<3 x i32> %i) {
define i1 @i32_cast_cmp_slt_int_0_uitofp_half(i32 %i) {
; CHECK-LABEL: @i32_cast_cmp_slt_int_0_uitofp_half(
; CHECK-NEXT: [[F:%.*]] = uitofp i32 [[I:%.*]] to half
; CHECK-NEXT: [[B:%.*]] = bitcast half [[F]] to i16
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i16 [[B]], 0
; CHECK-NEXT: ret i1 [[CMP]]
; CHECK-NEXT: ret i1 false
;
%f = uitofp i32 %i to half
%b = bitcast half %f to i16
@ -180,10 +147,7 @@ define i1 @i32_cast_cmp_slt_int_0_uitofp_half(i32 %i) {
define <2 x i1> @i32_cast_cmp_slt_int_0_uitofp_half_vec(<2 x i32> %i) {
; CHECK-LABEL: @i32_cast_cmp_slt_int_0_uitofp_half_vec(
; CHECK-NEXT: [[F:%.*]] = uitofp <2 x i32> [[I:%.*]] to <2 x half>
; CHECK-NEXT: [[B:%.*]] = bitcast <2 x half> [[F]] to <2 x i16>
; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i16> [[B]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[CMP]]
; CHECK-NEXT: ret <2 x i1> zeroinitializer
;
%f = uitofp <2 x i32> %i to <2 x half>
%b = bitcast <2 x half> %f to <2 x i16>
@ -206,10 +170,7 @@ define <3 x i1> @i32_cast_cmp_slt_int_0_uitofp_half_vec_undef(<3 x i32> %i) {
define i1 @i32_cast_cmp_sgt_int_m1_uitofp_half(i32 %i) {
; CHECK-LABEL: @i32_cast_cmp_sgt_int_m1_uitofp_half(
; CHECK-NEXT: [[F:%.*]] = uitofp i32 [[I:%.*]] to half
; CHECK-NEXT: [[B:%.*]] = bitcast half [[F]] to i16
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i16 [[B]], -1
; CHECK-NEXT: ret i1 [[CMP]]
; CHECK-NEXT: ret i1 true
;
%f = uitofp i32 %i to half
%b = bitcast half %f to i16
@ -219,10 +180,7 @@ define i1 @i32_cast_cmp_sgt_int_m1_uitofp_half(i32 %i) {
define <2 x i1> @i32_cast_cmp_sgt_int_m1_uitofp_half_vec(<2 x i32> %i) {
; CHECK-LABEL: @i32_cast_cmp_sgt_int_m1_uitofp_half_vec(
; CHECK-NEXT: [[F:%.*]] = uitofp <2 x i32> [[I:%.*]] to <2 x half>
; CHECK-NEXT: [[B:%.*]] = bitcast <2 x half> [[F]] to <2 x i16>
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i16> [[B]], <i16 -1, i16 -1>
; CHECK-NEXT: ret <2 x i1> [[CMP]]
; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
;
%f = uitofp <2 x i32> %i to <2 x half>
%b = bitcast <2 x half> %f to <2 x i16>
@ -232,10 +190,7 @@ define <2 x i1> @i32_cast_cmp_sgt_int_m1_uitofp_half_vec(<2 x i32> %i) {
define <3 x i1> @i32_cast_cmp_sgt_int_m1_uitofp_half_vec_undef(<3 x i32> %i) {
; CHECK-LABEL: @i32_cast_cmp_sgt_int_m1_uitofp_half_vec_undef(
; CHECK-NEXT: [[F:%.*]] = uitofp <3 x i32> [[I:%.*]] to <3 x half>
; CHECK-NEXT: [[B:%.*]] = bitcast <3 x half> [[F]] to <3 x i16>
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <3 x i16> [[B]], <i16 -1, i16 undef, i16 -1>
; CHECK-NEXT: ret <3 x i1> [[CMP]]
; CHECK-NEXT: ret <3 x i1> <i1 true, i1 true, i1 true>
;
%f = uitofp <3 x i32> %i to <3 x half>
%b = bitcast <3 x half> %f to <3 x i16>