Index: llvm/trunk/lib/Analysis/ValueTracking.cpp =================================================================== --- llvm/trunk/lib/Analysis/ValueTracking.cpp +++ llvm/trunk/lib/Analysis/ValueTracking.cpp @@ -2337,7 +2337,7 @@ case Instruction::Select: Tmp = ComputeNumSignBits(U->getOperand(1), Depth + 1, Q); - if (Tmp == 1) return 1; // Early out. + if (Tmp == 1) break; Tmp2 = ComputeNumSignBits(U->getOperand(2), Depth + 1, Q); return std::min(Tmp, Tmp2); @@ -2345,7 +2345,7 @@ // Add can have at most one carry bit. Thus we know that the output // is, at worst, one more bit than the inputs. Tmp = ComputeNumSignBits(U->getOperand(0), Depth + 1, Q); - if (Tmp == 1) return 1; // Early out. + if (Tmp == 1) break; // Special case decrementing a value (ADD X, -1): if (const auto *CRHS = dyn_cast(U->getOperand(1))) @@ -2365,12 +2365,12 @@ } Tmp2 = ComputeNumSignBits(U->getOperand(1), Depth + 1, Q); - if (Tmp2 == 1) return 1; + if (Tmp2 == 1) break; return std::min(Tmp, Tmp2)-1; case Instruction::Sub: Tmp2 = ComputeNumSignBits(U->getOperand(1), Depth + 1, Q); - if (Tmp2 == 1) return 1; + if (Tmp2 == 1) break; // Handle NEG. if (const auto *CLHS = dyn_cast(U->getOperand(0))) @@ -2393,15 +2393,15 @@ // Sub can have at most one carry bit. Thus we know that the output // is, at worst, one more bit than the inputs. Tmp = ComputeNumSignBits(U->getOperand(0), Depth + 1, Q); - if (Tmp == 1) return 1; // Early out. + if (Tmp == 1) break; return std::min(Tmp, Tmp2)-1; case Instruction::Mul: { // The output of the Mul can be at most twice the valid bits in the inputs. unsigned SignBitsOp0 = ComputeNumSignBits(U->getOperand(0), Depth + 1, Q); - if (SignBitsOp0 == 1) return 1; // Early out. + if (SignBitsOp0 == 1) break; unsigned SignBitsOp1 = ComputeNumSignBits(U->getOperand(1), Depth + 1, Q); - if (SignBitsOp1 == 1) return 1; + if (SignBitsOp1 == 1) break; unsigned OutValidBits = (TyBits - SignBitsOp0 + 1) + (TyBits - SignBitsOp1 + 1); return OutValidBits > TyBits ? 1 : TyBits - OutValidBits + 1; Index: llvm/trunk/test/Analysis/ValueTracking/numsignbits-from-assume.ll =================================================================== --- llvm/trunk/test/Analysis/ValueTracking/numsignbits-from-assume.ll +++ llvm/trunk/test/Analysis/ValueTracking/numsignbits-from-assume.ll @@ -0,0 +1,109 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -instcombine -S | FileCheck %s + +define i32 @computeNumSignBits_add1(i32 %in) { +; CHECK-LABEL: @computeNumSignBits_add1( +; CHECK-NEXT: [[ADD:%.*]] = add i32 [[IN:%.*]], 1 +; CHECK-NEXT: [[COND:%.*]] = icmp ult i32 [[ADD]], 43 +; CHECK-NEXT: call void @llvm.assume(i1 [[COND]]) +; CHECK-NEXT: [[SH:%.*]] = shl nuw nsw i32 [[ADD]], 3 +; CHECK-NEXT: ret i32 [[SH]] +; + %add = add i32 %in, 1 + %cond = icmp ule i32 %add, 42 + call void @llvm.assume(i1 %cond) + %sh = shl i32 %add, 3 + ret i32 %sh +} + +define i32 @computeNumSignBits_add2(i32 %in1, i32 %in2) { +; CHECK-LABEL: @computeNumSignBits_add2( +; CHECK-NEXT: [[ADD:%.*]] = add i32 [[IN1:%.*]], [[IN2:%.*]] +; CHECK-NEXT: [[COND:%.*]] = icmp ult i32 [[ADD]], 43 +; CHECK-NEXT: call void @llvm.assume(i1 [[COND]]) +; CHECK-NEXT: [[SH:%.*]] = shl nuw nsw i32 [[ADD]], 3 +; CHECK-NEXT: ret i32 [[SH]] +; + %add = add i32 %in1, %in2 + %cond = icmp ule i32 %add, 42 + call void @llvm.assume(i1 %cond) + %sh = shl i32 %add, 3 + ret i32 %sh +} + +define i32 @computeNumSignBits_sub1(i32 %in) { +; CHECK-LABEL: @computeNumSignBits_sub1( +; CHECK-NEXT: [[SUB:%.*]] = sub i32 1, [[IN:%.*]] +; CHECK-NEXT: [[COND:%.*]] = icmp ult i32 [[SUB]], 43 +; CHECK-NEXT: call void @llvm.assume(i1 [[COND]]) +; CHECK-NEXT: [[SH:%.*]] = shl nuw nsw i32 [[SUB]], 3 +; CHECK-NEXT: ret i32 [[SH]] +; + %sub = sub i32 1, %in + %cond = icmp ule i32 %sub, 42 + call void @llvm.assume(i1 %cond) + %sh = shl i32 %sub, 3 + ret i32 %sh +} + +define i32 @computeNumSignBits_sub2(i32 %in) { +; CHECK-LABEL: @computeNumSignBits_sub2( +; CHECK-NEXT: [[SUB:%.*]] = add i32 [[IN:%.*]], -1 +; CHECK-NEXT: [[COND:%.*]] = icmp ult i32 [[SUB]], 43 +; CHECK-NEXT: call void @llvm.assume(i1 [[COND]]) +; CHECK-NEXT: [[SH:%.*]] = shl nuw nsw i32 [[SUB]], 3 +; CHECK-NEXT: ret i32 [[SH]] +; + %sub = sub i32 %in, 1 + %cond = icmp ule i32 %sub, 42 + call void @llvm.assume(i1 %cond) + %sh = shl i32 %sub, 3 + ret i32 %sh +} + +define i32 @computeNumSignBits_sub3(i32 %in1, i32 %in2) { +; CHECK-LABEL: @computeNumSignBits_sub3( +; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[IN1:%.*]], [[IN2:%.*]] +; CHECK-NEXT: [[COND:%.*]] = icmp ult i32 [[SUB]], 43 +; CHECK-NEXT: call void @llvm.assume(i1 [[COND]]) +; CHECK-NEXT: [[SH:%.*]] = shl nuw nsw i32 [[SUB]], 3 +; CHECK-NEXT: ret i32 [[SH]] +; + %sub = sub i32 %in1, %in2 + %cond = icmp ule i32 %sub, 42 + call void @llvm.assume(i1 %cond) + %sh = shl i32 %sub, 3 + ret i32 %sh +} + +define i32 @computeNumSignBits_mul(i32 %in1, i32 %in2) { +; CHECK-LABEL: @computeNumSignBits_mul( +; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[IN1:%.*]], [[IN2:%.*]] +; CHECK-NEXT: [[COND:%.*]] = icmp ult i32 [[MUL]], 43 +; CHECK-NEXT: call void @llvm.assume(i1 [[COND]]) +; CHECK-NEXT: [[SH:%.*]] = shl nuw nsw i32 [[MUL]], 3 +; CHECK-NEXT: ret i32 [[SH]] +; + %mul = mul i32 %in1, %in2 + %cond = icmp ule i32 %mul, 42 + call void @llvm.assume(i1 %cond) + %sh = shl i32 %mul, 3 + ret i32 %sh +} + +define i32 @computeNumSignBits_select(i32 %in, i1 %s) { +; CHECK-LABEL: @computeNumSignBits_select( +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[S:%.*]], i32 [[IN:%.*]], i32 1 +; CHECK-NEXT: [[COND:%.*]] = icmp ult i32 [[SEL]], 43 +; CHECK-NEXT: call void @llvm.assume(i1 [[COND]]) +; CHECK-NEXT: [[SH:%.*]] = shl nuw nsw i32 [[SEL]], 3 +; CHECK-NEXT: ret i32 [[SH]] +; + %sel = select i1 %s, i32 %in, i32 1 + %cond = icmp ule i32 %sel, 42 + call void @llvm.assume(i1 %cond) + %sh = shl i32 %sel, 3 + ret i32 %sh +} + +declare void @llvm.assume(i1)