diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -4582,6 +4582,21 @@ return FalseVal; } + if (Pred == ICmpInst::Predicate::ICMP_EQ) { + Value *X; + Value *Y; + // select(X | Y == 0, X or Y, X | Y) -> X | Y + if (match(CondVal, m_ICmp(Pred, m_Specific(FalseVal), m_Zero())) && + match(FalseVal, m_Or(m_Value(X), m_Value(Y))) && + (TrueVal == X || TrueVal == Y)) + return FalseVal; + // select(X & Y == -1, X or Y, X & Y) -> X & Y + if (match(CondVal, m_ICmp(Pred, m_Specific(FalseVal), m_AllOnes())) && + match(FalseVal, m_And(m_Value(X), m_Value(Y))) && + (TrueVal == X || TrueVal == Y)) + return FalseVal; + } + return nullptr; } diff --git a/llvm/test/Transforms/InstSimplify/select_or_and.ll b/llvm/test/Transforms/InstSimplify/select_or_and.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/InstSimplify/select_or_and.ll @@ -0,0 +1,193 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -S -passes=instsimplify < %s | FileCheck %s + +; select(Y | X == 0, X, Y | X) +define i32 @select_or_1(i32 %x, i32 %y) { +; CHECK-LABEL: @select_or_1( +; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: ret i32 [[OR]] +; + %or = or i32 %y, %x + %cmp = icmp eq i32 %or, 0 + %ret = select i1 %cmp, i32 %x, i32 %or + ret i32 %ret +} + +; select(Y | X == 0, Y, Y | X) +define i32 @select_or_2(i32 %x, i32 %y) { +; CHECK-LABEL: @select_or_2( +; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: ret i32 [[OR]] +; + %or = or i32 %y, %x + %cmp = icmp eq i32 %or, 0 + %ret = select i1 %cmp, i32 %y, i32 %or + ret i32 %ret +} + +; select(Y | X != 0, Y | X, X) +define i32 @select_or_3(i32 %x, i32 %y) { +; CHECK-LABEL: @select_or_3( +; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: ret i32 [[OR]] +; + %or = or i32 %y, %x + %cmp = icmp ne i32 %or, 0 + %ret = select i1 %cmp, i32 %or, i32 %x + ret i32 %ret +} + +; select(Y | X != 0, Y | X, Y) +define i32 @select_or_4(i32 %x, i32 %y) { +; CHECK-LABEL: @select_or_4( +; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: ret i32 [[OR]] +; + %or = or i32 %y, %x + %cmp = icmp ne i32 %or, 0 + %ret = select i1 %cmp, i32 %or, i32 %y + ret i32 %ret +} + +; select(Y | X != 0, Y | X, Y) +define <4 x i32> @select_or_vec(<4 x i32> %x, <4 x i32> %y) { +; CHECK-LABEL: @select_or_vec( +; CHECK-NEXT: [[OR:%.*]] = or <4 x i32> [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: ret <4 x i32> [[OR]] +; + %or = or <4 x i32> %y, %x + %cmp = icmp ne <4 x i32> %or, zeroinitializer + %ret = select <4 x i1> %cmp, <4 x i32> %or, <4 x i32> %y + ret <4 x i32> %ret +} + +; select(Y | X == 0, Y | X, Y) +define i32 @select_or_not_1(i32 %x, i32 %y) { +; CHECK-LABEL: @select_or_not_1( +; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[OR]], 0 +; CHECK-NEXT: [[RET:%.*]] = select i1 [[CMP]], i32 [[OR]], i32 [[Y]] +; CHECK-NEXT: ret i32 [[RET]] +; + %or = or i32 %y, %x + %cmp = icmp eq i32 %or, 0 + %ret = select i1 %cmp, i32 %or, i32 %y + ret i32 %ret +} +; select(Y | X != 0, Y, Y | X) +define i32 @select_or_not_2(i32 %x, i32 %y) { +; CHECK-LABEL: @select_or_not_2( +; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[OR]], 0 +; CHECK-NEXT: [[RET:%.*]] = select i1 [[CMP]], i32 [[Y]], i32 [[OR]] +; CHECK-NEXT: ret i32 [[RET]] +; + %or = or i32 %y, %x + %cmp = icmp ne i32 %or, 0 + %ret = select i1 %cmp, i32 %y, i32 %or + ret i32 %ret +} +; select(Y | X != 1, Y, Y | X) +define i32 @select_or_not_3(i32 %x, i32 %y) { +; CHECK-LABEL: @select_or_not_3( +; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[OR]], 1 +; CHECK-NEXT: [[RET:%.*]] = select i1 [[CMP]], i32 [[Y]], i32 [[OR]] +; CHECK-NEXT: ret i32 [[RET]] +; + %or = or i32 %y, %x + %cmp = icmp ne i32 %or, 1 + %ret = select i1 %cmp, i32 %y, i32 %or + ret i32 %ret +} + +; select(Y & X == -1, X, Y & X) +define i32 @select_and_1(i32 %x, i32 %y) { +; CHECK-LABEL: @select_and_1( +; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: ret i32 [[AND]] +; + %and = and i32 %y, %x + %cmp = icmp eq i32 %and, -1 + %ret = select i1 %cmp, i32 %x, i32 %and + ret i32 %ret +} + +; select(Y & X == -1, Y, Y & X) +define i32 @select_and_2(i32 %x, i32 %y) { +; CHECK-LABEL: @select_and_2( +; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: ret i32 [[AND]] +; + %and = and i32 %y, %x + %cmp = icmp eq i32 %and, -1 + %ret = select i1 %cmp, i32 %y, i32 %and + ret i32 %ret +} + + +; select(Y & X != -1, Y & X, X) +define i32 @select_and_3(i32 %x, i32 %y) { +; CHECK-LABEL: @select_and_3( +; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: ret i32 [[AND]] +; + %and = and i32 %y, %x + %cmp = icmp ne i32 %and, -1 + %ret = select i1 %cmp, i32 %and, i32 %x + ret i32 %ret +} + +; select(Y & X != -1, Y & X, Y) +define i32 @select_and_4(i32 %x, i32 %y) { +; CHECK-LABEL: @select_and_4( +; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: ret i32 [[AND]] +; + %and = and i32 %y, %x + %cmp = icmp ne i32 %and, -1 + %ret = select i1 %cmp, i32 %and, i32 %y + ret i32 %ret +} + +; select(Y & X != -1, Y, Y & X) +define i32 @select_and_not_1(i32 %x, i32 %y) { +; CHECK-LABEL: @select_and_not_1( +; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], -1 +; CHECK-NEXT: [[RET:%.*]] = select i1 [[CMP]], i32 [[AND]], i32 [[Y]] +; CHECK-NEXT: ret i32 [[RET]] +; + %and = and i32 %y, %x + %cmp = icmp eq i32 %and, -1 + %ret = select i1 %cmp, i32 %and, i32 %y + ret i32 %ret +} + +; select(Y & X != -1, Y, Y & X) +define i32 @select_and_not_2(i32 %x, i32 %y) { +; CHECK-LABEL: @select_and_not_2( +; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[AND]], -1 +; CHECK-NEXT: [[RET:%.*]] = select i1 [[CMP]], i32 [[Y]], i32 [[AND]] +; CHECK-NEXT: ret i32 [[RET]] +; + %and = and i32 %y, %x + %cmp = icmp ne i32 %and, -1 + %ret = select i1 %cmp, i32 %y, i32 %and + ret i32 %ret +} + +; select(Y & X != 123, Y, Y & X) +define i32 @select_and_not_3(i32 %x, i32 %y) { +; CHECK-LABEL: @select_and_not_3( +; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[AND]], 123 +; CHECK-NEXT: [[RET:%.*]] = select i1 [[CMP]], i32 [[Y]], i32 [[AND]] +; CHECK-NEXT: ret i32 [[RET]] +; + %and = and i32 %y, %x + %cmp = icmp ne i32 %and, 123 + %ret = select i1 %cmp, i32 %y, i32 %and + ret i32 %ret +}