[PATCH] D93617: [LoopVectorize] Take non-instruction's size into consideration when computing leader's demanded bits

guopeilin via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 7 22:32:52 PST 2021


guopeilin added inline comments.


================
Comment at: llvm/lib/Analysis/VectorUtils.cpp:539
+    if (!isa<Instruction>(Val)) {
+      if (!isa<Argument>(Val))
+        continue;
----------------
guopeilin wrote:
> guopeilin wrote:
> > nikic wrote:
> > > guopeilin wrote:
> > > > nikic wrote:
> > > > > I think we can't entirely ignore non-arguments (aka constants) here. Take a look at this modified form of `llvm/test/Transforms/LoopVectorize/avoid-truncate-icmp-operands.ll`:
> > > > > 
> > > > > ```
> > > > > ; RUN: opt -loop-vectorize -S < %s | FileCheck %s
> > > > > target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
> > > > > target triple = "aarch64-unknown-linux-gnu"
> > > > > 
> > > > > @a = dso_local local_unnamed_addr global i64 0, align 8
> > > > > @b = dso_local local_unnamed_addr global i16 0, align 4
> > > > > 
> > > > > define dso_local void @myFunc(i32 %d, i32 %e) {
> > > > > ; CHECK:        pred.store.continue2:
> > > > > ; CHECK-NEXT:      %{{[0-9]+}} = icmp ult <2 x i64> %broadcast.splat{{[0-9]*}}, %broadcast.splat{{[0-9]*}}
> > > > > for.body29.lr.ph:
> > > > >   br label %for.body29
> > > > > 
> > > > > for.cond25.for.cond.cleanup28_crit_edge:          ; preds = %for.inc
> > > > >   ret void
> > > > > 
> > > > > for.body29:                                       ; preds = %for.inc, %for.body29.lr.ph
> > > > >   %n.078 = phi i16 [ undef, %for.body29.lr.ph ], [ %add34, %for.inc ]
> > > > >   br i1 undef, label %for.inc, label %if.then
> > > > > 
> > > > > if.then:                                          ; preds = %for.body29
> > > > >   %conv31 = zext i8 undef to i64
> > > > >   store i64 %conv31, i64* @a, align 8
> > > > >   %cmp.i = icmp ult i32 %e, %d
> > > > >   %.sroa.speculated = select i1 %cmp.i, i64 10000000000, i64 20000000000
> > > > >   %conv32 = trunc i64 %.sroa.speculated to i16
> > > > >   store i16 %conv32, i16* @b, align 4
> > > > >   br label %for.inc
> > > > > 
> > > > > for.inc:                                          ; preds = %if.then, %for.body29
> > > > >   %add34 = add nsw i16 %n.078, 2
> > > > >   %cmp27 = icmp slt i16 %add34, 16
> > > > >   br i1 %cmp27, label %for.body29, label %for.cond25.for.cond.cleanup28_crit_edge, !llvm.loop !6
> > > > > }
> > > > > 
> > > > > !6 = distinct !{!6, !7}
> > > > > !7 = !{!"llvm.loop.vectorize.enable", i1 true}
> > > > > ```
> > > > > 
> > > > > This gets vectorized with i32 width, but the two select constants are larger than 32-bit and get truncated.
> > > > > 
> > > > > I think the logic here should be: For `ConstantInt`, take the `getActiveBits()` of the constant value, for everything else (including Arguments) take the getTypeSizeInBits (what you're effectively doing now).
> > > > Thanks a lot for reviewing this patch. And a new patch has been updated, which takes case `ConstantInt` into consideration, too.
> > > > And there still exists something that confuses me. Firstly, I don't know why `the two select constants are larger than 32-bit`? As far as I can see, both `%d` and `%e` are defined as an `i32 argument`, what is the purpose that we take `ConstantInt` into consideration here?
> > > > Secondly, for `Constant`, there are `ConstantFP`, `ConstantInt` and some other kind of constant, so shall we take them into consideration, too?
> > > > It would be a great appreciation if you could explain it a bit more. Again, thanks a lot for reviewing.
> > > > 
> > > > And there still exists something that confuses me. Firstly, I don't know why `the two select constants are larger than 32-bit`? As far as I can see, both `%d` and `%e` are defined as an `i32 argument`, what is the purpose that we take `ConstantInt` into consideration here?
> > > 
> > > While the `%d` and `%e` arguments used in the icmp are 32-bit wide, the two constants that the `select` chooses between are larger than 32-bit. Vectorizing with 32-bit elements will also truncate the select constant and lose the top bits. Is this clearer?
> > > 
> > > By the way, it would be good if you could also add the above test case with a check that it uses i64 vectorization, not i32.
> > > 
> > > > Secondly, for `Constant`, there are `ConstantFP`, `ConstantInt` and some other kind of constant, so shall we take them into consideration, too?
> > > > It would be a great appreciation if you could explain it a bit more. Again, thanks a lot for reviewing.
> > > 
> > > I'm not sure to what degree these are really relevant in this code (as demanded bits only works on integer instructions), but generally yes, they should be taken into account. I would suggest to write the code something like this, so only ConstantInt has special treatment (to avoid regressions) while everything else is handled as "else":
> > > 
> > > ```
> > > unsigned BitSize;
> > > if (const auto *CI = dyn_cast<ConstantInt>(Val)) {
> > >   BitSize = CI->getValue().getActiveBits();
> > > } else {
> > >   DataLayout DL = ...;
> > >   BitSize = DL.getTypeSizeInBits(Val->getType());
> > > }
> > > 
> > > // Bail out for same reason below.
> > > if (BitSize > 64)
> > >   return MapVector<Instruction *, uint64_t>();
> > > uint64_t V = APInt::getAllOnesValue(BitSize).getZExtValue();
> > > DBits[Leader] |= V;
> > > LLVM_DEBUG(dbgs() << "\t Values's dbits " << Twine::utohexstr(V)
> > >                           << '\n');
> > > ```
> > > 
> > > There's just one problem there: Getting the DataLayout. I don't see any obvious way to get it, so it may be necessary to pass it as an argument to computeMinimumValueSizes().
> > Hi, Thanks a lot for your review and suggestion.
> > And as for DataLayout, I found that `ConstantInt` can be `0`,  the ActiveBits will return 0. So we may still need to check the BitSize before initializing APInt with BitSize. So maybe DL is not so necessary here.
> > Also, I found that case 
> > ```
> > Transforms/LoopVectorize/ARM/tail-folding-reduces-vf.ll
> > ```
> > failed if we `handle everything else as 'else'`. So maybe we can only take Argument and ConstantInt into consideration, a conservative way.
> > 
> Sorry, It seems that the failure of test case `Transforms/LoopVectorize/ARM/tail-folding-reduces-vf.ll` is not caused by `handle everything else as 'else'`, I am figuring it out. Please wait.
Hi, nikic! I update a new patch.
This patch fix three things:
Firstly, a `ConstantInt` can be zero, which means `getActiveBits` can be `0`, we still need to check `bitsize == 0` even through  we have `DL.getTypeSizeInBits(Val->getType())`. So I guess we don't need DataLayout here.
Secondly, a ConstantInt can be negative, if we still use `getActiveBits`, that is `BitWidth - countLeadingZeros()`, we will always get the most conservative bits for negative value cause its first bit is `1`. That is the reason why I failed on the test case by using getActiveBits for all ConstantInt
```
Transforms/LoopVectorize/ARM/tail-folding-reduces-vf.ll
```
For this case, there exist a negative constant int `-28`, So I use `getMinSignedBits()` for negative cases.
Thirdly, for no negative constant int, I still use `getActiveBits` as before. And handle everything else as 'else' by using `Val->getType()->getScalarSizeInBits()`


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D93617/new/

https://reviews.llvm.org/D93617



More information about the llvm-commits mailing list