[llvm] 44cac91 - Fix `FindSingleBitChange` to handle NOT(V) where V is not an Instruction

Noah Goldstein via llvm-commits llvm-commits at lists.llvm.org
Mon Jan 23 03:46:53 PST 2023


Author: Noah Goldstein
Date: 2023-01-23T03:35:56-08:00
New Revision: 44cac911e51a15fcfac7a9888ad0146191a14730

URL: https://github.com/llvm/llvm-project/commit/44cac911e51a15fcfac7a9888ad0146191a14730
DIFF: https://github.com/llvm/llvm-project/commit/44cac911e51a15fcfac7a9888ad0146191a14730.diff

LOG: Fix `FindSingleBitChange` to handle NOT(V) where V is not an Instruction

Was previously buggy to assume that NOT'd Value was always an
instruction. If the NOT'd value is not an Instruction, we should just
return as its either a constant, in which can we will re-run the logic
after constant-folding, or its a type we can't evaluate anyways.

This is a follow up to: `D140939`

Reviewed By: pengfei, RKSimon

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

Added: 
    

Modified: 
    llvm/lib/Target/X86/X86ISelLowering.cpp
    llvm/test/CodeGen/X86/atomic-rm-bit-test-64.ll
    llvm/test/CodeGen/X86/atomic-rm-bit-test.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 3339ac943c1e..70c7a0825b2c 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -31505,7 +31505,11 @@ static std::pair<Value *, BitTestKind> FindSingleBitChange(Value *V) {
         match(I, m_Sub(m_AllOnes(), m_Value(PeekI)))) {
       Not = true;
       I = dyn_cast<Instruction>(PeekI);
-      assert(I != nullptr);
+
+      // If I is constant, it will fold and we can evaluate later. If its an
+      // argument or something of that nature, we can't analyze.
+      if (I == nullptr)
+        return {nullptr, UndefBit};
     }
     // We can only use 1 << X without more sophisticated analysis. C << X where
     // C is a power of 2 but not 1 can result in zero which cannot be translated

diff  --git a/llvm/test/CodeGen/X86/atomic-rm-bit-test-64.ll b/llvm/test/CodeGen/X86/atomic-rm-bit-test-64.ll
index 3dcf8c6c00ef..ad85a090010f 100644
--- a/llvm/test/CodeGen/X86/atomic-rm-bit-test-64.ll
+++ b/llvm/test/CodeGen/X86/atomic-rm-bit-test-64.ll
@@ -1586,3 +1586,23 @@ return:                                           ; preds = %entry, %if.then
   %retval.0 = phi i64 [ %1, %if.then ], [ 123, %entry ]
   ret i64 %retval.0
 }
+
+define i64 @atomic_and_with_not_arg(ptr %v, i64 %c) nounwind {
+; CHECK-LABEL: atomic_and_with_not_arg:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    movq $-1, %rcx
+; CHECK-NEXT:    movq (%rdi), %rax
+; CHECK-NEXT:    .p2align 4, 0x90
+; CHECK-NEXT:  .LBB54_1: # %atomicrmw.start
+; CHECK-NEXT:    # =>This Inner Loop Header: Depth=1
+; CHECK-NEXT:    movq %rax, %rdx
+; CHECK-NEXT:    orq %rcx, %rdx
+; CHECK-NEXT:    lock cmpxchgq %rdx, (%rdi)
+; CHECK-NEXT:    jne .LBB54_1
+; CHECK-NEXT:  # %bb.2: # %atomicrmw.end
+; CHECK-NEXT:    retq
+  entry:
+  %0 = xor i64 0, -1
+  %1 = atomicrmw or ptr %v, i64 %0 monotonic, align 8
+  ret i64 %1
+}

diff  --git a/llvm/test/CodeGen/X86/atomic-rm-bit-test.ll b/llvm/test/CodeGen/X86/atomic-rm-bit-test.ll
index 5a5d207b3373..5594d13a234d 100644
--- a/llvm/test/CodeGen/X86/atomic-rm-bit-test.ll
+++ b/llvm/test/CodeGen/X86/atomic-rm-bit-test.ll
@@ -6873,3 +6873,140 @@ entry:
   %and1 = and i32 %and, %shl
   ret i32 %and1
 }
+
+define i32 @atomic_xor_with_not_arg(ptr %v, i32 %c) nounwind {
+; X86-LABEL: atomic_xor_with_not_arg:
+; X86:       # %bb.0: # %entry
+; X86-NEXT:    pushl %esi
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X86-NEXT:    notl %edx
+; X86-NEXT:    movl (%ecx), %eax
+; X86-NEXT:    .p2align 4, 0x90
+; X86-NEXT:  .LBB123_1: # %atomicrmw.start
+; X86-NEXT:    # =>This Inner Loop Header: Depth=1
+; X86-NEXT:    movl %eax, %esi
+; X86-NEXT:    xorl %edx, %esi
+; X86-NEXT:    lock cmpxchgl %esi, (%ecx)
+; X86-NEXT:    jne .LBB123_1
+; X86-NEXT:  # %bb.2: # %atomicrmw.end
+; X86-NEXT:    popl %esi
+; X86-NEXT:    retl
+;
+; X64-LABEL: atomic_xor_with_not_arg:
+; X64:       # %bb.0: # %entry
+; X64-NEXT:    notl %esi
+; X64-NEXT:    movl (%rdi), %eax
+; X64-NEXT:    .p2align 4, 0x90
+; X64-NEXT:  .LBB123_1: # %atomicrmw.start
+; X64-NEXT:    # =>This Inner Loop Header: Depth=1
+; X64-NEXT:    movl %eax, %ecx
+; X64-NEXT:    xorl %esi, %ecx
+; X64-NEXT:    lock cmpxchgl %ecx, (%rdi)
+; X64-NEXT:    jne .LBB123_1
+; X64-NEXT:  # %bb.2: # %atomicrmw.end
+; X64-NEXT:    retq
+entry:
+  %0 = xor i32 %c, -1
+  %1 = atomicrmw xor ptr %v, i32 %0 monotonic, align 4
+  ret i32 %1
+}
+
+define i16 @atomic_or_with_not_arg(ptr %v, i16 %c) nounwind {
+; X86-LABEL: atomic_or_with_not_arg:
+; X86:       # %bb.0: # %entry
+; X86-NEXT:    pushl %esi
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X86-NEXT:    notl %edx
+; X86-NEXT:    movzwl (%ecx), %eax
+; X86-NEXT:    .p2align 4, 0x90
+; X86-NEXT:  .LBB124_1: # %atomicrmw.start
+; X86-NEXT:    # =>This Inner Loop Header: Depth=1
+; X86-NEXT:    movl %eax, %esi
+; X86-NEXT:    orl %edx, %esi
+; X86-NEXT:    # kill: def $ax killed $ax killed $eax
+; X86-NEXT:    lock cmpxchgw %si, (%ecx)
+; X86-NEXT:    # kill: def $ax killed $ax def $eax
+; X86-NEXT:    jne .LBB124_1
+; X86-NEXT:  # %bb.2: # %atomicrmw.end
+; X86-NEXT:    # kill: def $ax killed $ax killed $eax
+; X86-NEXT:    popl %esi
+; X86-NEXT:    retl
+;
+; X64-LABEL: atomic_or_with_not_arg:
+; X64:       # %bb.0: # %entry
+; X64-NEXT:    notl %esi
+; X64-NEXT:    movzwl (%rdi), %eax
+; X64-NEXT:    .p2align 4, 0x90
+; X64-NEXT:  .LBB124_1: # %atomicrmw.start
+; X64-NEXT:    # =>This Inner Loop Header: Depth=1
+; X64-NEXT:    movl %eax, %ecx
+; X64-NEXT:    orl %esi, %ecx
+; X64-NEXT:    # kill: def $ax killed $ax killed $eax
+; X64-NEXT:    lock cmpxchgw %cx, (%rdi)
+; X64-NEXT:    # kill: def $ax killed $ax def $eax
+; X64-NEXT:    jne .LBB124_1
+; X64-NEXT:  # %bb.2: # %atomicrmw.end
+; X64-NEXT:    # kill: def $ax killed $ax killed $eax
+; X64-NEXT:    retq
+entry:
+  %0 = xor i16 %c, -1
+  %1 = atomicrmw or ptr %v, i16 %0 monotonic, align 2
+  ret i16 %1
+}
+
+define i8 @atomic_and_with_not_arg(ptr %v, i8 %c) nounwind {
+; X86-LABEL: atomic_and_with_not_arg:
+; X86:       # %bb.0: # %entry
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    movzbl {{[0-9]+}}(%esp), %edx
+; X86-NEXT:    notb %dl
+; X86-NEXT:    movzbl (%ecx), %eax
+; X86-NEXT:    .p2align 4, 0x90
+; X86-NEXT:  .LBB125_1: # %atomicrmw.start
+; X86-NEXT:    # =>This Inner Loop Header: Depth=1
+; X86-NEXT:    movb %al, %ah
+; X86-NEXT:    orb %dl, %ah
+; X86-NEXT:    lock cmpxchgb %ah, (%ecx)
+; X86-NEXT:    jne .LBB125_1
+; X86-NEXT:  # %bb.2: # %atomicrmw.end
+; X86-NEXT:    retl
+;
+; X64-LABEL: atomic_and_with_not_arg:
+; X64:       # %bb.0: # %entry
+; X64-NEXT:    notb %sil
+; X64-NEXT:    movzbl (%rdi), %eax
+; X64-NEXT:    .p2align 4, 0x90
+; X64-NEXT:  .LBB125_1: # %atomicrmw.start
+; X64-NEXT:    # =>This Inner Loop Header: Depth=1
+; X64-NEXT:    movl %eax, %ecx
+; X64-NEXT:    orb %sil, %cl
+; X64-NEXT:    lock cmpxchgb %cl, (%rdi)
+; X64-NEXT:    jne .LBB125_1
+; X64-NEXT:  # %bb.2: # %atomicrmw.end
+; X64-NEXT:    retq
+entry:
+  %0 = xor i8 %c, -1
+  %1 = atomicrmw or ptr %v, i8 %0 monotonic, align 1
+  ret i8 %1
+}
+
+define weak_odr void @atomic_and_with_not_const() nounwind {
+; X86-LABEL: atomic_and_with_not_const:
+; X86:       # %bb.0: # %entry
+; X86-NEXT:    retl
+;
+; X64-LABEL: atomic_and_with_not_const:
+; X64:       # %bb.0: # %entry
+; X64-NEXT:    retq
+  entry:
+  br label %if.end19
+cont11:  ; No predecessors!
+  %not = xor i32 0, -1
+  %0 = atomicrmw and ptr null, i32 %not monotonic, align 4
+  %and13 = and i32 %0, 0
+  br label %if.end19
+if.end19:  ; preds = %cont11, %entry
+  ret void
+}


        


More information about the llvm-commits mailing list