[llvm] 2f525cf - [NFC][InstCombine] Add baseline tests for canonicalizing "and, add", "or, add", "xor, add"

Eric Gullufsen via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 26 10:57:19 PDT 2022


Author: Eric Gullufsen
Date: 2022-08-26T13:57:11-04:00
New Revision: 2f525cfb76974b7c23aeda1199dfe9d78b012d2c

URL: https://github.com/llvm/llvm-project/commit/2f525cfb76974b7c23aeda1199dfe9d78b012d2c
DIFF: https://github.com/llvm/llvm-project/commit/2f525cfb76974b7c23aeda1199dfe9d78b012d2c.diff

LOG: [NFC][InstCombine] Add baseline tests for canonicalizing "and, add", "or, add", "xor, add"

Baseline tests for canonicalizing "logic op, add"
```
((x + C1) & C2) --> ((x & C2) + C1)
((x + C1) ^ C2) --> ((x ^ C2) + C1)
((x + C1) | C2) --> ((x | C2) + C1)
```
for suitable constants `C1` and `C2`.

Reviewed By: spatel

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

Added: 
    

Modified: 
    llvm/test/Transforms/InstCombine/and-xor-or.ll

Removed: 
    


################################################################################
diff  --git a/llvm/test/Transforms/InstCombine/and-xor-or.ll b/llvm/test/Transforms/InstCombine/and-xor-or.ll
index edfc62ab2b05..fdff7a2b1690 100644
--- a/llvm/test/Transforms/InstCombine/and-xor-or.ll
+++ b/llvm/test/Transforms/InstCombine/and-xor-or.ll
@@ -2,6 +2,7 @@
 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
 
 declare void @use(i32)
+declare void @use_i8(i8)
 
 ; a & (a ^ b) --> a & ~b
 
@@ -4353,3 +4354,242 @@ define i1 @PR56294(i8 %x) {
   %t7 = icmp ne i32 %t6, 0
   ret i1 %t7
 }
+
+define i32 @canonicalize_logic_first_or0(i32 %x) {
+; CHECK-LABEL: define {{[^@]+}}@canonicalize_logic_first_or0
+; CHECK-SAME: (i32 [[X:%.*]]) {
+; CHECK-NEXT:    [[A:%.*]] = add i32 [[X]], 112
+; CHECK-NEXT:    [[R:%.*]] = or i32 [[A]], 15
+; CHECK-NEXT:    ret i32 [[R]]
+;
+  %a = add i32 %x, 112 ; 01110000
+  %r = or i32 %a, 15   ; 00001111
+  ret i32 %r
+}
+
+define <2 x i32> @canonicalize_logic_first_or_vector0(<2 x i32> %x) {
+; CHECK-LABEL: define {{[^@]+}}@canonicalize_logic_first_or_vector0
+; CHECK-SAME: (<2 x i32> [[X:%.*]]) {
+; CHECK-NEXT:    [[A:%.*]] = add <2 x i32> [[X]], <i32 112, i32 112>
+; CHECK-NEXT:    [[R:%.*]] = or <2 x i32> [[A]], <i32 15, i32 15>
+; CHECK-NEXT:    ret <2 x i32> [[R]]
+;
+  %a = add <2 x i32> <i32 112, i32 112>, %x ; <0x00000070, 0x00000070>
+  %r = or <2 x i32> <i32 15, i32 15>, %a    ; <0x0000000F, 0x0000000F>
+  ret <2 x i32> %r
+}
+
+; elementwise these constants should be ok to canonicalize logic op then math
+define <2 x i32> @canonicalize_logic_first_or_vector1(<2 x i32> %x) {
+; CHECK-LABEL: define {{[^@]+}}@canonicalize_logic_first_or_vector1
+; CHECK-SAME: (<2 x i32> [[X:%.*]]) {
+; CHECK-NEXT:    [[A:%.*]] = add <2 x i32> [[X]], <i32 -8388608, i32 2071986176>
+; CHECK-NEXT:    [[R:%.*]] = or <2 x i32> [[A]], <i32 32783, i32 2063>
+; CHECK-NEXT:    ret <2 x i32> [[R]]
+;
+  %a = add <2 x i32> <i32 -8388608, i32 2071986176>, %x ; <0xFF800000, 0x7B800000>
+  %r = or <2 x i32> <i32 32783, i32 2063>, %a           ; <0x0000800F, 0x0000080F>
+  ret <2 x i32> %r
+}
+
+define <2 x i32> @canonicalize_logic_first_or_vector2(<2 x i32> %x) {
+; CHECK-LABEL: define {{[^@]+}}@canonicalize_logic_first_or_vector2
+; CHECK-SAME: (<2 x i32> [[X:%.*]]) {
+; CHECK-NEXT:    [[A:%.*]] = add <2 x i32> [[X]], <i32 2147483632, i32 2147483640>
+; CHECK-NEXT:    [[R:%.*]] = or <2 x i32> [[A]], <i32 32783, i32 2063>
+; CHECK-NEXT:    ret <2 x i32> [[R]]
+;
+  %a = add <2 x i32> <i32 2147483632, i32 2147483640>, %x ; <0x7FFFFFF0, 0x7FFFFFF8>
+  %r = or <2 x i32> <i32 32783, i32 2063>, %a             ; <0x0000800F, 0x0000080F>
+  ret <2 x i32> %r
+}
+
+define i32 @canonicalize_logic_first_or_mult_use1(i32 %x) {
+; CHECK-LABEL: define {{[^@]+}}@canonicalize_logic_first_or_mult_use1
+; CHECK-SAME: (i32 [[X:%.*]]) {
+; CHECK-NEXT:    [[A:%.*]] = add i32 [[X]], 112
+; CHECK-NEXT:    call void @use(i32 [[A]])
+; CHECK-NEXT:    [[R:%.*]] = or i32 [[A]], 15
+; CHECK-NEXT:    ret i32 [[R]]
+;
+  %a = add i32 %x, 112 ; 01110000
+  call void @use(i32 %a)
+  %r = or i32 %a, 15   ; 00001111
+  ret i32 %r
+}
+
+define i32 @canonicalize_logic_first_or_bad_constraints2(i32 %x) {
+; CHECK-LABEL: define {{[^@]+}}@canonicalize_logic_first_or_bad_constraints2
+; CHECK-SAME: (i32 [[X:%.*]]) {
+; CHECK-NEXT:    [[A:%.*]] = add i32 [[X]], 112
+; CHECK-NEXT:    [[R:%.*]] = or i32 [[A]], 16
+; CHECK-NEXT:    ret i32 [[R]]
+;
+  %a = add i32 %x, 112 ; 01110000
+  %r = or i32 %a, 16   ; 00010000
+  ret i32 %r
+}
+
+define i8 @canonicalize_logic_first_and0(i8 %x) {
+; CHECK-LABEL: define {{[^@]+}}@canonicalize_logic_first_and0
+; CHECK-SAME: (i8 [[X:%.*]]) {
+; CHECK-NEXT:    [[B:%.*]] = add i8 [[X]], 48
+; CHECK-NEXT:    [[R:%.*]] = and i8 [[B]], -10
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %b = add i8 %x, 48    ;  00110000
+  %r = and i8 %b, -10   ;  11110110
+  ret i8 %r
+}
+
+define <2 x i8> @canonicalize_logic_first_and_vector0(<2 x i8> %x) {
+; CHECK-LABEL: define {{[^@]+}}@canonicalize_logic_first_and_vector0
+; CHECK-SAME: (<2 x i8> [[X:%.*]]) {
+; CHECK-NEXT:    [[A:%.*]] = add <2 x i8> [[X]], <i8 48, i8 48>
+; CHECK-NEXT:    [[R:%.*]] = and <2 x i8> [[A]], <i8 -10, i8 -10>
+; CHECK-NEXT:    ret <2 x i8> [[R]]
+;
+  %a = add <2 x i8> <i8 48, i8 48>, %x
+  %r = and <2 x i8> <i8 -10, i8 -10>, %a
+  ret <2 x i8> %r
+}
+
+; element-wise the constants match constraints
+define <2 x i8> @canonicalize_logic_first_and_vector1(<2 x i8> %x) {
+; CHECK-LABEL: define {{[^@]+}}@canonicalize_logic_first_and_vector1
+; CHECK-SAME: (<2 x i8> [[X:%.*]]) {
+; CHECK-NEXT:    [[A:%.*]] = add <2 x i8> [[X]], <i8 48, i8 32>
+; CHECK-NEXT:    [[R:%.*]] = and <2 x i8> [[A]], <i8 -10, i8 -4>
+; CHECK-NEXT:    ret <2 x i8> [[R]]
+;
+  %a = add <2 x i8> <i8 48, i8 32>, %x
+  %r = and <2 x i8> <i8 -10, i8 -4>, %a
+  ret <2 x i8> %r
+}
+
+; elementwise these constants do match constraints needed to canonicalize
+; logic op first then math op
+define <2 x i32> @canonicalize_logic_first_and_vector2(<2 x i32> %x) {
+; CHECK-LABEL: define {{[^@]+}}@canonicalize_logic_first_and_vector2
+; CHECK-SAME: (<2 x i32> [[X:%.*]]) {
+; CHECK-NEXT:    [[A:%.*]] = add <2 x i32> [[X]], <i32 612368384, i32 612368384>
+; CHECK-NEXT:    [[R:%.*]] = and <2 x i32> [[A]], <i32 -65536, i32 -32768>
+; CHECK-NEXT:    ret <2 x i32> [[R]]
+;
+  %a = add <2 x i32> <i32 612368384, i32 612368384>, %x ; <0x24800000, 0x24800000>
+  %r = and <2 x i32> <i32 -65536, i32 -32768>, %a       ; <0xFFFF0000, 0xFFFF8000>
+  ret <2 x i32> %r
+}
+
+define <2 x i32> @canonicalize_logic_first_and_vector3(<2 x i32> %x) {
+; CHECK-LABEL: define {{[^@]+}}@canonicalize_logic_first_and_vector3
+; CHECK-SAME: (<2 x i32> [[X:%.*]]) {
+; CHECK-NEXT:    [[A:%.*]] = add <2 x i32> [[X]], <i32 32768, i32 16384>
+; CHECK-NEXT:    [[R:%.*]] = and <2 x i32> [[A]], <i32 -65536, i32 -32768>
+; CHECK-NEXT:    ret <2 x i32> [[R]]
+;
+  %a = add <2 x i32> <i32 32768, i32 16384>, %x   ; <0x00008000, 0x00004000>
+  %r = and <2 x i32> <i32 -65536, i32 -32768>, %a ; <0xFFFF0000, 0xFFFF8000>
+  ret <2 x i32> %r
+}
+
+define i8 @canonicalize_logic_first_and_mult_use1(i8 %x) {
+; CHECK-LABEL: define {{[^@]+}}@canonicalize_logic_first_and_mult_use1
+; CHECK-SAME: (i8 [[X:%.*]]) {
+; CHECK-NEXT:    [[B:%.*]] = add i8 [[X]], 48
+; CHECK-NEXT:    call void @use_i8(i8 [[B]])
+; CHECK-NEXT:    [[R:%.*]] = and i8 [[B]], -10
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %b = add i8 %x, 48    ;  00110000
+  call void @use_i8(i8 %b)
+  %r = and i8 %b, -10   ;  11110110
+  ret i8 %r
+}
+
+define i8 @canonicalize_logic_first_and_bad_constraints2(i8 %x) {
+; CHECK-LABEL: define {{[^@]+}}@canonicalize_logic_first_and_bad_constraints2
+; CHECK-SAME: (i8 [[X:%.*]]) {
+; CHECK-NEXT:    [[B:%.*]] = add i8 [[X]], 48
+; CHECK-NEXT:    [[R:%.*]] = and i8 [[B]], -26
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %b = add i8 %x, 48    ;  00110000
+  %r = and i8 %b, -26   ;  11100110
+  ret i8 %r
+}
+
+define i8 @canonicalize_logic_first_xor_0(i8 %x) {
+; CHECK-LABEL: define {{[^@]+}}@canonicalize_logic_first_xor_0
+; CHECK-SAME: (i8 [[X:%.*]]) {
+; CHECK-NEXT:    [[A:%.*]] = add i8 [[X]], 96
+; CHECK-NEXT:    [[R:%.*]] = xor i8 [[A]], 31
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %a = add i8 %x, 96  ; 01100000
+  %r = xor i8 %a, 31  ; 00011111
+  ret i8 %r
+}
+
+define <2 x i32> @canonicalize_logic_first_xor_vector0(<2 x i32> %x) {
+; CHECK-LABEL: define {{[^@]+}}@canonicalize_logic_first_xor_vector0
+; CHECK-SAME: (<2 x i32> [[X:%.*]]) {
+; CHECK-NEXT:    [[A:%.*]] = add <2 x i32> [[X]], <i32 -8388608, i32 -8388608>
+; CHECK-NEXT:    [[R:%.*]] = xor <2 x i32> [[A]], <i32 32783, i32 32783>
+; CHECK-NEXT:    ret <2 x i32> [[R]]
+;
+  %a = add <2 x i32> <i32 -8388608, i32 -8388608>, %x ; <0xFF800000, 0xFF800000>
+  %r = xor <2 x i32> <i32 32783, i32 32783>, %a       ; <0x0000800F, 0x0000800F>
+  ret <2 x i32> %r
+}
+
+; elementwise these constants do obey constraints required to canonicalize
+define <2 x i32> @canonicalize_logic_first_xor_vector1(<2 x i32> %x) {
+; CHECK-LABEL: define {{[^@]+}}@canonicalize_logic_first_xor_vector1
+; CHECK-SAME: (<2 x i32> [[X:%.*]]) {
+; CHECK-NEXT:    [[A:%.*]] = add <2 x i32> [[X]], <i32 -8388608, i32 2071986176>
+; CHECK-NEXT:    [[R:%.*]] = xor <2 x i32> [[A]], <i32 32783, i32 2063>
+; CHECK-NEXT:    ret <2 x i32> [[R]]
+;
+  %a = add <2 x i32> <i32 -8388608, i32 2071986176>, %x ; <0xFF800000, 0x7B800000>
+  %r = xor <2 x i32> <i32 32783, i32 2063>, %a          ; <0x0000800F, 0x0000080F>
+  ret <2 x i32> %r
+}
+
+define <2 x i32> @canonicalize_logic_first_xor_vector2(<2 x i32> %x) {
+; CHECK-LABEL: define {{[^@]+}}@canonicalize_logic_first_xor_vector2
+; CHECK-SAME: (<2 x i32> [[X:%.*]]) {
+; CHECK-NEXT:    [[A:%.*]] = add <2 x i32> [[X]], <i32 2147483632, i32 2147483640>
+; CHECK-NEXT:    [[R:%.*]] = xor <2 x i32> [[A]], <i32 32783, i32 2063>
+; CHECK-NEXT:    ret <2 x i32> [[R]]
+;
+  %a = add <2 x i32> <i32 2147483632, i32 2147483640>, %x ; <0x7FFFFFF0, 0x7FFFFFF8>
+  %r = xor <2 x i32> <i32 32783, i32 2063>, %a            ; <0x0000800F, 0x0000080F>
+  ret <2 x i32> %r
+}
+
+define i8 @canonicalize_logic_first_xor_mult_use1(i8 %x) {
+; CHECK-LABEL: define {{[^@]+}}@canonicalize_logic_first_xor_mult_use1
+; CHECK-SAME: (i8 [[X:%.*]]) {
+; CHECK-NEXT:    [[A:%.*]] = add i8 [[X]], 96
+; CHECK-NEXT:    call void @use_i8(i8 [[A]])
+; CHECK-NEXT:    [[R:%.*]] = xor i8 [[A]], 31
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %a = add i8 %x, 96  ; 01100000
+  call void @use_i8(i8 %a)
+  %r = xor i8 %a, 31  ; 00011111
+  ret i8 %r
+}
+
+define i8 @canonicalize_logic_first_xor_bad_constants2(i8 %x) {
+; CHECK-LABEL: define {{[^@]+}}@canonicalize_logic_first_xor_bad_constants2
+; CHECK-SAME: (i8 [[X:%.*]]) {
+; CHECK-NEXT:    [[A:%.*]] = add i8 [[X]], 96
+; CHECK-NEXT:    [[R:%.*]] = xor i8 [[A]], 32
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %a = add i8 %x, 96  ; 01100000
+  %r = xor i8 %a, 32  ; 00100000
+  ret i8 %r
+}


        


More information about the llvm-commits mailing list