From 0bb8a97b41498860d60a06ad1df2758a36a580ca Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Sun, 5 Dec 2021 09:28:11 -0500 Subject: [PATCH] [InstSimplify] add/adjust tests for 'or' logic fold; NFC The last test shows a miscompile: https://alive2.llvm.org/ce/z/s5xy55 --- llvm/test/Transforms/InstSimplify/or.ll | 263 +++++++++++++++----------------- 1 file changed, 119 insertions(+), 144 deletions(-) diff --git a/llvm/test/Transforms/InstSimplify/or.ll b/llvm/test/Transforms/InstSimplify/or.ll index 34dd831..6591dce 100644 --- a/llvm/test/Transforms/InstSimplify/or.ll +++ b/llvm/test/Transforms/InstSimplify/or.ll @@ -348,150 +348,125 @@ define i32 @poison(i32 %x) { ret i32 %v } -declare void @use(i32) - -define i32 @and_or_not_or(i32 %A, i32 %B) { -; CHECK-LABEL: @and_or_not_or( -; CHECK-NEXT: [[I:%.*]] = xor i32 [[B:%.*]], -1 -; CHECK-NEXT: ret i32 [[I]] -; - %i = xor i32 %B, -1 - %i2 = and i32 %i, %A - %i3 = or i32 %B, %A - %i4 = xor i32 %i3, -1 - %i5 = or i32 %i2, %i4 - ret i32 %i5 -} - -define i32 @and_or_not_or2(i32 %A, i32 %B) { -; CHECK-LABEL: @and_or_not_or2( -; CHECK-NEXT: [[I:%.*]] = xor i32 [[A:%.*]], -1 -; CHECK-NEXT: ret i32 [[I]] -; - %i = xor i32 %A, -1 - %i2 = and i32 %i, %B - %i3 = or i32 %B, %A - %i4 = xor i32 %i3, -1 - %i5 = or i32 %i2, %i4 - ret i32 %i5 -} - -define <4 x i32> @and_or_not_or3_vec(<4 x i32> %A, <4 x i32> %B) { -; CHECK-LABEL: @and_or_not_or3_vec( -; CHECK-NEXT: [[I:%.*]] = xor <4 x i32> [[A:%.*]], -; CHECK-NEXT: ret <4 x i32> [[I]] -; - %i = xor <4 x i32> %A, - %i2 = and <4 x i32> %i, %B - %i3 = or <4 x i32> %B, %A - %i4 = xor <4 x i32> %i3, - %i5 = or <4 x i32> %i2, %i4 - ret <4 x i32> %i5 -} - -define i32 @and_or_not_or4_use(i32 %A, i32 %B) { -; CHECK-LABEL: @and_or_not_or4_use( -; CHECK-NEXT: [[I:%.*]] = xor i32 [[A:%.*]], -1 -; CHECK-NEXT: [[I2:%.*]] = and i32 [[I]], [[B:%.*]] -; CHECK-NEXT: tail call void @use(i32 [[I2]]) -; CHECK-NEXT: ret i32 [[I]] -; - %i = xor i32 %A, -1 - %i2 = and i32 %i, %B - tail call void @use(i32 %i2) - %i3 = or i32 %B, %A - %i4 = xor i32 %i3, -1 - %i5 = or i32 %i2, %i4 - ret i32 %i5 -} - -define i32 @and_or_not_or4_use2(i32 %A, i32 %B) { -; CHECK-LABEL: @and_or_not_or4_use2( -; CHECK-NEXT: [[I:%.*]] = or i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[I2:%.*]] = xor i32 [[I]], -1 -; CHECK-NEXT: tail call void @use(i32 [[I2]]) -; CHECK-NEXT: [[I3:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: ret i32 [[I3]] -; - %i = or i32 %B, %A - %i2 = xor i32 %i, -1 - tail call void @use(i32 %i2) - %i3 = xor i32 %A, -1 - %i4 = and i32 %i3, %B - %i5 = or i32 %i4, %i2 - ret i32 %i5 -} - -define i32 @and_or_not_or4_use3(i32 %A, i32 %B) { -; CHECK-LABEL: @and_or_not_or4_use3( -; CHECK-NEXT: [[I:%.*]] = or i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[I2:%.*]] = xor i32 [[I]], -1 -; CHECK-NEXT: tail call void @use(i32 [[I2]]) -; CHECK-NEXT: [[I3:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[I4:%.*]] = and i32 [[I3]], [[B]] -; CHECK-NEXT: tail call void @use(i32 [[I4]]) -; CHECK-NEXT: ret i32 [[I3]] -; - %i = or i32 %B, %A - %i2 = xor i32 %i, -1 - tail call void @use(i32 %i2) - %i3 = xor i32 %A, -1 - %i4 = and i32 %i3, %B - tail call void @use(i32 %i4) - %i5 = or i32 %i4, %i2 - ret i32 %i5 -} - -define i32 @and_or_not_or5(i32 %A, i32 %B) { -; CHECK-LABEL: @and_or_not_or5( -; CHECK-NEXT: [[I:%.*]] = xor i32 [[A:%.*]], -1 -; CHECK-NEXT: ret i32 [[I]] -; - %i = xor i32 %A, -1 - %i2 = and i32 %B, %i - %i3 = or i32 %B, %A - %i4 = xor i32 %i3, -1 - %i5 = or i32 %i2, %i4 - ret i32 %i5 -} - -define i32 @and_or_not_or6(i32 %A, i32 %B) { -; CHECK-LABEL: @and_or_not_or6( -; CHECK-NEXT: [[I:%.*]] = xor i32 [[A:%.*]], -1 -; CHECK-NEXT: ret i32 [[I]] -; - %i = xor i32 %A, -1 - %i2 = and i32 %i, %B - %i3 = or i32 %B, %A - %i4 = xor i32 %i3, -1 - %i5 = or i32 %i4, %i2 - ret i32 %i5 -} - -define i32 @and_or_not_or7(i32 %A, i32 %B) { -; CHECK-LABEL: @and_or_not_or7( -; CHECK-NEXT: [[I:%.*]] = xor i32 [[A:%.*]], -1 -; CHECK-NEXT: ret i32 [[I]] -; - %i = xor i32 %A, -1 - %i2 = and i32 %B, %i - %i3 = or i32 %B, %A - %i4 = xor i32 %i3, -1 - %i5 = or i32 %i4, %i2 - ret i32 %i5 -} - -define i32 @and_or_not_or8(i32 %A, i32 %B) { -; CHECK-LABEL: @and_or_not_or8( -; CHECK-NEXT: [[I:%.*]] = xor i32 [[B:%.*]], -1 -; CHECK-NEXT: ret i32 [[I]] -; - %i = xor i32 %B, -1 - %i2 = and i32 %A, %i - %i3 = or i32 %B, %A - %i4 = xor i32 %i3, -1 - %i5 = or i32 %i4, %i2 - ret i32 %i5 +; (~A & B) | ~(A | B) --> ~A + +define i4 @and_or_not_or_commute0(i4 %A, i4 %B) { +; CHECK-LABEL: @and_or_not_or_commute0( +; CHECK-NEXT: [[NOTA:%.*]] = xor i4 [[A:%.*]], -1 +; CHECK-NEXT: ret i4 [[NOTA]] +; + %nota = xor i4 %A, -1 + %and = and i4 %nota, %B + %or = or i4 %A, %B + %notab = xor i4 %or, -1 + %r = or i4 %and, %notab + ret i4 %r +} + +define i41 @and_or_not_or_commute1(i41 %A, i41 %B) { +; CHECK-LABEL: @and_or_not_or_commute1( +; CHECK-NEXT: [[NOTA:%.*]] = xor i41 [[A:%.*]], -1 +; CHECK-NEXT: ret i41 [[NOTA]] +; + %nota = xor i41 %A, -1 + %and = and i41 %B, %nota + %or = or i41 %A, %B + %notab = xor i41 %or, -1 + %r = or i41 %and, %notab + ret i41 %r +} + +define i8 @and_or_not_or_commute2(i8 %A, i8 %B) { +; CHECK-LABEL: @and_or_not_or_commute2( +; CHECK-NEXT: [[NOTA:%.*]] = xor i8 [[A:%.*]], -1 +; CHECK-NEXT: ret i8 [[NOTA]] +; + %nota = xor i8 %A, -1 + %and = and i8 %nota, %B + %or = or i8 %B, %A + %notab = xor i8 %or, -1 + %r = or i8 %and, %notab + ret i8 %r +} + +define <2 x i4> @and_or_not_or_commute3(<2 x i4> %A, <2 x i4> %B) { +; CHECK-LABEL: @and_or_not_or_commute3( +; CHECK-NEXT: [[NOTA:%.*]] = xor <2 x i4> [[A:%.*]], +; CHECK-NEXT: ret <2 x i4> [[NOTA]] +; + %nota = xor <2 x i4> %A, + %and = and <2 x i4> %B, %nota + %or = or <2 x i4> %B, %A + %notab = xor <2 x i4> %or, + %r = or <2 x i4> %and, %notab + ret <2 x i4> %r +} + +define i4 @and_or_not_or_commute4(i4 %A, i4 %B) { +; CHECK-LABEL: @and_or_not_or_commute4( +; CHECK-NEXT: [[NOTA:%.*]] = xor i4 [[A:%.*]], -1 +; CHECK-NEXT: ret i4 [[NOTA]] +; + %nota = xor i4 %A, -1 + %and = and i4 %nota, %B + %or = or i4 %A, %B + %notab = xor i4 %or, -1 + %r = or i4 %notab, %and + ret i4 %r +} + +define i41 @and_or_not_or_commute5(i41 %A, i41 %B) { +; CHECK-LABEL: @and_or_not_or_commute5( +; CHECK-NEXT: [[NOTA:%.*]] = xor i41 [[A:%.*]], -1 +; CHECK-NEXT: ret i41 [[NOTA]] +; + %nota = xor i41 %A, -1 + %and = and i41 %B, %nota + %or = or i41 %A, %B + %notab = xor i41 %or, -1 + %r = or i41 %notab, %and + ret i41 %r +} + +define i8 @and_or_not_or_commute6(i8 %A, i8 %B) { +; CHECK-LABEL: @and_or_not_or_commute6( +; CHECK-NEXT: [[NOTA:%.*]] = xor i8 [[A:%.*]], -1 +; CHECK-NEXT: ret i8 [[NOTA]] +; + %nota = xor i8 %A, -1 + %and = and i8 %nota, %B + %or = or i8 %B, %A + %notab = xor i8 %or, -1 + %r = or i8 %notab, %and + ret i8 %r +} + +define <2 x i4> @and_or_not_or_commute7(<2 x i4> %A, <2 x i4> %B) { +; CHECK-LABEL: @and_or_not_or_commute7( +; CHECK-NEXT: [[NOTA:%.*]] = xor <2 x i4> [[A:%.*]], +; CHECK-NEXT: ret <2 x i4> [[NOTA]] +; + %nota = xor <2 x i4> %A, + %and = and <2 x i4> %B, %nota + %or = or <2 x i4> %B, %A + %notab = xor <2 x i4> %or, + %r = or <2 x i4> %notab, %and + ret <2 x i4> %r +} + +; FIXME: It is not safe to propagate an undef element from the 'not' op. + +define <2 x i4> @and_or_not_or_commute7_undef_elt(<2 x i4> %A, <2 x i4> %B) { +; CHECK-LABEL: @and_or_not_or_commute7_undef_elt( +; CHECK-NEXT: [[NOTA:%.*]] = xor <2 x i4> [[A:%.*]], +; CHECK-NEXT: ret <2 x i4> [[NOTA]] +; + %nota = xor <2 x i4> %A, + %and = and <2 x i4> %B, %nota + %or = or <2 x i4> %B, %A + %notab = xor <2 x i4> %or, + %r = or <2 x i4> %notab, %and + ret <2 x i4> %r } ; (A | B) | (A ^ B) --> A | B -- 2.7.4