mirror of
https://github.com/RPCS3/llvm.git
synced 2025-02-01 16:22:41 +00:00
InstCombine: Improve the result bitvect type when folding (cmp pred (load (gep GV, i)) C) to a bit test.
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; use the smallest fitting legal type (using an added DataLayout method); default to i32. A testcase checks that this works when the index gep operand is i16. Patch by : Ahmed Bougacha <ahmed.bougacha@gmail.com> Reviewed by : Duncan git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@177712 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
9b294d4056
commit
2be921adc4
@ -352,6 +352,10 @@ public:
|
|||||||
/// type.
|
/// type.
|
||||||
Type *getIntPtrType(Type *) const;
|
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
|
/// getIndexedOffset - return the offset from the beginning of the type for
|
||||||
/// the specified indices. This is used to implement getelementptr.
|
/// the specified indices. This is used to implement getelementptr.
|
||||||
uint64_t getIndexedOffset(Type *Ty, ArrayRef<Value *> Indices) const;
|
uint64_t getIndexedOffset(Type *Ty, ArrayRef<Value *> Indices) const;
|
||||||
|
@ -621,6 +621,13 @@ Type *DataLayout::getIntPtrType(Type *Ty) const {
|
|||||||
return IntTy;
|
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,
|
uint64_t DataLayout::getIndexedOffset(Type *ptrTy,
|
||||||
ArrayRef<Value *> Indices) const {
|
ArrayRef<Value *> Indices) const {
|
||||||
Type *Ty = ptrTy;
|
Type *Ty = ptrTy;
|
||||||
|
@ -443,21 +443,30 @@ 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:
|
// of this load, replace it with computation that does:
|
||||||
// ((magic_cst >> i) & 1) != 0
|
// ((magic_cst >> i) & 1) != 0
|
||||||
if (ArrayElementCount <= 32 ||
|
{
|
||||||
(TD && ArrayElementCount <= 64 && TD->isLegalInteger(64))) {
|
Type *Ty = 0;
|
||||||
Type *Ty;
|
|
||||||
if (ArrayElementCount <= 32)
|
// 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());
|
Ty = Type::getInt32Ty(Init->getContext());
|
||||||
else
|
|
||||||
Ty = Type::getInt64Ty(Init->getContext());
|
if (Ty != 0) {
|
||||||
Value *V = Builder->CreateIntCast(Idx, Ty, false);
|
Value *V = Builder->CreateIntCast(Idx, Ty, false);
|
||||||
V = Builder->CreateLShr(ConstantInt::get(Ty, MagicBitvector), V);
|
V = Builder->CreateLShr(ConstantInt::get(Ty, MagicBitvector), V);
|
||||||
V = Builder->CreateAnd(ConstantInt::get(Ty, 1), V);
|
V = Builder->CreateAnd(ConstantInt::get(Ty, 1), V);
|
||||||
return new ICmpInst(ICmpInst::ICMP_NE, V, ConstantInt::get(Ty, 0));
|
return new ICmpInst(ICmpInst::ICMP_NE, V, ConstantInt::get(Ty, 0));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -47,6 +47,18 @@ define i1 @test4(i32 %X) {
|
|||||||
; CHECK-NEXT: ret i1 %R
|
; 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) {
|
define i1 @test5(i32 %X) {
|
||||||
%P = getelementptr inbounds [10 x i16]* @G16, i32 0, i32 %X
|
%P = getelementptr inbounds [10 x i16]* @G16, i32 0, i32 %X
|
||||||
%Q = load i16* %P
|
%Q = load i16* %P
|
||||||
|
Loading…
x
Reference in New Issue
Block a user