diff options
-rw-r--r-- | include/llvm/IR/DataLayout.h | 4 | ||||
-rw-r--r-- | lib/IR/DataLayout.cpp | 7 | ||||
-rw-r--r-- | lib/Transforms/InstCombine/InstCombineCompares.cpp | 31 | ||||
-rw-r--r-- | test/Transforms/InstCombine/load-cmp.ll | 12 |
4 files changed, 43 insertions, 11 deletions
diff --git a/include/llvm/IR/DataLayout.h b/include/llvm/IR/DataLayout.h index 72b4eedabd..547d857b7b 100644 --- a/include/llvm/IR/DataLayout.h +++ b/include/llvm/IR/DataLayout.h @@ -352,6 +352,10 @@ public: /// type. Type *getIntPtrType(Type *) const; + /// getSmallestLegalIntType - Return the smallest integer type with size at + /// least as big as Width bits. + 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; diff --git a/lib/IR/DataLayout.cpp b/lib/IR/DataLayout.cpp index 9596674912..ecd5216f20 100644 --- a/lib/IR/DataLayout.cpp +++ b/lib/IR/DataLayout.cpp @@ -621,6 +621,13 @@ Type *DataLayout::getIntPtrType(Type *Ty) const { return IntTy; } +Type *DataLayout::getSmallestLegalIntType(LLVMContext &C, unsigned Width) const { + for (unsigned i = 0, e = (unsigned)LegalIntWidths.size(); i != e; ++i) + if (Width <= LegalIntWidths[i]) + return Type::getIntNTy(C, LegalIntWidths[i]); + return 0; +} + uint64_t DataLayout::getIndexedOffset(Type *ptrTy, ArrayRef<Value *> Indices) const { Type *Ty = ptrTy; diff --git a/lib/Transforms/InstCombine/InstCombineCompares.cpp b/lib/Transforms/InstCombine/InstCombineCompares.cpp index 32fdb9b708..a4e117e4c4 100644 --- a/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -443,20 +443,29 @@ 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; + + // Look for an appropriate type: + // - The type of Idx if the magic fits + // - The smallest fitting legal type if we have a DataLayout + // - Default to i32 + if (ArrayElementCount <= Idx->getType()->getIntegerBitWidth()) + Ty = Idx->getType(); + else 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)); + + 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; diff --git a/test/Transforms/InstCombine/load-cmp.ll b/test/Transforms/InstCombine/load-cmp.ll index 5cafb7787e..d88188e410 100644 --- a/test/Transforms/InstCombine/load-cmp.ll +++ b/test/Transforms/InstCombine/load-cmp.ll @@ -47,6 +47,18 @@ define i1 @test4(i32 %X) { ; CHECK-NEXT: ret i1 %R } +define i1 @test4_i16(i16 %X) { + %P = getelementptr inbounds [10 x i16]* @G16, i32 0, i16 %X + %Q = load i16* %P + %R = icmp sle i16 %Q, 73 + ret i1 %R +; CHECK: @test4_i16 +; CHECK-NEXT: lshr i16 933, %X +; CHECK-NEXT: and i16 {{.*}}, 1 +; CHECK-NEXT: %R = icmp ne i16 {{.*}}, 0 +; CHECK-NEXT: ret i1 %R +} + define i1 @test5(i32 %X) { %P = getelementptr inbounds [10 x i16]* @G16, i32 0, i32 %X %Q = load i16* %P |