[PATCH] InstCombine: Improve the result bitvect type when folding (cmp pred (load (gep GV, i)) C) to a bit test.

Ahmed Bougacha ahmed.bougacha at gmail.com
Thu Mar 21 09:39:31 PDT 2013


Hi Duncan !

On Thu, Mar 21, 2013 at 2:57 PM, Duncan Sands <baldrick at free.fr> wrote:
> Hi Ahmed,
>
>
>> This patch makes InstCombine choose better types when folding (cmp
>> pred (load (gep GV, i)) C) to a bit test (((bitvector >> i) & 1) !=
>> 0).
>>
>> As the commit says:
>>
>>> The original code used i32, and i64 if legal. This introduced unneeded
>>> casts when they aren't legal, or when the index variable i has another
>>> type. In order of preference: try to use i's type, looking past a cast
>>> if there is one;  use the smallest fitting legal type (using an added
>>> DataLayout method); default to i32.
>>> A testcase checks that this works when everything is i16.
>>
>>
>> I'm not convinced about adding DataLayout::getSmallestLegalIntType,
>> but it seemed like the natural way to do it (mirrorring
>> isLegalInteger).
>
>
>
>> --- a/include/llvm/IR/DataLayout.h
>> +++ b/include/llvm/IR/DataLayout.h
>> @@ -350,6 +350,9 @@ public:
>>    /// type.
>>    Type *getIntPtrType(Type *) const;
>>
>> +  /// getSmallestLegalIntType - Return an integer type with size
>
>
> This comment is incomplete.
>
>> +  Type *getSmallestLegalIntType(LLVMContext &C, unsigned Width = 0)
>> const;
>> +
>>    /// getIndexedOffset - return the offset from the beginning of the type
>> for
>>    /// the specified indices.  This is used to implement getelementptr.
>>    uint64_t getIndexedOffset(Type *Ty, ArrayRef<Value *> Indices) const;
>
>
>> --- a/lib/Transforms/InstCombine/InstCombineCompares.cpp
>> +++ b/lib/Transforms/InstCombine/InstCombineCompares.cpp
>> @@ -443,20 +443,35 @@ FoldCmpLoadFromIndexedGlobal(GetElementPtrInst *GEP,
>> GlobalVariable *GV,
>>    }
>>
>>
>> -  // If a 32-bit or 64-bit magic bitvector captures the entire comparison
>> state
>> +  // If a magic bitvector captures the entire comparison state
>>    // of this load, replace it with computation that does:
>>    //   ((magic_cst >> i) & 1) != 0
>> -  if (ArrayElementCount <= 32 ||
>> -      (TD && ArrayElementCount <= 64 && TD->isLegalInteger(64))) {
>> -    Type *Ty;
>> -    if (ArrayElementCount <= 32)
>> +  {
>> +    Type *Ty = 0;
>> +
>> +    // Default to either a legal type, or i32
>> +    if (TD)
>> +      Ty = TD->getSmallestLegalIntType(Init->getContext(),
>> ArrayElementCount);
>> +    else if (ArrayElementCount <= 32)
>>        Ty = Type::getInt32Ty(Init->getContext());
>> -    else
>> -      Ty = Type::getInt64Ty(Init->getContext());
>> -    Value *V = Builder->CreateIntCast(Idx, Ty, false);
>> -    V = Builder->CreateLShr(ConstantInt::get(Ty, MagicBitvector), V);
>> -    V = Builder->CreateAnd(ConstantInt::get(Ty, 1), V);
>> -    return new ICmpInst(ICmpInst::ICMP_NE, V, ConstantInt::get(Ty, 0));
>> +
>> +    // Use Idx' type; if it's a cast, look past it
>
>
> Given that you might have already determined a value for Ty, shouldn't this
> logic only apply when Ty is null?  If not, then shouldn't you first check
> this
> case and only do the above Ty logic afterwards (if Ty is null) in order to
> reduce unnecessary work.  Also I think you mean "Idx" in the comment not
> "Idx'".  Finally, why look through casts of Idx here, why not just let the
> optimizers zap the extra cast if they think it is a good idea?
>
>> +    CastInst *IdxC = dyn_cast<CastInst>(Idx);
>> +    if (IdxC && IdxC->isIntegerCast() &&
>> +        ArrayElementCount <= IdxC->getSrcTy()->getIntegerBitWidth() &&
>> +        ShouldOptimizeCast(IdxC->getOpcode(), IdxC->getOperand(0),
>> +                           Idx->getType())) {
>> +      Ty = IdxC->getSrcTy();
>> +      Idx = IdxC->getOperand(0);
>> +    } else if (ArrayElementCount <= Idx->getType()->getIntegerBitWidth())
>> +      Ty = Idx->getType();
>
>
> Style: the above line should be in curly brackets {} because the preceding
> "if" branch was.
>
>> +
>> +    if (Ty != 0) {
>> +      Value *V = Builder->CreateIntCast(Idx, Ty, false);
>> +      V = Builder->CreateLShr(ConstantInt::get(Ty, MagicBitvector), V);
>> +      V = Builder->CreateAnd(ConstantInt::get(Ty, 1), V);
>> +      return new ICmpInst(ICmpInst::ICMP_NE, V, ConstantInt::get(Ty, 0));
>> +    }
>>    }
>>
>>    return 0;
>
>
> Lastly, I don't think your testcase tests all cases, for example it doesn't
> look like it tests the case when Idx is a cast, so can you please beef it
> up.

The cast was implicitly added as InstCombine casts the getelementptr's
operands to the DataLayout pointer type (here i64). I originally added
the cast-aware part because it avoided introducing pointer-sized
arithmetic when keeping the index type is enough, but I'm not sure
what's the best thing to do here.
Anyway, I updated the patch to no longer take into account casted
indices (among the other fixes, sorry for the hastiness!).
Also, I replaced the testcase with a cleaner one, next to its i32 equivalent.

Thanks!

> Best wishes, Duncan.
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-InstCombine-Improve-the-result-bitvect-type-when-fol.patch
Type: application/octet-stream
Size: 4887 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20130321/4af52ca8/attachment.obj>


More information about the llvm-commits mailing list