diff --git a/llvm/test/Transforms/InstCombine/or-xor-xor.ll b/llvm/test/Transforms/InstCombine/or-xor-xor.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/or-xor-xor.ll @@ -0,0 +1,100 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -passes=instcombine -S | FileCheck %s + +declare void @use(i1) + +define i1 @or_xor_xor_normal_variant1(i1 %a, i1 %b) { +; CHECK-LABEL: @or_xor_xor_normal_variant1( +; CHECK-NEXT: [[AND:%.*]] = and i1 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[XOR1:%.*]] = xor i1 [[AND]], [[A]] +; CHECK-NEXT: [[XOR2:%.*]] = xor i1 [[AND]], [[B]] +; CHECK-NEXT: [[OR:%.*]] = or i1 [[XOR1]], [[XOR2]] +; CHECK-NEXT: ret i1 [[OR]] +; + %and = and i1 %a, %b + %xor1 = xor i1 %and, %a + %xor2 = xor i1 %and, %b + %or = or i1 %xor1, %xor2 + ret i1 %or +} + +define i1 @or_xor_xor_normal_variant2(i1 %a, i1 %b) { +; CHECK-LABEL: @or_xor_xor_normal_variant2( +; CHECK-NEXT: [[AND:%.*]] = and i1 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[XOR1:%.*]] = xor i1 [[AND]], [[B]] +; CHECK-NEXT: [[XOR2:%.*]] = xor i1 [[AND]], [[A]] +; CHECK-NEXT: [[OR:%.*]] = or i1 [[XOR1]], [[XOR2]] +; CHECK-NEXT: ret i1 [[OR]] +; + %and = and i1 %a, %b + %xor1 = xor i1 %and, %b + %xor2 = xor i1 %and, %a + %or = or i1 %xor1, %xor2 + ret i1 %or +} + +define <3 x i1> @or_xor_xor_normal_vector(<3 x i1> %a, <3 x i1> %b) { +; CHECK-LABEL: @or_xor_xor_normal_vector( +; CHECK-NEXT: [[AND:%.*]] = and <3 x i1> [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[XOR1:%.*]] = xor <3 x i1> [[AND]], [[B]] +; CHECK-NEXT: [[XOR2:%.*]] = xor <3 x i1> [[AND]], [[A]] +; CHECK-NEXT: [[OR:%.*]] = or <3 x i1> [[XOR1]], [[XOR2]] +; CHECK-NEXT: ret <3 x i1> [[OR]] +; + %and = and <3 x i1> %a, %b + %xor1 = xor <3 x i1> %and, %b + %xor2 = xor <3 x i1> %and, %a + %or = or <3 x i1> %xor1, %xor2 + ret <3 x i1> %or +} + +define i1 @or_xor_xor_normal_multiple_uses_and(i1 %a, i1 %b) { +; CHECK-LABEL: @or_xor_xor_normal_multiple_uses_and( +; CHECK-NEXT: [[AND:%.*]] = and i1 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: call void @use(i1 [[AND]]) +; CHECK-NEXT: [[XOR1:%.*]] = xor i1 [[AND]], [[B]] +; CHECK-NEXT: [[XOR2:%.*]] = xor i1 [[AND]], [[A]] +; CHECK-NEXT: [[OR:%.*]] = or i1 [[XOR1]], [[XOR2]] +; CHECK-NEXT: ret i1 [[OR]] +; + %and = and i1 %a, %b + call void @use(i1 %and) + %xor1 = xor i1 %and, %b + %xor2 = xor i1 %and, %a + %or = or i1 %xor1, %xor2 + ret i1 %or +} + +define i1 @or_xor_xor_negative_multiple_uses_xor1(i1 %a, i1 %b) { +; CHECK-LABEL: @or_xor_xor_negative_multiple_uses_xor1( +; CHECK-NEXT: [[AND:%.*]] = and i1 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[XOR1:%.*]] = xor i1 [[AND]], [[B]] +; CHECK-NEXT: call void @use(i1 [[XOR1]]) +; CHECK-NEXT: [[XOR2:%.*]] = xor i1 [[AND]], [[A]] +; CHECK-NEXT: [[OR:%.*]] = or i1 [[XOR1]], [[XOR2]] +; CHECK-NEXT: ret i1 [[OR]] +; + %and = and i1 %a, %b + %xor1 = xor i1 %and, %b + call void @use(i1 %xor1) + %xor2 = xor i1 %and, %a + %or = or i1 %xor1, %xor2 + ret i1 %or +} + +define i1 @or_xor_xor_negative_multiple_uses_xor2(i1 %a, i1 %b) { +; CHECK-LABEL: @or_xor_xor_negative_multiple_uses_xor2( +; CHECK-NEXT: [[AND:%.*]] = and i1 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[XOR1:%.*]] = xor i1 [[AND]], [[B]] +; CHECK-NEXT: [[XOR2:%.*]] = xor i1 [[AND]], [[A]] +; CHECK-NEXT: call void @use(i1 [[XOR2]]) +; CHECK-NEXT: [[OR:%.*]] = or i1 [[XOR1]], [[XOR2]] +; CHECK-NEXT: ret i1 [[OR]] +; + %and = and i1 %a, %b + %xor1 = xor i1 %and, %b + %xor2 = xor i1 %and, %a + call void @use(i1 %xor2) + %or = or i1 %xor1, %xor2 + ret i1 %or +}