[llvm] r338967 - [NFC][InstCombine] Add tests for sinking 'not' into 'xor' (PR38446)

Roman Lebedev via llvm-commits llvm-commits at lists.llvm.org
Sun Aug 5 03:15:04 PDT 2018


Author: lebedevri
Date: Sun Aug  5 03:15:04 2018
New Revision: 338967

URL: http://llvm.org/viewvc/llvm-project?rev=338967&view=rev
Log:
[NFC][InstCombine] Add tests for sinking 'not' into 'xor' (PR38446)

https://rise4fun.com/Alive/IT3

Comes up in the [most ugliest]  signed int -> signed char  case of
-fsanitize=implicit-conversion (https://reviews.llvm.org/D50250)

Not sure if we want to do it always, or only when it is free to invert.

Added:
    llvm/trunk/test/Transforms/InstCombine/demorgan-sink-not-into-xor.ll

Added: llvm/trunk/test/Transforms/InstCombine/demorgan-sink-not-into-xor.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/demorgan-sink-not-into-xor.ll?rev=338967&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/demorgan-sink-not-into-xor.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/demorgan-sink-not-into-xor.ll Sun Aug  5 03:15:04 2018
@@ -0,0 +1,170 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -instcombine -S | FileCheck %s
+
+; https://bugs.llvm.org/show_bug.cgi?id=38446
+
+; Pattern:
+;   ~(x ^ y)
+; Should be transformed into:
+;   (~x) ^ y
+; or into
+;   x ^ (~y)
+
+; While -reassociate does handle this simple pattern, it does not handle
+; the more complicated motivating pattern.
+
+; ============================================================================ ;
+; Basic positive tests
+; ============================================================================ ;
+
+; Just fold it into the first operand.
+define i32 @positive(i32 %x, i32 %y) {
+; CHECK-LABEL: @positive(
+; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = xor i32 [[TMP1]], -1
+; CHECK-NEXT:    ret i32 [[TMP2]]
+;
+  %tmp1 = xor i32 %x, %y
+  %tmp2 = xor i32 %tmp1, -1
+  ret i32 %tmp2
+}
+
+declare i32 @gen32()
+
+; If the [second] operand is easily-invertible, fold into it.
+declare i1 @gen1()
+
+define i1 @positive_easyinvert(i8 %y) {
+; CHECK-LABEL: @positive_easyinvert(
+; CHECK-NEXT:    [[TMP1:%.*]] = call i1 @gen1()
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp slt i8 [[Y:%.*]], 0
+; CHECK-NEXT:    [[TMP3:%.*]] = xor i1 [[TMP1]], [[TMP2]]
+; CHECK-NEXT:    [[TMP4:%.*]] = xor i1 [[TMP3]], true
+; CHECK-NEXT:    ret i1 [[TMP4]]
+;
+  %tmp1 = call i1 @gen1()
+  %tmp2 = icmp slt i8 %y, 0
+  %tmp3 = xor i1 %tmp1, %tmp2
+  %tmp4 = xor i1 %tmp3, true
+  ret i1 %tmp4
+}
+
+; ============================================================================ ;
+; Vector tests
+; ============================================================================ ;
+
+define <2 x i32> @positive_vec(<2 x i32> %x, <2 x i32> %y) {
+; CHECK-LABEL: @positive_vec(
+; CHECK-NEXT:    [[TMP1:%.*]] = xor <2 x i32> [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = xor <2 x i32> [[TMP1]], <i32 -1, i32 -1>
+; CHECK-NEXT:    ret <2 x i32> [[TMP2]]
+;
+  %tmp1 = xor <2 x i32> %x, %y
+  %tmp2 = xor <2 x i32> %tmp1, <i32 -1, i32 -1>
+  ret <2 x i32> %tmp2
+}
+
+define <3 x i32> @positive_vec_undef(<3 x i32> %x, <3 x i32> %y) {
+; CHECK-LABEL: @positive_vec_undef(
+; CHECK-NEXT:    [[TMP1:%.*]] = xor <3 x i32> [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = xor <3 x i32> [[TMP1]], <i32 -1, i32 undef, i32 -1>
+; CHECK-NEXT:    ret <3 x i32> [[TMP2]]
+;
+  %tmp1 = xor <3 x i32> %x, %y
+  %tmp2 = xor <3 x i32> %tmp1, <i32 -1, i32 undef, i32 -1>
+  ret <3 x i32> %tmp2
+}
+
+; ============================================================================ ;
+; One-use tests.
+; ============================================================================ ;
+
+declare void @use32(i32)
+
+define i32 @oneuse_0(i32 %x, i32 %y) {
+; CHECK-LABEL: @oneuse_0(
+; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    call void @use32(i32 [[TMP1]])
+; CHECK-NEXT:    [[TMP2:%.*]] = xor i32 [[TMP1]], -1
+; CHECK-NEXT:    ret i32 [[TMP2]]
+;
+  %tmp1 = xor i32 %x, %y
+  call void @use32(i32 %tmp1)
+  %tmp2 = xor i32 %tmp1, -1
+  ret i32 %tmp2
+}
+
+; ============================================================================ ;
+; One-use tests with easily-invertible operand.
+; ============================================================================ ;
+
+declare void @use1(i1)
+
+define i1 @oneuse_easyinvert_0(i8 %y) {
+; CHECK-LABEL: @oneuse_easyinvert_0(
+; CHECK-NEXT:    [[TMP1:%.*]] = call i1 @gen1()
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp slt i8 [[Y:%.*]], 0
+; CHECK-NEXT:    call void @use1(i1 [[TMP2]])
+; CHECK-NEXT:    [[TMP3:%.*]] = xor i1 [[TMP1]], [[TMP2]]
+; CHECK-NEXT:    [[TMP4:%.*]] = xor i1 [[TMP3]], true
+; CHECK-NEXT:    ret i1 [[TMP4]]
+;
+  %tmp1 = call i1 @gen1()
+  %tmp2 = icmp slt i8 %y, 0
+  call void @use1(i1 %tmp2)
+  %tmp3 = xor i1 %tmp1, %tmp2
+  %tmp4 = xor i1 %tmp3, true
+  ret i1 %tmp4
+}
+
+define i1 @oneuse_easyinvert_1(i8 %y) {
+; CHECK-LABEL: @oneuse_easyinvert_1(
+; CHECK-NEXT:    [[TMP1:%.*]] = call i1 @gen1()
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp slt i8 [[Y:%.*]], 0
+; CHECK-NEXT:    [[TMP3:%.*]] = xor i1 [[TMP1]], [[TMP2]]
+; CHECK-NEXT:    call void @use1(i1 [[TMP3]])
+; CHECK-NEXT:    [[TMP4:%.*]] = xor i1 [[TMP3]], true
+; CHECK-NEXT:    ret i1 [[TMP4]]
+;
+  %tmp1 = call i1 @gen1()
+  %tmp2 = icmp slt i8 %y, 0
+  %tmp3 = xor i1 %tmp1, %tmp2
+  call void @use1(i1 %tmp3)
+  %tmp4 = xor i1 %tmp3, true
+  ret i1 %tmp4
+}
+
+define i1 @oneuse_easyinvert_2(i8 %y) {
+; CHECK-LABEL: @oneuse_easyinvert_2(
+; CHECK-NEXT:    [[TMP1:%.*]] = call i1 @gen1()
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp slt i8 [[Y:%.*]], 0
+; CHECK-NEXT:    call void @use1(i1 [[TMP2]])
+; CHECK-NEXT:    [[TMP3:%.*]] = xor i1 [[TMP1]], [[TMP2]]
+; CHECK-NEXT:    call void @use1(i1 [[TMP3]])
+; CHECK-NEXT:    [[TMP4:%.*]] = xor i1 [[TMP3]], true
+; CHECK-NEXT:    ret i1 [[TMP4]]
+;
+  %tmp1 = call i1 @gen1()
+  %tmp2 = icmp slt i8 %y, 0
+  call void @use1(i1 %tmp2)
+  %tmp3 = xor i1 %tmp1, %tmp2
+  call void @use1(i1 %tmp3)
+  %tmp4 = xor i1 %tmp3, true
+  ret i1 %tmp4
+}
+
+; ============================================================================ ;
+; Negative tests
+; ============================================================================ ;
+
+; It has to be 'not'.
+define i32 @negative(i32 %x, i32 %y) {
+; CHECK-LABEL: @negative(
+; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = xor i32 [[TMP1]], 1
+; CHECK-NEXT:    ret i32 [[TMP2]]
+;
+  %tmp1 = xor i32 %x, %y
+  %tmp2 = xor i32 %tmp1, 1 ; not -1
+  ret i32 %tmp2
+}




More information about the llvm-commits mailing list