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,208 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -S -passes=instsimplify,instnamer < %s | FileCheck %s + +; select(Y | X == 0, X, Y | X) +define i32 @select_or_1(i32 %0, i32 %1) { +; CHECK-LABEL: @select_or_1( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[I:%.*]] = or i32 [[ARG1:%.*]], [[ARG:%.*]] +; CHECK-NEXT: ret i32 [[I]] +; + %3 = or i32 %1, %0 + %4 = icmp eq i32 %3, 0 + %5 = select i1 %4, i32 %0, i32 %3 + ret i32 %5 +} + +; select(Y | X == 0, Y, Y | X) +define i32 @select_or_2(i32 %0, i32 %1) { +; CHECK-LABEL: @select_or_2( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[I:%.*]] = or i32 [[ARG1:%.*]], [[ARG:%.*]] +; CHECK-NEXT: ret i32 [[I]] +; + %3 = or i32 %1, %0 + %4 = icmp eq i32 %3, 0 + %5 = select i1 %4, i32 %1, i32 %3 + ret i32 %5 +} + +; select(Y | X != 0, Y | X, X) +define i32 @select_or_3(i32 %0, i32 %1) { +; CHECK-LABEL: @select_or_3( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[I:%.*]] = or i32 [[ARG1:%.*]], [[ARG:%.*]] +; CHECK-NEXT: ret i32 [[I]] +; + %3 = or i32 %1, %0 + %4 = icmp ne i32 %3, 0 + %5 = select i1 %4, i32 %3, i32 %0 + ret i32 %5 +} + +; select(Y | X != 0, Y | X, Y) +define i32 @select_or_4(i32 %0, i32 %1) { +; CHECK-LABEL: @select_or_4( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[I:%.*]] = or i32 [[ARG1:%.*]], [[ARG:%.*]] +; CHECK-NEXT: ret i32 [[I]] +; + %3 = or i32 %1, %0 + %4 = icmp ne i32 %3, 0 + %5 = select i1 %4, i32 %3, i32 %1 + ret i32 %5 +} + +; select(Y | X != 0, Y | X, Y) +define <4 x i32> @select_or_vec(<4 x i32> %0, <4 x i32> %1) { +; CHECK-LABEL: @select_or_vec( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[I:%.*]] = or <4 x i32> [[ARG1:%.*]], [[ARG:%.*]] +; CHECK-NEXT: ret <4 x i32> [[I]] +; + %3 = or <4 x i32> %1, %0 + %4 = icmp ne <4 x i32> %3, zeroinitializer + %5 = select <4 x i1> %4, <4 x i32> %3, <4 x i32> %1 + ret <4 x i32> %5 +} + +; select(Y | X == 0, Y | X, Y) +define i32 @select_or_not_1(i32 %0, i32 %1) { +; CHECK-LABEL: @select_or_not_1( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[I:%.*]] = or i32 [[ARG1:%.*]], [[ARG:%.*]] +; CHECK-NEXT: [[I2:%.*]] = icmp eq i32 [[I]], 0 +; CHECK-NEXT: [[I3:%.*]] = select i1 [[I2]], i32 [[I]], i32 [[ARG1]] +; CHECK-NEXT: ret i32 [[I3]] +; + %3 = or i32 %1, %0 + %4 = icmp eq i32 %3, 0 + %5 = select i1 %4, i32 %3, i32 %1 + ret i32 %5 +} +; select(Y | X != 0, Y, Y | X) +define i32 @select_or_not_2(i32 %0, i32 %1) { +; CHECK-LABEL: @select_or_not_2( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[I:%.*]] = or i32 [[ARG1:%.*]], [[ARG:%.*]] +; CHECK-NEXT: [[I2:%.*]] = icmp ne i32 [[I]], 0 +; CHECK-NEXT: [[I3:%.*]] = select i1 [[I2]], i32 [[ARG1]], i32 [[I]] +; CHECK-NEXT: ret i32 [[I3]] +; + %3 = or i32 %1, %0 + %4 = icmp ne i32 %3, 0 + %5 = select i1 %4, i32 %1, i32 %3 + ret i32 %5 +} +; select(Y | X != 1, Y, Y | X) +define i32 @select_or_not_3(i32 %0, i32 %1) { +; CHECK-LABEL: @select_or_not_3( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[I:%.*]] = or i32 [[ARG1:%.*]], [[ARG:%.*]] +; CHECK-NEXT: [[I2:%.*]] = icmp ne i32 [[I]], 1 +; CHECK-NEXT: [[I3:%.*]] = select i1 [[I2]], i32 [[ARG1]], i32 [[I]] +; CHECK-NEXT: ret i32 [[I3]] +; + %3 = or i32 %1, %0 + %4 = icmp ne i32 %3, 1 + %5 = select i1 %4, i32 %1, i32 %3 + ret i32 %5 +} + +; select(Y & X == -1, X, Y & X) +define i32 @select_and_1(i32 %0, i32 %1) { +; CHECK-LABEL: @select_and_1( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[I:%.*]] = and i32 [[ARG1:%.*]], [[ARG:%.*]] +; CHECK-NEXT: ret i32 [[I]] +; + %3 = and i32 %1, %0 + %4 = icmp eq i32 %3, -1 + %5 = select i1 %4, i32 %0, i32 %3 + ret i32 %5 +} + +; select(Y & X == -1, Y, Y & X) +define i32 @select_and_2(i32 %0, i32 %1) { +; CHECK-LABEL: @select_and_2( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[I:%.*]] = and i32 [[ARG1:%.*]], [[ARG:%.*]] +; CHECK-NEXT: ret i32 [[I]] +; + %3 = and i32 %1, %0 + %4 = icmp eq i32 %3, -1 + %5 = select i1 %4, i32 %1, i32 %3 + ret i32 %5 +} + + +; select(Y & X != -1, Y & X, X) +define i32 @select_and_3(i32 %0, i32 %1) { +; CHECK-LABEL: @select_and_3( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[I:%.*]] = and i32 [[ARG1:%.*]], [[ARG:%.*]] +; CHECK-NEXT: ret i32 [[I]] +; + %3 = and i32 %1, %0 + %4 = icmp ne i32 %3, -1 + %5 = select i1 %4, i32 %3, i32 %0 + ret i32 %5 +} + +; select(Y & X != -1, Y & X, Y) +define i32 @select_and_4(i32 %0, i32 %1) { +; CHECK-LABEL: @select_and_4( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[I:%.*]] = and i32 [[ARG1:%.*]], [[ARG:%.*]] +; CHECK-NEXT: ret i32 [[I]] +; + %3 = and i32 %1, %0 + %4 = icmp ne i32 %3, -1 + %5 = select i1 %4, i32 %3, i32 %1 + ret i32 %5 +} + +; select(Y & X != -1, Y, Y & X) +define i32 @select_and_not_1(i32 %0, i32 %1) { +; CHECK-LABEL: @select_and_not_1( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[I:%.*]] = and i32 [[ARG1:%.*]], [[ARG:%.*]] +; CHECK-NEXT: [[I2:%.*]] = icmp eq i32 [[I]], -1 +; CHECK-NEXT: [[I3:%.*]] = select i1 [[I2]], i32 [[I]], i32 [[ARG1]] +; CHECK-NEXT: ret i32 [[I3]] +; + %3 = and i32 %1, %0 + %4 = icmp eq i32 %3, -1 + %5 = select i1 %4, i32 %3, i32 %1 + ret i32 %5 +} + +; select(Y & X != -1, Y, Y & X) +define i32 @select_and_not_2(i32 %0, i32 %1) { +; CHECK-LABEL: @select_and_not_2( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[I:%.*]] = and i32 [[ARG1:%.*]], [[ARG:%.*]] +; CHECK-NEXT: [[I2:%.*]] = icmp ne i32 [[I]], -1 +; CHECK-NEXT: [[I3:%.*]] = select i1 [[I2]], i32 [[ARG1]], i32 [[I]] +; CHECK-NEXT: ret i32 [[I3]] +; + %3 = and i32 %1, %0 + %4 = icmp ne i32 %3, -1 + %5 = select i1 %4, i32 %1, i32 %3 + ret i32 %5 +} + +; select(Y & X != 123, Y, Y & X) +define i32 @select_and_not_3(i32 %0, i32 %1) { +; CHECK-LABEL: @select_and_not_3( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[I:%.*]] = and i32 [[ARG1:%.*]], [[ARG:%.*]] +; CHECK-NEXT: [[I2:%.*]] = icmp ne i32 [[I]], 123 +; CHECK-NEXT: [[I3:%.*]] = select i1 [[I2]], i32 [[ARG1]], i32 [[I]] +; CHECK-NEXT: ret i32 [[I3]] +; + %3 = and i32 %1, %0 + %4 = icmp ne i32 %3, 123 + %5 = select i1 %4, i32 %1, i32 %3 + ret i32 %5 +}