@@ -232,41 +232,53 @@ KnownBits KnownBits::smin(const KnownBits &LHS, const KnownBits &RHS) {
232
232
}
233
233
234
234
KnownBits KnownBits::abdu (const KnownBits &LHS, const KnownBits &RHS) {
235
- // abdu(LHS,RHS) = sub(umax(LHS,RHS), umin(LHS,RHS)).
236
- KnownBits UMaxValue = umax (LHS, RHS);
237
- KnownBits UMinValue = umin (LHS, RHS);
238
- KnownBits MinMaxDiff = computeForAddSub (/* Add=*/ false , /* NSW=*/ false ,
239
- /* NUW=*/ true , UMaxValue, UMinValue);
235
+ // If we know which argument is larger, return (sub LHS, RHS) or
236
+ // (sub RHS, LHS) directly.
237
+ if (LHS.getMinValue ().uge (RHS.getMaxValue ()))
238
+ return computeForAddSub (/* Add=*/ false , /* NSW=*/ false , /* NUW=*/ false , LHS,
239
+ RHS);
240
+ if (RHS.getMinValue ().uge (LHS.getMaxValue ()))
241
+ return computeForAddSub (/* Add=*/ false , /* NSW=*/ false , /* NUW=*/ false , RHS,
242
+ LHS);
240
243
241
- // find the common bits between sub(LHS,RHS) and sub(RHS,LHS).
244
+ // By construction, the subtraction in abdu never has unsigned overflow.
245
+ // Find the common bits between (sub nuw LHS, RHS) and (sub nuw RHS, LHS).
242
246
KnownBits Diff0 =
243
- computeForAddSub (/* Add=*/ false , /* NSW=*/ false , /* NUW=*/ false , LHS, RHS);
247
+ computeForAddSub (/* Add=*/ false , /* NSW=*/ false , /* NUW=*/ true , LHS, RHS);
244
248
KnownBits Diff1 =
245
- computeForAddSub (/* Add=*/ false , /* NSW=*/ false , /* NUW=*/ false , RHS, LHS);
246
- KnownBits SubDiff = Diff0.intersectWith (Diff1);
247
-
248
- KnownBits KnownAbsDiff = MinMaxDiff.unionWith (SubDiff);
249
- assert (!KnownAbsDiff.hasConflict () && " Bad Output" );
250
- return KnownAbsDiff;
249
+ computeForAddSub (/* Add=*/ false , /* NSW=*/ false , /* NUW=*/ true , RHS, LHS);
250
+ return Diff0.intersectWith (Diff1);
251
251
}
252
252
253
- KnownBits KnownBits::abds (const KnownBits &LHS, const KnownBits &RHS) {
254
- // abds(LHS,RHS) = sub(smax(LHS,RHS), smin(LHS,RHS)).
255
- KnownBits SMaxValue = smax (LHS, RHS);
256
- KnownBits SMinValue = smin (LHS, RHS);
257
- KnownBits MinMaxDiff = computeForAddSub (/* Add=*/ false , /* NSW=*/ false ,
258
- /* NUW=*/ false , SMaxValue, SMinValue);
253
+ KnownBits KnownBits::abds (KnownBits LHS, KnownBits RHS) {
254
+ // If we know which argument is larger, return (sub LHS, RHS) or
255
+ // (sub RHS, LHS) directly.
256
+ if (LHS.getSignedMinValue ().sge (RHS.getSignedMaxValue ()))
257
+ return computeForAddSub (/* Add=*/ false , /* NSW=*/ false , /* NUW=*/ false , LHS,
258
+ RHS);
259
+ if (RHS.getSignedMinValue ().sge (LHS.getSignedMaxValue ()))
260
+ return computeForAddSub (/* Add=*/ false , /* NSW=*/ false , /* NUW=*/ false , RHS,
261
+ LHS);
262
+
263
+ // Shift both arguments from the signed range to the unsigned range, e.g. from
264
+ // [-0x80, 0x7F] to [0, 0xFF]. This allows us to use "sub nuw" below just like
265
+ // abdu does.
266
+ // Note that we can't just use "sub nsw" instead because abds has signed
267
+ // inputs but an unsigned result, which makes the overflow conditions
268
+ // different.
269
+ unsigned SignBitPosition = LHS.getBitWidth () - 1 ;
270
+ for (auto Arg : {&LHS, &RHS}) {
271
+ bool Tmp = Arg->Zero [SignBitPosition];
272
+ Arg->Zero .setBitVal (SignBitPosition, Arg->One [SignBitPosition]);
273
+ Arg->One .setBitVal (SignBitPosition, Tmp);
274
+ }
259
275
260
- // find the common bits between sub( LHS,RHS) and sub( RHS,LHS).
276
+ // Find the common bits between (sub nuw LHS, RHS) and (sub nuw RHS, LHS).
261
277
KnownBits Diff0 =
262
- computeForAddSub (/* Add=*/ false , /* NSW=*/ false , /* NUW=*/ false , LHS, RHS);
278
+ computeForAddSub (/* Add=*/ false , /* NSW=*/ false , /* NUW=*/ true , LHS, RHS);
263
279
KnownBits Diff1 =
264
- computeForAddSub (/* Add=*/ false , /* NSW=*/ false , /* NUW=*/ false , RHS, LHS);
265
- KnownBits SubDiff = Diff0.intersectWith (Diff1);
266
-
267
- KnownBits KnownAbsDiff = MinMaxDiff.unionWith (SubDiff);
268
- assert (!KnownAbsDiff.hasConflict () && " Bad Output" );
269
- return KnownAbsDiff;
280
+ computeForAddSub (/* Add=*/ false , /* NSW=*/ false , /* NUW=*/ true , RHS, LHS);
281
+ return Diff0.intersectWith (Diff1);
270
282
}
271
283
272
284
static unsigned getMaxShiftAmount (const APInt &MaxValue, unsigned BitWidth) {
0 commit comments