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

Roman Lebedev via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 15 09:17:46 PDT 2018


Author: lebedevri
Date: Thu Mar 15 09:17:46 2018
New Revision: 327642

URL: http://llvm.org/viewvc/llvm-project?rev=327642&view=rev
Log:
[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

Modified:
    llvm/trunk/lib/Analysis/InstructionSimplify.cpp
    llvm/trunk/test/Transforms/InstSimplify/cast-unsigned-icmp-cmp-0.ll

Modified: llvm/trunk/lib/Analysis/InstructionSimplify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/InstructionSimplify.cpp?rev=327642&r1=327641&r2=327642&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/InstructionSimplify.cpp (original)
+++ llvm/trunk/lib/Analysis/InstructionSimplify.cpp Thu Mar 15 09:17:46 2018
@@ -2490,6 +2490,18 @@ static Value *simplifyICmpWithConstant(C
                                        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;

Modified: llvm/trunk/test/Transforms/InstSimplify/cast-unsigned-icmp-cmp-0.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/cast-unsigned-icmp-cmp-0.ll?rev=327642&r1=327641&r2=327642&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/cast-unsigned-icmp-cmp-0.ll (original)
+++ llvm/trunk/test/Transforms/InstSimplify/cast-unsigned-icmp-cmp-0.ll Thu Mar 15 09:17:46 2018
@@ -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
 
 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_
 
 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_uitof
 
 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
 
 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
 
 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
 
 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_
 
 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_uitof
 
 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
 
 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
 
 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
 
 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_
 
 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_uitof
 
 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
 
 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>




More information about the llvm-commits mailing list