diff --git a/llvm/lib/Transforms/Scalar/SCCP.cpp b/llvm/lib/Transforms/Scalar/SCCP.cpp --- a/llvm/lib/Transforms/Scalar/SCCP.cpp +++ b/llvm/lib/Transforms/Scalar/SCCP.cpp @@ -872,16 +872,10 @@ LatticeVal TVal = getValueState(I.getTrueValue()); LatticeVal FVal = getValueState(I.getFalseValue()); - // select ?, C, C -> C. - if (isConstant(TVal) && isConstant(FVal) && - getConstant(TVal) == getConstant(FVal)) - return (void)markConstant(&I, getConstant(FVal)); - - if (TVal.isUnknown()) // select ?, undef, X -> X. - return (void)mergeInValue(&I, FVal); - if (FVal.isUnknown()) // select ?, X, undef -> X. - return (void)mergeInValue(&I, TVal); - markOverdefined(&I); + bool Changed = ValueState[&I].mergeIn(TVal, DL); + Changed |= ValueState[&I].mergeIn(FVal, DL); + if (Changed) + pushToWorkListMsg(ValueState[&I], &I); } // Handle Unary Operators. diff --git a/llvm/test/Transforms/SCCP/ip-ranges-select.ll b/llvm/test/Transforms/SCCP/ip-ranges-select.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/SCCP/ip-ranges-select.ll @@ -0,0 +1,73 @@ +; RUN: opt < %s -ipsccp -S | FileCheck %s + +define internal i1 @f1(i32 %x, i32 %y, i1 %cmp) { +; CHECK-LABEL: define internal i1 @f1(i32 %x, i32 %y, i1 %cmp) { +; CHECK-NEXT: %sel.1 = select i1 %cmp, i32 %x, i32 %y +; CHECK-NEXT: %c.2 = icmp sgt i32 %sel.1, 100 +; CHECK-NEXT: %c.3 = icmp eq i32 %sel.1, 50 +; CHECK-NEXT: %res.1 = add i1 false, %c.2 +; CHECK-NEXT: %res.2 = add i1 %res.1, %c.3 +; CHECK-NEXT: %res.3 = add i1 %res.2, false +; CHECK-NEXT: ret i1 %res.3 +; + %sel.1 = select i1 %cmp, i32 %x, i32 %y + %c.1 = icmp sgt i32 %sel.1, 300 + %c.2 = icmp sgt i32 %sel.1, 100 + %c.3 = icmp eq i32 %sel.1, 50 + %c.4 = icmp slt i32 %sel.1, 9 + %res.1 = add i1 %c.1, %c.2 + %res.2 = add i1 %res.1, %c.3 + %res.3 = add i1 %res.2, %c.4 + ret i1 %res.3 +} + +define i1 @caller1(i1 %cmp) { +; CHECK-LABEL: define i1 @caller1(i1 %cmp) { +; CHECK-NEXT: %call.1 = tail call i1 @f1(i32 10, i32 100, i1 %cmp) +; CHECK-NEXT: %call.2 = tail call i1 @f1(i32 20, i32 200, i1 %cmp) +; CHECK-NEXT: %res = and i1 %call.1, %call.2 +; CHECK-NEXT: ret i1 %res +; + %call.1 = tail call i1 @f1(i32 10, i32 100, i1 %cmp) + %call.2 = tail call i1 @f1(i32 20, i32 200, i1 %cmp) + %res = and i1 %call.1, %call.2 + ret i1 %res +} + + +define i1 @f2(i32 %x, i32 %y, i1 %cmp) { +; CHECK-LABEL: define i1 @f2(i32 %x, i32 %y, i1 %cmp) { +; CHECK-NEXT: %sel.1 = select i1 %cmp, i32 %x, i32 %y +; CHECK-NEXT: %c.1 = icmp sgt i32 %sel.1, 300 +; CHECK-NEXT: %c.2 = icmp sgt i32 %sel.1, 100 +; CHECK-NEXT: %c.3 = icmp eq i32 %sel.1, 50 +; CHECK-NEXT: %c.4 = icmp slt i32 %sel.1, 9 +; CHECK-NEXT: %res.1 = add i1 %c.1, %c.2 +; CHECK-NEXT: %res.2 = add i1 %res.1, %c.3 +; CHECK-NEXT: %res.3 = add i1 %res.2, %c.4 +; CHECK-NEXT: ret i1 %res.3 +; + %sel.1 = select i1 %cmp, i32 %x, i32 %y + %c.1 = icmp sgt i32 %sel.1, 300 + %c.2 = icmp sgt i32 %sel.1, 100 + %c.3 = icmp eq i32 %sel.1, 50 + %c.4 = icmp slt i32 %sel.1, 9 + %res.1 = add i1 %c.1, %c.2 + %res.2 = add i1 %res.1, %c.3 + %res.3 = add i1 %res.2, %c.4 + ret i1 %res.3 +} + +define i1 @caller2(i32 %y, i1 %cmp) { +; CHECK-LABEL: define i1 @caller2(i32 %y, i1 %cmp) { +; CHECK-NEXT: %call.1 = tail call i1 @f2(i32 10, i32 %y, i1 %cmp) +; CHECK-NEXT: %call.2 = tail call i1 @f2(i32 20, i32 %y, i1 %cmp) +; CHECK-NEXT: %res = and i1 %call.1, %call.2 +; CHECK-NEXT: ret i1 %res +; + %call.1 = tail call i1 @f2(i32 10, i32 %y, i1 %cmp) + %call.2 = tail call i1 @f2(i32 20, i32 %y, i1 %cmp) + %res = and i1 %call.1, %call.2 + ret i1 %res +} + diff --git a/llvm/test/Transforms/SCCP/select.ll b/llvm/test/Transforms/SCCP/select.ll --- a/llvm/test/Transforms/SCCP/select.ll +++ b/llvm/test/Transforms/SCCP/select.ll @@ -1,12 +1,40 @@ -; RUN: opt < %s -sccp -S | not grep select +; RUN: opt < %s -sccp -S | FileCheck %s define i32 @test1(i1 %C) { +; CHECK-LABEL: define i32 @test1( +; CHECK-NEXT: ret i32 0 +; %X = select i1 %C, i32 0, i32 0 ; [#uses=1] ret i32 %X } define i32 @test2(i1 %C) { +; CHECK-LABEL: define i32 @test2( +; CHECK-NEXT: ret i32 0 +; %X = select i1 %C, i32 0, i32 undef ; [#uses=1] ret i32 %X } +define i1 @f2(i32 %x, i1 %cmp) { +; CHECK-LABEL: define i1 @f2(i32 %x, i1 %cmp) { +; CHECK-NEXT: %sel.1 = select i1 %cmp, i32 %x, i32 10 +; CHECK-NEXT: %c.1 = icmp sgt i32 %sel.1, 300 +; CHECK-NEXT: %c.2 = icmp sgt i32 %sel.1, 100 +; CHECK-NEXT: %c.3 = icmp eq i32 %sel.1, 50 +; CHECK-NEXT: %c.4 = icmp slt i32 %sel.1, 9 +; CHECK-NEXT: %res.1 = add i1 %c.1, %c.2 +; CHECK-NEXT: %res.2 = add i1 %res.1, %c.3 +; CHECK-NEXT: %res.3 = add i1 %res.2, %c.4 +; CHECK-NEXT: ret i1 %res.3 +; + %sel.1 = select i1 %cmp, i32 %x, i32 10 + %c.1 = icmp sgt i32 %sel.1, 300 + %c.2 = icmp sgt i32 %sel.1, 100 + %c.3 = icmp eq i32 %sel.1, 50 + %c.4 = icmp slt i32 %sel.1, 9 + %res.1 = add i1 %c.1, %c.2 + %res.2 = add i1 %res.1, %c.3 + %res.3 = add i1 %res.2, %c.4 + ret i1 %res.3 +}