Index: lib/Analysis/ValueTracking.cpp =================================================================== --- lib/Analysis/ValueTracking.cpp +++ lib/Analysis/ValueTracking.cpp @@ -3966,7 +3966,10 @@ unsigned Depth, AssumptionCache *AC, const Instruction *CxtI, const DominatorTree *DT) { - assert(LHS->getType() == RHS->getType() && "mismatched type"); + // A mismatch occurs when we compare a scalar cmp to a vector cmp, for example. + if (LHS->getType() != RHS->getType()) + return None; + Type *OpTy = LHS->getType(); assert(OpTy->getScalarType()->isIntegerTy(1)); Index: lib/Transforms/InstCombine/InstCombineSelect.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineSelect.cpp +++ lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -1213,5 +1213,23 @@ } } + // See if we can determine the result of this select based on a dominating + // condition. + BasicBlock *Parent = SI.getParent(); + BasicBlock *Dom = Parent->getSinglePredecessor(); + auto *PBI = + Dom ? dyn_cast_or_null(Dom->getTerminator()) : nullptr; + if (PBI && PBI->isConditional() && + PBI->getSuccessor(0) != PBI->getSuccessor(1) && + (PBI->getSuccessor(0) == Parent || PBI->getSuccessor(1) == Parent)) { + bool CondIsFalse = PBI->getSuccessor(1) == Parent; + Optional Implication = isImpliedCondition( + PBI->getCondition(), SI.getCondition(), DL, CondIsFalse); + if (Implication) { + Value *V = *Implication ? TrueVal : FalseVal; + return replaceInstUsesWith(SI, V); + } + } + return nullptr; } Index: test/Transforms/InstCombine/pr21210.ll =================================================================== --- test/Transforms/InstCombine/pr21210.ll +++ test/Transforms/InstCombine/pr21210.ll @@ -21,30 +21,3 @@ ; CHECK: select ; CHECK: icmp eq i32 %cond, 8 } - -; don't replace 'cond' by 'len' in a block ('b1') that dominates all uses -; of the select outside the home block ('bb'), but can be reached from the home -; block on another path ('bb -> b0 -> b1') -define void @test2(i32 %len) { -entry: - %0 = call i32 @bar(i32 %len); - %cmp = icmp ult i32 %len, 4 - br i1 %cmp, label %bb, label %b1 -bb: - %cond = select i1 %cmp, i32 %len, i32 8 - %cmp11 = icmp eq i32 %cond, 8 - br i1 %cmp11, label %b0, label %b1 - -b0: - call void @foo(i32 %len) - br label %b1 - -b1: -; CHECK: phi i32 [ %cond, %bb ], [ undef, %b0 ], [ %0, %entry ] - %1 = phi i32 [ %cond, %bb ], [ undef, %b0 ], [ %0, %entry ] - br label %ret - -ret: - call void @foo(i32 %1) - ret void -} Index: test/Transforms/InstCombine/select-implied.ll =================================================================== --- /dev/null +++ test/Transforms/InstCombine/select-implied.ll @@ -0,0 +1,103 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +; A == B implies A >u B is false. +; CHECK-LABEL: @test1 +; CHECK-NOT: select +; CHECK: call void @foo(i32 10) +define void @test1(i32 %a, i32 %b) { + %cmp1 = icmp eq i32 %a, %b + br i1 %cmp1, label %taken, label %end + +taken: + %cmp2 = icmp ugt i32 %a, %b + %c = select i1 %cmp2, i32 0, i32 10 + call void @foo(i32 %c) + br label %end + +end: + ret void +} + +; If A == B is false then A != B is true. +; CHECK-LABEL: @test2 +; CHECK-NOT: select +; CHECK: call void @foo(i32 20) +define void @test2(i32 %a, i32 %b) { + %cmp1 = icmp eq i32 %a, %b + br i1 %cmp1, label %end, label %taken + +taken: + %cmp2 = icmp ne i32 %a, %b + %c = select i1 %cmp2, i32 20, i32 0 + call void @foo(i32 %c) + br label %end + +end: + ret void +} + +; A >u 10 implies A >u 10 is true. +; CHECK-LABEL: @test3 +; CHECK-NOT: select +; CHECK: call void @foo(i32 30) +define void @test3(i32 %a, i32 %b) { + %cmp1 = icmp ugt i32 %a, 10 + br i1 %cmp1, label %taken, label %end + +taken: + %cmp2 = icmp ugt i32 %a, 10 + %c = select i1 %cmp2, i32 30, i32 0 + call void @foo(i32 %c) + br label %end + +end: + ret void +} + +; CHECK-LABEL: @PR23333 +; CHECK-NOT: select +; CHECK: ret i8 1 +define i8 @PR23333(i8 addrspace(1)* %ptr) { + %cmp = icmp eq i8 addrspace(1)* %ptr, null + br i1 %cmp, label %taken, label %end + +taken: + %cmp2 = icmp ne i8 addrspace(1)* %ptr, null + %res = select i1 %cmp2, i8 2, i8 1 + ret i8 %res + +end: + ret i8 0 +} + +; We know the condition of the select is true based on a dominating condition. +; Therefore, we can replace %cond with %len. +; CHECK-LABEL: @test4 +; CHECK-NOT: select +define void @test4(i32 %len) { +entry: + %0 = call i32 @bar(i32 %len); + %cmp = icmp ult i32 %len, 4 + br i1 %cmp, label %bb, label %b1 +bb: + %cond = select i1 %cmp, i32 %len, i32 8 +; CHECK: %cmp11 = icmp eq i32 %len, 8 + %cmp11 = icmp eq i32 %cond, 8 + br i1 %cmp11, label %b0, label %b1 + +b0: + call void @foo(i32 %len) + br label %b1 + +b1: +; CHECK: phi i32 [ %len, %bb ], [ undef, %b0 ], [ %0, %entry ] + %1 = phi i32 [ %cond, %bb ], [ undef, %b0 ], [ %0, %entry ] + br label %ret + +ret: + call void @foo(i32 %1) + ret void +} + +declare void @foo(i32) +declare i32 @bar(i32)