llvm.org GIT mirror llvm / 9b2526d
[ValueTracking] Don't do an unchecked shift in ComputeNumSignBits Summary: Previously we used to return a bogus result, 0, for IR like `ashr %val, -1`. I've also added an assert checking that `ComputeNumSignBits` at least returns 1. That assert found an already checked in test case where we were returning a bad result for `ashr %val, -1`. Fixes PR32045. Reviewers: spatel, majnemer Reviewed By: spatel, majnemer Subscribers: efriedma, mcrosier, llvm-commits Differential Revision: https://reviews.llvm.org/D30311 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@296273 91177308-0d34-0410-b5e6-96231b3b80d8 Sanjoy Das 2 years ago
3 changed file(s) with 79 addition(s) and 2 deletion(s). Raw diff Collapse all Expand all
21122112 return MinSignBits;
21132113 }
21142114
2115 static unsigned ComputeNumSignBitsImpl(const Value *V, unsigned Depth,
2116 const Query &Q);
2117
2118 static unsigned ComputeNumSignBits(const Value *V, unsigned Depth,
2119 const Query &Q) {
2120 unsigned Result = ComputeNumSignBitsImpl(V, Depth, Q);
2121 assert(Result > 0 && "At least one sign bit needs to be present!");
2122 return Result;
2123 }
2124
21152125 /// Return the number of times the sign bit of the register is replicated into
21162126 /// the other bits. We know that at least 1 bit is always equal to the sign bit
21172127 /// (itself), but other cases can give us information. For example, immediately
21182128 /// after an "ashr X, 2", we know that the top 3 bits are all equal to each
21192129 /// other, so we return 3. For vectors, return the number of sign bits for the
21202130 /// vector element with the mininum number of known sign bits.
2121 unsigned ComputeNumSignBits(const Value *V, unsigned Depth, const Query &Q) {
2131 static unsigned ComputeNumSignBitsImpl(const Value *V, unsigned Depth,
2132 const Query &Q) {
2133
2134 // We return the minimum number of sign bits that are guaranteed to be present
2135 // in V, so for undef we have to conservatively return 1. We don't have the
2136 // same behavior for poison though -- that's a FIXME today.
2137
21222138 unsigned TyBits = Q.DL.getTypeSizeInBits(V->getType()->getScalarType());
21232139 unsigned Tmp, Tmp2;
21242140 unsigned FirstAnswer = 1;
21942210 // ashr X, C -> adds C sign bits. Vectors too.
21952211 const APInt *ShAmt;
21962212 if (match(U->getOperand(1), m_APInt(ShAmt))) {
2197 Tmp += ShAmt->getZExtValue();
2213 unsigned ShAmtLimited = ShAmt->getZExtValue();
2214 if (ShAmtLimited >= TyBits)
2215 break; // Bad shift.
2216 Tmp += ShAmtLimited;
21982217 if (Tmp > TyBits) Tmp = TyBits;
21992218 }
22002219 return Tmp;
0 ; RUN: opt -S -indvars < %s | FileCheck %s
1
2 ; This is not an IndVarSimplify bug, but the original symptom
3 ; manifested as one.
4
5 define i32 @foo(i32 %a, i32 %b, i32 %c, i32* %sink) {
6 ; CHECK-LABEL: @foo(
7 ; CHECK: for.end:
8 ; CHECK-NEXT: [[SHR:%.*]] = ashr i32 %neg3, -1
9 ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 0, [[SHR]]
10 ; CHECK-NEXT: [[SHR1:%.*]] = ashr i32 [[SUB]], [[B:%.*]]
11 ; CHECK-NEXT: [[NEG:%.*]] = xor i32 [[SHR1]], -1
12 ; CHECK-NEXT: store i32 [[NEG]], i32* %sink
13 ;
14 entry:
15 %tobool2 = icmp eq i32 %a, 0
16 br i1 %tobool2, label %exit, label %preheader
17
18 preheader:
19 %neg3 = phi i32 [ %c, %entry ], [ %neg, %for.end ]
20 br label %for
21
22 for:
23 %p = phi i32 [ %dec, %for ], [ 1, %preheader ]
24 %cmp = icmp sgt i32 %p, -1
25 %dec = add nsw i32 %p, -1
26 br i1 %cmp, label %for, label %for.end
27
28 for.end:
29 %shr = ashr i32 %neg3, %p
30 %sub = sub nsw i32 0, %shr
31 %shr1 = ashr i32 %sub, %b
32 %neg = xor i32 %shr1, -1
33 store i32 %neg, i32* %sink
34 br i1 false, label %exit, label %preheader
35
36 exit:
37 ret i32 0
38 }
238238 Index++;
239239 }
240240 }
241
242 TEST(ValueTracking, ComputeNumSignBits_PR32045) {
243 StringRef Assembly = "define i32 @f(i32 %a) { "
244 " %val = ashr i32 %a, -1 "
245 " ret i32 %val "
246 "} ";
247
248 LLVMContext Context;
249 SMDiagnostic Error;
250 auto M = parseAssemblyString(Assembly, Error, Context);
251 assert(M && "Bad assembly?");
252
253 auto *F = M->getFunction("f");
254 assert(F && "Bad assembly?");
255
256 auto *RVal =
257 cast(F->getEntryBlock().getTerminator())->getOperand(0);
258 EXPECT_EQ(ComputeNumSignBits(RVal, M->getDataLayout()), 1);
259 }