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,152 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -passes=instcombine -S | FileCheck %s + +declare void @use.i3(i1) +declare void @use.i5(i5) +declare void @use.i32(i5) + +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 i8 @or_xor_xor_normal_variant2(i8 %a, i8 %b) { +; CHECK-LABEL: @or_xor_xor_normal_variant2( +; CHECK-NEXT: [[AND:%.*]] = and i8 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[XOR1:%.*]] = xor i8 [[AND]], [[B]] +; CHECK-NEXT: [[XOR2:%.*]] = xor i8 [[AND]], [[A]] +; CHECK-NEXT: [[OR:%.*]] = or i8 [[XOR1]], [[XOR2]] +; CHECK-NEXT: ret i8 [[OR]] +; + %and = and i8 %a, %b + %xor1 = xor i8 %and, %b + %xor2 = xor i8 %a, %and + %or = or i8 %xor1, %xor2 + ret i8 %or +} + +define i16 @or_xor_xor_normal_variant3(i16 %a, i16 %b) { +; CHECK-LABEL: @or_xor_xor_normal_variant3( +; CHECK-NEXT: [[AND:%.*]] = and i16 [[B:%.*]], [[A:%.*]] +; CHECK-NEXT: [[XOR1:%.*]] = xor i16 [[AND]], [[B]] +; CHECK-NEXT: [[XOR2:%.*]] = xor i16 [[AND]], [[A]] +; CHECK-NEXT: [[OR:%.*]] = or i16 [[XOR1]], [[XOR2]] +; CHECK-NEXT: ret i16 [[OR]] +; + %and = and i16 %b, %a + %xor1 = xor i16 %b, %and + %xor2 = xor i16 %a, %and + %or = or i16 %xor1, %xor2 + ret i16 %or +} + +define i64 @or_xor_xor_normal_variant4(i64 %a, i64 %b) { +; CHECK-LABEL: @or_xor_xor_normal_variant4( +; CHECK-NEXT: [[AND:%.*]] = and i64 [[B:%.*]], [[A:%.*]] +; CHECK-NEXT: [[XOR1:%.*]] = xor i64 [[AND]], [[B]] +; CHECK-NEXT: [[XOR2:%.*]] = xor i64 [[AND]], [[A]] +; CHECK-NEXT: [[OR:%.*]] = or i64 [[XOR1]], [[XOR2]] +; CHECK-NEXT: ret i64 [[OR]] +; + %and = and i64 %b, %a + %xor1 = xor i64 %and, %b + %xor2 = xor i64 %and, %a + %or = or i64 %xor1, %xor2 + ret i64 %or +} + +define i32 @or_xor_xor_normal_binops(i32 %aa, i32 %bb, i32 %cc) { +; CHECK-LABEL: @or_xor_xor_normal_binops( +; CHECK-NEXT: [[A:%.*]] = xor i32 [[AA:%.*]], [[CC:%.*]] +; CHECK-NEXT: [[B:%.*]] = xor i32 [[BB:%.*]], [[CC]] +; CHECK-NEXT: [[AND:%.*]] = and i32 [[B]], [[A]] +; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[AND]] +; CHECK-NEXT: [[XOR2:%.*]] = xor i32 [[A]], [[AND]] +; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[XOR2]] +; CHECK-NEXT: ret i32 [[OR]] +; + %a = xor i32 %aa, %cc + %b = xor i32 %bb, %cc + + %and = and i32 %b, %a + %xor1 = xor i32 %b, %and + %xor2 = xor i32 %a, %and + %or = or i32 %xor1, %xor2 + ret i32 %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 i3 @or_xor_xor_normal_multiple_uses_and(i3 %a, i3 %b) { +; CHECK-LABEL: @or_xor_xor_normal_multiple_uses_and( +; CHECK-NEXT: [[AND:%.*]] = and i3 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: call void @use.i3(i3 [[AND]]) +; CHECK-NEXT: [[XOR1:%.*]] = xor i3 [[AND]], [[B]] +; CHECK-NEXT: [[XOR2:%.*]] = xor i3 [[AND]], [[A]] +; CHECK-NEXT: [[OR:%.*]] = or i3 [[XOR1]], [[XOR2]] +; CHECK-NEXT: ret i3 [[OR]] +; + %and = and i3 %a, %b + call void @use.i3(i3 %and) + %xor1 = xor i3 %b, %and + %xor2 = xor i3 %a, %and + %or = or i3 %xor1, %xor2 + ret i3 %or +} + +define i32 @or_xor_xor_negative_multiple_uses_xor1(i32 %a, i32 %b) { +; CHECK-LABEL: @or_xor_xor_negative_multiple_uses_xor1( +; CHECK-NEXT: [[AND:%.*]] = and i32 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[AND]], [[B]] +; CHECK-NEXT: call void @use.i32(i32 [[XOR1]]) +; CHECK-NEXT: [[XOR2:%.*]] = xor i32 [[AND]], [[A]] +; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[XOR2]] +; CHECK-NEXT: ret i32 [[OR]] +; + %and = and i32 %a, %b + %xor1 = xor i32 %and, %b + call void @use.i32(i32 %xor1) + %xor2 = xor i32 %and, %a + %or = or i32 %xor1, %xor2 + ret i32 %or +} + +define i5 @or_xor_xor_negative_multiple_uses_xor2(i5 %a, i5 %b) { +; CHECK-LABEL: @or_xor_xor_negative_multiple_uses_xor2( +; CHECK-NEXT: [[AND:%.*]] = and i5 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[XOR1:%.*]] = xor i5 [[AND]], [[B]] +; CHECK-NEXT: [[XOR2:%.*]] = xor i5 [[AND]], [[A]] +; CHECK-NEXT: call void @use.i5(i5 [[XOR2]]) +; CHECK-NEXT: [[OR:%.*]] = or i5 [[XOR1]], [[XOR2]] +; CHECK-NEXT: ret i5 [[OR]] +; + %and = and i5 %a, %b + %xor1 = xor i5 %and, %b + %xor2 = xor i5 %and, %a + call void @use.i5(i5 %xor2) + %or = or i5 %xor1, %xor2 + ret i5 %or +}