[InstCombine] Support sext in foldLogicCastConstant

This adds support for sext in foldLogicCastConstant. This is a prerequisite for D36214.

Differential Revision: https://reviews.llvm.org/D36234

llvm-svn: 309880
This commit is contained in:
Craig Topper 2017-08-02 20:25:56 +00:00
parent 22dc4474a6
commit ae9b87d10c
4 changed files with 26 additions and 16 deletions

View File

@ -1089,10 +1089,10 @@ static Instruction *foldLogicCastConstant(BinaryOperator &Logic, CastInst *Cast,
Type *DestTy = Logic.getType(); Type *DestTy = Logic.getType();
Type *SrcTy = Cast->getSrcTy(); Type *SrcTy = Cast->getSrcTy();
// Move the logic operation ahead of a zext if the constant is unchanged in // Move the logic operation ahead of a zext or sext if the constant is
// the smaller source type. Performing the logic in a smaller type may provide // unchanged in the smaller source type. Performing the logic in a smaller
// more information to later folds, and the smaller logic instruction may be // type may provide more information to later folds, and the smaller logic
// cheaper (particularly in the case of vectors). // instruction may be cheaper (particularly in the case of vectors).
Value *X; Value *X;
if (match(Cast, m_OneUse(m_ZExt(m_Value(X))))) { if (match(Cast, m_OneUse(m_ZExt(m_Value(X))))) {
Constant *TruncC = ConstantExpr::getTrunc(C, SrcTy); Constant *TruncC = ConstantExpr::getTrunc(C, SrcTy);
@ -1104,6 +1104,16 @@ static Instruction *foldLogicCastConstant(BinaryOperator &Logic, CastInst *Cast,
} }
} }
if (match(Cast, m_OneUse(m_SExt(m_Value(X))))) {
Constant *TruncC = ConstantExpr::getTrunc(C, SrcTy);
Constant *SextTruncC = ConstantExpr::getSExt(TruncC, DestTy);
if (SextTruncC == C) {
// LogicOpc (sext X), C --> sext (LogicOpc X, C)
Value *NewOp = Builder.CreateBinOp(LogicOpc, X, TruncC);
return new SExtInst(NewOp, DestTy);
}
}
return nullptr; return nullptr;
} }

View File

@ -587,9 +587,9 @@ define i64 @test46(i64 %A) {
define i64 @test47(i8 %A) { define i64 @test47(i8 %A) {
; CHECK-LABEL: @test47( ; CHECK-LABEL: @test47(
; CHECK-NEXT: [[B:%.*]] = sext i8 %A to i64 ; CHECK-NEXT: [[TMP1:%.*]] = or i8 [[A:%.*]], 42
; CHECK-NEXT: [[C:%.*]] = and i64 [[B]], 4294967253 ; CHECK-NEXT: [[C:%.*]] = sext i8 [[TMP1]] to i64
; CHECK-NEXT: [[E:%.*]] = or i64 [[C]], 42 ; CHECK-NEXT: [[E:%.*]] = and i64 [[C]], 4294967295
; CHECK-NEXT: ret i64 [[E]] ; CHECK-NEXT: ret i64 [[E]]
; ;
%B = sext i8 %A to i32 %B = sext i8 %A to i32

View File

@ -504,11 +504,11 @@ define <4 x i32> @vec_sel_xor(<4 x i32> %a, <4 x i32> %b, <4 x i1> %c) {
define <4 x i32> @vec_sel_xor_multi_use(<4 x i32> %a, <4 x i32> %b, <4 x i1> %c) { define <4 x i32> @vec_sel_xor_multi_use(<4 x i32> %a, <4 x i32> %b, <4 x i1> %c) {
; CHECK-LABEL: @vec_sel_xor_multi_use( ; CHECK-LABEL: @vec_sel_xor_multi_use(
; CHECK-NEXT: [[MASK:%.*]] = sext <4 x i1> %c to <4 x i32> ; CHECK-NEXT: [[TMP1:%.*]] = xor <4 x i1> [[C:%.*]], <i1 true, i1 false, i1 false, i1 false>
; CHECK-NEXT: [[MASK_FLIP1:%.*]] = xor <4 x i32> [[MASK]], <i32 -1, i32 0, i32 0, i32 0> ; CHECK-NEXT: [[MASK_FLIP1:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i32>
; CHECK-NEXT: [[TMP1:%.*]] = xor <4 x i1> %c, <i1 false, i1 true, i1 true, i1 true> ; CHECK-NEXT: [[TMP2:%.*]] = xor <4 x i1> [[C]], <i1 false, i1 true, i1 true, i1 true>
; CHECK-NEXT: [[TMP2:%.*]] = select <4 x i1> [[TMP1]], <4 x i32> %a, <4 x i32> %b ; CHECK-NEXT: [[TMP3:%.*]] = select <4 x i1> [[TMP2]], <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]
; CHECK-NEXT: [[ADD:%.*]] = add <4 x i32> [[TMP2]], [[MASK_FLIP1]] ; CHECK-NEXT: [[ADD:%.*]] = add <4 x i32> [[TMP3]], [[MASK_FLIP1]]
; CHECK-NEXT: ret <4 x i32> [[ADD]] ; CHECK-NEXT: ret <4 x i32> [[ADD]]
; ;
%mask = sext <4 x i1> %c to <4 x i32> %mask = sext <4 x i1> %c to <4 x i32>

View File

@ -48,12 +48,12 @@ entry:
; optimization, we make the proposed smaller type (i8) larger (i16) to ; optimization, we make the proposed smaller type (i8) larger (i16) to
; ensure correctness. ; ensure correctness.
; ;
; CHECK: %[[S0:.+]] = sext <2 x i8> {{.*}} to <2 x i16> ; CHECK: %[[OR:.+]] = or <2 x i8> {{.*}}, <i8 1, i8 1>
; CHECK: %[[OR:.+]] = or <2 x i16> %[[S0]], <i16 1, i16 1> ; CHECK: %[[S0:.+]] = sext <2 x i8> %[[OR]] to <2 x i16>
; CHECK: %[[E0:.+]] = extractelement <2 x i16> %[[OR]], i32 0 ; CHECK: %[[E0:.+]] = extractelement <2 x i16> %[[S0]], i32 0
; CHECK: %[[S1:.+]] = sext i16 %[[E0]] to i64 ; CHECK: %[[S1:.+]] = sext i16 %[[E0]] to i64
; CHECK: getelementptr inbounds i8, i8* %ptr, i64 %[[S1]] ; CHECK: getelementptr inbounds i8, i8* %ptr, i64 %[[S1]]
; CHECK: %[[E1:.+]] = extractelement <2 x i16> %[[OR]], i32 1 ; CHECK: %[[E1:.+]] = extractelement <2 x i16> %[[S0]], i32 1
; CHECK: %[[S2:.+]] = sext i16 %[[E1]] to i64 ; CHECK: %[[S2:.+]] = sext i16 %[[E1]] to i64
; CHECK: getelementptr inbounds i8, i8* %ptr, i64 %[[S2]] ; CHECK: getelementptr inbounds i8, i8* %ptr, i64 %[[S2]]
; ;