mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 11:42:57 +01:00
[InstCombine] Teach canEvaluateZExtd and canEvaluateTruncated to handle vector shifts with splat shift amount
We were only allowing ConstantInt before. This patch allows splat of ConstantInt too. Differential Revision: https://reviews.llvm.org/D36763 llvm-svn: 310970
This commit is contained in:
parent
862e639dc6
commit
3cf4550e3b
@ -346,29 +346,33 @@ static bool canEvaluateTruncated(Value *V, Type *Ty, InstCombiner &IC,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Instruction::Shl:
|
||||
case Instruction::Shl: {
|
||||
// If we are truncating the result of this SHL, and if it's a shift of a
|
||||
// constant amount, we can always perform a SHL in a smaller type.
|
||||
if (ConstantInt *CI = dyn_cast<ConstantInt>(I->getOperand(1))) {
|
||||
const APInt *Amt;
|
||||
if (match(I->getOperand(1), m_APInt(Amt))) {
|
||||
uint32_t BitWidth = Ty->getScalarSizeInBits();
|
||||
if (CI->getLimitedValue(BitWidth) < BitWidth)
|
||||
if (Amt->getLimitedValue(BitWidth) < BitWidth)
|
||||
return canEvaluateTruncated(I->getOperand(0), Ty, IC, CxtI);
|
||||
}
|
||||
break;
|
||||
case Instruction::LShr:
|
||||
}
|
||||
case Instruction::LShr: {
|
||||
// If this is a truncate of a logical shr, we can truncate it to a smaller
|
||||
// lshr iff we know that the bits we would otherwise be shifting in are
|
||||
// already zeros.
|
||||
if (ConstantInt *CI = dyn_cast<ConstantInt>(I->getOperand(1))) {
|
||||
const APInt *Amt;
|
||||
if (match(I->getOperand(1), m_APInt(Amt))) {
|
||||
uint32_t OrigBitWidth = OrigTy->getScalarSizeInBits();
|
||||
uint32_t BitWidth = Ty->getScalarSizeInBits();
|
||||
if (IC.MaskedValueIsZero(I->getOperand(0),
|
||||
APInt::getHighBitsSet(OrigBitWidth, OrigBitWidth-BitWidth), 0, CxtI) &&
|
||||
CI->getLimitedValue(BitWidth) < BitWidth) {
|
||||
Amt->getLimitedValue(BitWidth) < BitWidth) {
|
||||
return canEvaluateTruncated(I->getOperand(0), Ty, IC, CxtI);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Instruction::Trunc:
|
||||
// trunc(trunc(x)) -> trunc(x)
|
||||
return true;
|
||||
@ -936,10 +940,11 @@ static bool canEvaluateZExtd(Value *V, Type *Ty, unsigned &BitsToClear,
|
||||
// Otherwise, we don't know how to analyze this BitsToClear case yet.
|
||||
return false;
|
||||
|
||||
case Instruction::Shl:
|
||||
case Instruction::Shl: {
|
||||
// We can promote shl(x, cst) if we can promote x. Since shl overwrites the
|
||||
// upper bits we can reduce BitsToClear by the shift amount.
|
||||
if (ConstantInt *Amt = dyn_cast<ConstantInt>(I->getOperand(1))) {
|
||||
const APInt *Amt;
|
||||
if (match(I->getOperand(1), m_APInt(Amt))) {
|
||||
if (!canEvaluateZExtd(I->getOperand(0), Ty, BitsToClear, IC, CxtI))
|
||||
return false;
|
||||
uint64_t ShiftAmt = Amt->getZExtValue();
|
||||
@ -947,10 +952,12 @@ static bool canEvaluateZExtd(Value *V, Type *Ty, unsigned &BitsToClear,
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case Instruction::LShr:
|
||||
}
|
||||
case Instruction::LShr: {
|
||||
// We can promote lshr(x, cst) if we can promote x. This requires the
|
||||
// ultimate 'and' to clear out the high zero bits we're clearing out though.
|
||||
if (ConstantInt *Amt = dyn_cast<ConstantInt>(I->getOperand(1))) {
|
||||
const APInt *Amt;
|
||||
if (match(I->getOperand(1), m_APInt(Amt))) {
|
||||
if (!canEvaluateZExtd(I->getOperand(0), Ty, BitsToClear, IC, CxtI))
|
||||
return false;
|
||||
BitsToClear += Amt->getZExtValue();
|
||||
@ -960,6 +967,7 @@ static bool canEvaluateZExtd(Value *V, Type *Ty, unsigned &BitsToClear,
|
||||
}
|
||||
// Cannot promote variable LSHR.
|
||||
return false;
|
||||
}
|
||||
case Instruction::Select:
|
||||
if (!canEvaluateZExtd(I->getOperand(1), Ty, Tmp, IC, CxtI) ||
|
||||
!canEvaluateZExtd(I->getOperand(2), Ty, BitsToClear, IC, CxtI) ||
|
||||
|
@ -492,6 +492,21 @@ define i16 @test40(i16 %a) {
|
||||
ret i16 %tmp.upgrd.3
|
||||
}
|
||||
|
||||
define <2 x i16> @test40vec(<2 x i16> %a) {
|
||||
; CHECK-LABEL: @test40vec(
|
||||
; CHECK-NEXT: [[TMP21:%.*]] = lshr <2 x i16> [[A:%.*]], <i16 9, i16 9>
|
||||
; CHECK-NEXT: [[TMP5:%.*]] = shl <2 x i16> [[A]], <i16 8, i16 8>
|
||||
; CHECK-NEXT: [[TMP_UPGRD_32:%.*]] = or <2 x i16> [[TMP21]], [[TMP5]]
|
||||
; CHECK-NEXT: ret <2 x i16> [[TMP_UPGRD_32]]
|
||||
;
|
||||
%tmp = zext <2 x i16> %a to <2 x i32>
|
||||
%tmp21 = lshr <2 x i32> %tmp, <i32 9, i32 9>
|
||||
%tmp5 = shl <2 x i32> %tmp, <i32 8, i32 8>
|
||||
%tmp.upgrd.32 = or <2 x i32> %tmp21, %tmp5
|
||||
%tmp.upgrd.3 = trunc <2 x i32> %tmp.upgrd.32 to <2 x i16>
|
||||
ret <2 x i16> %tmp.upgrd.3
|
||||
}
|
||||
|
||||
; PR1263
|
||||
define i32* @test41(i32* %tmp1) {
|
||||
; CHECK-LABEL: @test41(
|
||||
@ -585,6 +600,19 @@ define i64 @test46(i64 %A) {
|
||||
ret i64 %E
|
||||
}
|
||||
|
||||
define <2 x i64> @test46vec(<2 x i64> %A) {
|
||||
; CHECK-LABEL: @test46vec(
|
||||
; CHECK-NEXT: [[C:%.*]] = shl <2 x i64> [[A:%.*]], <i64 8, i64 8>
|
||||
; CHECK-NEXT: [[D:%.*]] = and <2 x i64> [[C]], <i64 10752, i64 10752>
|
||||
; CHECK-NEXT: ret <2 x i64> [[D]]
|
||||
;
|
||||
%B = trunc <2 x i64> %A to <2 x i32>
|
||||
%C = and <2 x i32> %B, <i32 42, i32 42>
|
||||
%D = shl <2 x i32> %C, <i32 8, i32 8>
|
||||
%E = zext <2 x i32> %D to <2 x i64>
|
||||
ret <2 x i64> %E
|
||||
}
|
||||
|
||||
define i64 @test47(i8 %A) {
|
||||
; CHECK-LABEL: @test47(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = or i8 [[A:%.*]], 42
|
||||
@ -729,6 +757,19 @@ define i64 @test56(i16 %A) nounwind {
|
||||
ret i64 %tmp355
|
||||
}
|
||||
|
||||
define <2 x i64> @test56vec(<2 x i16> %A) nounwind {
|
||||
; CHECK-LABEL: @test56vec(
|
||||
; CHECK-NEXT: [[TMP353:%.*]] = sext <2 x i16> [[A:%.*]] to <2 x i64>
|
||||
; CHECK-NEXT: [[TMP354:%.*]] = lshr <2 x i64> [[TMP353]], <i64 5, i64 5>
|
||||
; CHECK-NEXT: [[TMP355:%.*]] = and <2 x i64> [[TMP354]], <i64 134217727, i64 134217727>
|
||||
; CHECK-NEXT: ret <2 x i64> [[TMP355]]
|
||||
;
|
||||
%tmp353 = sext <2 x i16> %A to <2 x i32>
|
||||
%tmp354 = lshr <2 x i32> %tmp353, <i32 5, i32 5>
|
||||
%tmp355 = zext <2 x i32> %tmp354 to <2 x i64>
|
||||
ret <2 x i64> %tmp355
|
||||
}
|
||||
|
||||
define i64 @test57(i64 %A) nounwind {
|
||||
; CHECK-LABEL: @test57(
|
||||
; CHECK-NEXT: [[C:%.*]] = lshr i64 %A, 8
|
||||
@ -741,6 +782,18 @@ define i64 @test57(i64 %A) nounwind {
|
||||
ret i64 %E
|
||||
}
|
||||
|
||||
define <2 x i64> @test57vec(<2 x i64> %A) nounwind {
|
||||
; CHECK-LABEL: @test57vec(
|
||||
; CHECK-NEXT: [[C:%.*]] = lshr <2 x i64> [[A:%.*]], <i64 8, i64 8>
|
||||
; CHECK-NEXT: [[E:%.*]] = and <2 x i64> [[C]], <i64 16777215, i64 16777215>
|
||||
; CHECK-NEXT: ret <2 x i64> [[E]]
|
||||
;
|
||||
%B = trunc <2 x i64> %A to <2 x i32>
|
||||
%C = lshr <2 x i32> %B, <i32 8, i32 8>
|
||||
%E = zext <2 x i32> %C to <2 x i64>
|
||||
ret <2 x i64> %E
|
||||
}
|
||||
|
||||
define i64 @test58(i64 %A) nounwind {
|
||||
; CHECK-LABEL: @test58(
|
||||
; CHECK-NEXT: [[C:%.*]] = lshr i64 %A, 8
|
||||
|
Loading…
Reference in New Issue
Block a user