[llvm] 07c18a0 - [InstSimplify] Fix select bit test miscompile with disjoint

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 30 07:55:52 PST 2023


Author: Nikita Popov
Date: 2023-11-30T16:55:32+01:00
New Revision: 07c18a05e2cb80e87b0c681c147a253565064f3e

URL: https://github.com/llvm/llvm-project/commit/07c18a05e2cb80e87b0c681c147a253565064f3e
DIFF: https://github.com/llvm/llvm-project/commit/07c18a05e2cb80e87b0c681c147a253565064f3e.diff

LOG: [InstSimplify] Fix select bit test miscompile with disjoint

The select condition ensures the disjointness here. The transform
is not valid without dropping the flag, which InstSimplify can't
do.

Added: 
    

Modified: 
    llvm/lib/Analysis/InstructionSimplify.cpp
    llvm/test/Transforms/InstSimplify/select.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index ad608702b859f79..9f3b3f25ec3f154 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -4447,14 +4447,22 @@ static Value *simplifySelectBitTest(Value *TrueVal, Value *FalseVal, Value *X,
     // (X & Y) == 0 ? X | Y : X  --> X | Y
     // (X & Y) != 0 ? X | Y : X  --> X
     if (FalseVal == X && match(TrueVal, m_Or(m_Specific(X), m_APInt(C))) &&
-        *Y == *C)
+        *Y == *C) {
+      // We can't return the or if it has the disjoint flag.
+      if (TrueWhenUnset && cast<PossiblyDisjointInst>(TrueVal)->isDisjoint())
+        return nullptr;
       return TrueWhenUnset ? TrueVal : FalseVal;
+    }
 
     // (X & Y) == 0 ? X : X | Y  --> X
     // (X & Y) != 0 ? X : X | Y  --> X | Y
     if (TrueVal == X && match(FalseVal, m_Or(m_Specific(X), m_APInt(C))) &&
-        *Y == *C)
+        *Y == *C) {
+      // We can't return the or if it has the disjoint flag.
+      if (!TrueWhenUnset && cast<PossiblyDisjointInst>(FalseVal)->isDisjoint())
+        return nullptr;
       return TrueWhenUnset ? TrueVal : FalseVal;
+    }
   }
 
   return nullptr;

diff  --git a/llvm/test/Transforms/InstSimplify/select.ll b/llvm/test/Transforms/InstSimplify/select.ll
index d0bb6c2613ef1b0..16901b888933875 100644
--- a/llvm/test/Transforms/InstSimplify/select.ll
+++ b/llvm/test/Transforms/InstSimplify/select.ll
@@ -174,11 +174,12 @@ define i32 @test4(i32 %X) {
   ret i32 %cond
 }
 
-; FIXME: This is a miscompile.
 define i32 @test4_disjoint(i32 %X) {
 ; CHECK-LABEL: @test4_disjoint(
-; CHECK-NEXT:    [[OR:%.*]] = or disjoint i32 [[X:%.*]], -2147483648
-; CHECK-NEXT:    ret i32 [[OR]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 0
+; CHECK-NEXT:    [[OR:%.*]] = or disjoint i32 [[X]], -2147483648
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[OR]]
+; CHECK-NEXT:    ret i32 [[COND]]
 ;
   %cmp = icmp slt i32 %X, 0
   %or = or disjoint i32 %X, -2147483648
@@ -270,11 +271,12 @@ define i32 @test9(i32 %X) {
   ret i32 %cond
 }
 
-; FIXME: This is a miscompile.
 define i32 @test9_disjoint(i32 %X) {
 ; CHECK-LABEL: @test9_disjoint(
-; CHECK-NEXT:    [[OR:%.*]] = or disjoint i32 [[X:%.*]], -2147483648
-; CHECK-NEXT:    ret i32 [[OR]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[X:%.*]], -1
+; CHECK-NEXT:    [[OR:%.*]] = or disjoint i32 [[X]], -2147483648
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i32 [[OR]], i32 [[X]]
+; CHECK-NEXT:    ret i32 [[COND]]
 ;
   %cmp = icmp sgt i32 %X, -1
   %or = or disjoint i32 %X, -2147483648


        


More information about the llvm-commits mailing list