diff --git a/llvm/test/Transforms/InstCombine/and-xor-or.ll b/llvm/test/Transforms/InstCombine/and-xor-or.ll --- 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 @@ -4355,3 +4356,117 @@ %t7 = icmp ne i32 %t6, 0 ret i1 %t7 } + +define i32 @canonicalize_logic_first_or_0(i32 %x) { +; CHECK-LABEL: define {{[^@]+}}@canonicalize_logic_first_or_0 +; 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 i32 @canonicalize_logic_first_negative_mult_use_or_1(i32 %x) { +; CHECK-LABEL: define {{[^@]+}}@canonicalize_logic_first_negative_mult_use_or_1 +; 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_negative_or_2(i32 %x) { +; CHECK-LABEL: define {{[^@]+}}@canonicalize_logic_first_negative_or_2 +; 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_and_0(i8 %x) { +; CHECK-LABEL: define {{[^@]+}}@canonicalize_logic_first_and_0 +; 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 i8 @canonicalize_logic_first_negative_mult_use_and_1(i8 %x) { +; CHECK-LABEL: define {{[^@]+}}@canonicalize_logic_first_negative_mult_use_and_1 +; 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_negative_and_2(i8 %x) { +; CHECK-LABEL: define {{[^@]+}}@canonicalize_logic_first_negative_and_2 +; 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 i8 @canonicalize_logic_first_negative_mult_use_xor_1(i8 %x) { +; CHECK-LABEL: define {{[^@]+}}@canonicalize_logic_first_negative_mult_use_xor_1 +; 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_negative_xor_2(i8 %x) { +; CHECK-LABEL: define {{[^@]+}}@canonicalize_logic_first_negative_xor_2 +; 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 +}