Index: llvm/trunk/lib/Analysis/CmpInstAnalysis.cpp =================================================================== --- llvm/trunk/lib/Analysis/CmpInstAnalysis.cpp +++ llvm/trunk/lib/Analysis/CmpInstAnalysis.cpp @@ -81,6 +81,13 @@ Mask = APInt::getSignMask(C->getBitWidth()); Pred = ICmpInst::ICMP_NE; break; + case ICmpInst::ICMP_SLE: + // X <= -1 is equivalent to (X & SignMask) != 0. + if (!C->isAllOnesValue()) + return false; + Mask = APInt::getSignMask(C->getBitWidth()); + Pred = ICmpInst::ICMP_NE; + break; case ICmpInst::ICMP_SGT: // X > -1 is equivalent to (X & SignMask) == 0. if (!C->isAllOnesValue()) @@ -88,6 +95,13 @@ Mask = APInt::getSignMask(C->getBitWidth()); Pred = ICmpInst::ICMP_EQ; break; + case ICmpInst::ICMP_SGE: + // X >= 0 is equivalent to (X & SignMask) == 0. + if (!C->isNullValue()) + return false; + Mask = APInt::getSignMask(C->getBitWidth()); + Pred = ICmpInst::ICMP_EQ; + break; case ICmpInst::ICMP_ULT: // X isPowerOf2()) @@ -95,6 +109,13 @@ Mask = -*C; Pred = ICmpInst::ICMP_EQ; break; + case ICmpInst::ICMP_ULE: + // X <=u 2^n-1 is equivalent to (X & ~(2^n-1)) == 0. + if (!(*C + 1).isPowerOf2()) + return false; + Mask = ~*C; + Pred = ICmpInst::ICMP_EQ; + break; case ICmpInst::ICMP_UGT: // X >u 2^n-1 is equivalent to (X & ~(2^n-1)) != 0. if (!(*C + 1).isPowerOf2()) @@ -102,6 +123,13 @@ Mask = ~*C; Pred = ICmpInst::ICMP_NE; break; + case ICmpInst::ICMP_UGE: + // X >=u 2^n is equivalent to (X & ~(2^n-1)) != 0. + if (!C->isPowerOf2()) + return false; + Mask = -*C; + Pred = ICmpInst::ICMP_NE; + break; } X = LHS; Index: llvm/trunk/test/Transforms/InstSimplify/select.ll =================================================================== --- llvm/trunk/test/Transforms/InstSimplify/select.ll +++ llvm/trunk/test/Transforms/InstSimplify/select.ll @@ -47,13 +47,10 @@ } ; Same as above, but the compare isn't canonical -; TODO: we should be able to simplify this define i32 @test4noncanon(i32 %X) { ; CHECK-LABEL: @test4noncanon( -; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[X:%.*]], -1 -; CHECK-NEXT: [[OR:%.*]] = or i32 [[X]], -2147483648 -; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[OR]] -; CHECK-NEXT: ret i32 [[COND]] +; CHECK-NEXT: [[OR:%.*]] = or i32 [[X:%.*]], -2147483648 +; CHECK-NEXT: ret i32 [[OR]] ; %cmp = icmp sle i32 %X, -1 %or = or i32 %X, -2147483648 @@ -114,13 +111,10 @@ } ; Same as above, but the compare isn't canonical -; TODO: we should be able to simplify this define i32 @test9noncanon(i32 %X) { ; CHECK-LABEL: @test9noncanon( -; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[X:%.*]], 0 -; CHECK-NEXT: [[OR:%.*]] = or i32 [[X]], -2147483648 -; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[OR]], i32 [[X]] -; CHECK-NEXT: ret i32 [[COND]] +; CHECK-NEXT: [[OR:%.*]] = or i32 [[X:%.*]], -2147483648 +; CHECK-NEXT: ret i32 [[OR]] ; %cmp = icmp sge i32 %X, 0 %or = or i32 %X, -2147483648 @@ -172,13 +166,10 @@ } ; Same as above, but the compare isn't canonical -; TODO: we should be able to simplify this define i32 @test12noncanon(i32 %X) { ; CHECK-LABEL: @test12noncanon( -; CHECK-NEXT: [[CMP:%.*]] = icmp ule i32 [[X:%.*]], 3 -; CHECK-NEXT: [[AND:%.*]] = and i32 [[X]], 3 -; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[AND]] -; CHECK-NEXT: ret i32 [[COND]] +; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 3 +; CHECK-NEXT: ret i32 [[AND]] ; %cmp = icmp ule i32 %X, 3 %and = and i32 %X, 3 @@ -198,13 +189,10 @@ } ; Same as above, but the compare isn't canonical -; TODO: we should be able to simplify this define i32 @test13noncanon(i32 %X) { ; CHECK-LABEL: @test13noncanon( -; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[X:%.*]], 4 -; CHECK-NEXT: [[AND:%.*]] = and i32 [[X]], 3 -; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[AND]], i32 [[X]] -; CHECK-NEXT: ret i32 [[COND]] +; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 3 +; CHECK-NEXT: ret i32 [[AND]] ; %cmp = icmp uge i32 %X, 4 %and = and i32 %X, 3