Index: llvm/lib/Analysis/InstructionSimplify.cpp =================================================================== --- llvm/lib/Analysis/InstructionSimplify.cpp +++ llvm/lib/Analysis/InstructionSimplify.cpp @@ -3968,6 +3968,29 @@ return nullptr; } +/// Try to simplify a select of boolean values where one of the true/false arms +/// of the select is a true/false constant. The more general transform from +/// select to logic op is not valid because 'select' may block poison that a +/// logic op would allow to flow through. +static Value *foldSelectOfBools(Value *Cond, Value *T, Value *F, + const SimplifyQuery &Q) { + Type *Ty = Cond->getType(); + assert(Ty->isIntOrIntVectorTy(1) && "Expected bool condition for select"); + assert(T->getType() == F->getType() && "Mismatched select types"); + if (Ty != T->getType()) + return nullptr; + + // select Cond, T, false --> Cond & T + if (match(F, m_ZeroInt())) + return SimplifyAndInst(Cond, T, Q); + + // select Cond, true, F --> Cond | F + if (match(T, m_One())) + return SimplifyOrInst(Cond, F, Q); + + return nullptr; +} + /// Given operands for a SelectInst, see if we can fold the result. /// If not, this returns null. static Value *SimplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal, @@ -4047,6 +4070,9 @@ if (Value *V = foldSelectWithBinaryOp(Cond, TrueVal, FalseVal)) return V; + if (Value *V = foldSelectOfBools(Cond, TrueVal, FalseVal, Q)) + return V; + Optional Imp = isImpliedByDomCondition(Cond, Q.CxtI, Q.DL); if (Imp) return *Imp ? TrueVal : FalseVal; Index: llvm/test/Transforms/InstSimplify/select.ll =================================================================== --- llvm/test/Transforms/InstSimplify/select.ll +++ llvm/test/Transforms/InstSimplify/select.ll @@ -647,12 +647,12 @@ ret i32* %r } +; X < 92 && X < 11 --> X < 11 + define i1 @and_cmps(i32 %x) { ; CHECK-LABEL: @and_cmps( -; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[X:%.*]], 92 -; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[X]], 11 -; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP1]], i1 [[CMP2]], i1 false -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[X:%.*]], 11 +; CHECK-NEXT: ret i1 [[CMP2]] ; %cmp1 = icmp slt i32 %x, 92 %cmp2 = icmp slt i32 %x, 11 @@ -660,12 +660,12 @@ ret i1 %r } +; Repeat with vector types. + define <2 x i1> @and_cmps_vector(<2 x i32> %x) { ; CHECK-LABEL: @and_cmps_vector( -; CHECK-NEXT: [[CMP1:%.*]] = icmp slt <2 x i32> [[X:%.*]], -; CHECK-NEXT: [[CMP2:%.*]] = icmp slt <2 x i32> [[X]], -; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[CMP1]], <2 x i1> [[CMP2]], <2 x i1> zeroinitializer -; CHECK-NEXT: ret <2 x i1> [[R]] +; CHECK-NEXT: [[CMP2:%.*]] = icmp slt <2 x i32> [[X:%.*]], +; CHECK-NEXT: ret <2 x i1> [[CMP2]] ; %cmp1 = icmp slt <2 x i32> %x, %cmp2 = icmp slt <2 x i32> %x, @@ -673,12 +673,12 @@ ret <2 x i1> %r } +; Is %x a NAN? + define i1 @or_cmps(float %x) { ; CHECK-LABEL: @or_cmps( -; CHECK-NEXT: [[CMP1:%.*]] = fcmp uno float [[X:%.*]], 4.200000e+01 -; CHECK-NEXT: [[CMP2:%.*]] = fcmp uno float [[X]], 5.200000e+01 -; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP2]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[CMP2:%.*]] = fcmp uno float [[X:%.*]], 5.200000e+01 +; CHECK-NEXT: ret i1 [[CMP2]] ; %cmp1 = fcmp uno float %x, 42.0 %cmp2 = fcmp uno float %x, 52.0 @@ -686,17 +686,19 @@ ret i1 %r } +; x | (x & y) --> x + define <2 x i1> @or_logic_vector(<2 x i1> %x, <2 x i1> %y) { ; CHECK-LABEL: @or_logic_vector( -; CHECK-NEXT: [[A:%.*]] = and <2 x i1> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[X]], <2 x i1> , <2 x i1> [[A]] -; CHECK-NEXT: ret <2 x i1> [[R]] +; CHECK-NEXT: ret <2 x i1> [[X:%.*]] ; %a = and <2 x i1> %x, %y %r = select <2 x i1> %x, <2 x i1> , <2 x i1> %a ret <2 x i1> %r } +; TODO: This reduces to 'false'. + define i1 @and_not_cmps(i32 %x) { ; CHECK-LABEL: @and_not_cmps( ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[X:%.*]], 92 @@ -710,6 +712,8 @@ ret i1 %r } +; Negative test (but instcombine can reduce it). + define i1 @or_not_cmps(i32 %x) { ; CHECK-LABEL: @or_not_cmps( ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[X:%.*]], 92 @@ -723,6 +727,8 @@ ret i1 %r } +; TODO: Could look through a cast and fold to %s? + define i8 @and_cmps_wrong_type(i32 %x) { ; CHECK-LABEL: @and_cmps_wrong_type( ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[X:%.*]], 92