Skip to content

Commit 9075edc

Browse files
committed
[InstCombine] move shl-only folds out from under commonShiftTransforms(); NFCI
This is no-functional-change-intended, but it hopefully makes things slightly clearer and more efficient to have transforms that require 'shl' be called only from visitShl(). Further cleanup is possible.
1 parent 3dbf27e commit 9075edc

File tree

1 file changed

+124
-127
lines changed

1 file changed

+124
-127
lines changed

llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp

Lines changed: 124 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -661,14 +661,13 @@ static bool canShiftBinOpWithConstantRHS(BinaryOperator &Shift,
661661

662662
Instruction *InstCombinerImpl::FoldShiftByConstant(Value *Op0, Constant *Op1,
663663
BinaryOperator &I) {
664-
bool IsLeftShift = I.getOpcode() == Instruction::Shl;
665-
666664
const APInt *Op1C;
667665
if (!match(Op1, m_APInt(Op1C)))
668666
return nullptr;
669667

670668
// See if we can propagate this shift into the input, this covers the trivial
671669
// cast of lshr(shl(x,c1),c2) as well as other more complex cases.
670+
bool IsLeftShift = I.getOpcode() == Instruction::Shl;
672671
if (I.getOpcode() != Instruction::AShr &&
673672
canEvaluateShifted(Op0, Op1C->getZExtValue(), IsLeftShift, *this, &I)) {
674673
LLVM_DEBUG(
@@ -693,118 +692,7 @@ Instruction *InstCombinerImpl::FoldShiftByConstant(Value *Op0, Constant *Op1,
693692
if (!Op0->hasOneUse())
694693
return nullptr;
695694

696-
// Fold shift2(trunc(shift1(x,c1)), c2) -> trunc(shift2(shift1(x,c1),c2))
697-
// If 'shift2' is an ashr, we would have to get the sign bit into a funny
698-
// place. Don't try to do this transformation in this case. Also, we
699-
// require that the input operand is a non-poison shift-by-constant so that we
700-
// have confidence that the shifts will get folded together. We could do this
701-
// xform in more cases, but it is unlikely to be profitable.
702-
Instruction *TrOp;
703-
const APInt *TrShiftAmt;
704-
if (IsLeftShift && match(Op0, m_Trunc(m_Instruction(TrOp))) &&
705-
match(TrOp, m_OneUse(m_Shift(m_Value(), m_APInt(TrShiftAmt)))) &&
706-
TrShiftAmt->ult(TrOp->getType()->getScalarSizeInBits())) {
707-
Type *SrcTy = TrOp->getType();
708-
709-
// Okay, we'll do this xform. Make the shift of shift.
710-
Constant *ShAmt = ConstantExpr::getZExt(Op1, SrcTy);
711-
// (shift2 (shift1 & 0x00FF), c2)
712-
Value *NSh = Builder.CreateBinOp(I.getOpcode(), TrOp, ShAmt, I.getName());
713-
714-
// For logical shifts, the truncation has the effect of making the high
715-
// part of the register be zeros. Emulate this by inserting an AND to
716-
// clear the top bits as needed. This 'and' will usually be zapped by
717-
// other xforms later if dead.
718-
unsigned SrcSize = SrcTy->getScalarSizeInBits();
719-
Constant *MaskV =
720-
ConstantInt::get(SrcTy, APInt::getLowBitsSet(SrcSize, TypeBits));
721-
722-
// The mask we constructed says what the trunc would do if occurring
723-
// between the shifts. We want to know the effect *after* the second
724-
// shift. We know that it is a logical shift by a constant, so adjust the
725-
// mask as appropriate.
726-
MaskV = ConstantExpr::get(I.getOpcode(), MaskV, ShAmt);
727-
// shift1 & 0x00FF
728-
Value *And = Builder.CreateAnd(NSh, MaskV, Op0->getName());
729-
// Return the value truncated to the interesting size.
730-
return new TruncInst(And, Ty);
731-
}
732-
733695
if (auto *Op0BO = dyn_cast<BinaryOperator>(Op0)) {
734-
// Turn ((X >> C) + Y) << C -> (X + (Y << C)) & (~0 << C)
735-
Value *V1;
736-
const APInt *CC;
737-
switch (Op0BO->getOpcode()) {
738-
default:
739-
break;
740-
case Instruction::Add:
741-
case Instruction::And:
742-
case Instruction::Or:
743-
case Instruction::Xor: {
744-
// These operators commute.
745-
// Turn (Y + (X >> C)) << C -> (X + (Y << C)) & (~0 << C)
746-
if (IsLeftShift && Op0BO->getOperand(1)->hasOneUse() &&
747-
match(Op0BO->getOperand(1), m_Shr(m_Value(V1), m_Specific(Op1)))) {
748-
Value *YS = // (Y << C)
749-
Builder.CreateShl(Op0BO->getOperand(0), Op1, Op0BO->getName());
750-
// (X + (Y << C))
751-
Value *X = Builder.CreateBinOp(Op0BO->getOpcode(), YS, V1,
752-
Op0BO->getOperand(1)->getName());
753-
unsigned Op1Val = Op1C->getLimitedValue(TypeBits);
754-
APInt Bits = APInt::getHighBitsSet(TypeBits, TypeBits - Op1Val);
755-
Constant *Mask = ConstantInt::get(Ty, Bits);
756-
return BinaryOperator::CreateAnd(X, Mask);
757-
}
758-
759-
// Turn (Y + ((X >> C) & CC)) << C -> ((X & (CC << C)) + (Y << C))
760-
Value *Op0BOOp1 = Op0BO->getOperand(1);
761-
if (IsLeftShift && Op0BOOp1->hasOneUse() &&
762-
match(Op0BOOp1, m_And(m_OneUse(m_Shr(m_Value(V1), m_Specific(Op1))),
763-
m_APInt(CC)))) {
764-
Value *YS = // (Y << C)
765-
Builder.CreateShl(Op0BO->getOperand(0), Op1, Op0BO->getName());
766-
// X & (CC << C)
767-
Value *XM = Builder.CreateAnd(
768-
V1, ConstantExpr::getShl(ConstantInt::get(Ty, *CC), Op1),
769-
V1->getName() + ".mask");
770-
return BinaryOperator::Create(Op0BO->getOpcode(), YS, XM);
771-
}
772-
LLVM_FALLTHROUGH;
773-
}
774-
775-
case Instruction::Sub: {
776-
// Turn ((X >> C) + Y) << C -> (X + (Y << C)) & (~0 << C)
777-
if (IsLeftShift && Op0BO->getOperand(0)->hasOneUse() &&
778-
match(Op0BO->getOperand(0), m_Shr(m_Value(V1), m_Specific(Op1)))) {
779-
Value *YS = // (Y << C)
780-
Builder.CreateShl(Op0BO->getOperand(1), Op1, Op0BO->getName());
781-
// (X + (Y << C))
782-
Value *X = Builder.CreateBinOp(Op0BO->getOpcode(), V1, YS,
783-
Op0BO->getOperand(0)->getName());
784-
unsigned Op1Val = Op1C->getLimitedValue(TypeBits);
785-
APInt Bits = APInt::getHighBitsSet(TypeBits, TypeBits - Op1Val);
786-
Constant *Mask = ConstantInt::get(Ty, Bits);
787-
return BinaryOperator::CreateAnd(X, Mask);
788-
}
789-
790-
// Turn (((X >> C)&CC) + Y) << C -> (X + (Y << C)) & (CC << C)
791-
if (IsLeftShift && Op0BO->getOperand(0)->hasOneUse() &&
792-
match(Op0BO->getOperand(0),
793-
m_And(m_OneUse(m_Shr(m_Value(V1), m_Specific(Op1))),
794-
m_APInt(CC)))) {
795-
Value *YS = // (Y << C)
796-
Builder.CreateShl(Op0BO->getOperand(1), Op1, Op0BO->getName());
797-
// X & (CC << C)
798-
Value *XM = Builder.CreateAnd(
799-
V1, ConstantExpr::getShl(ConstantInt::get(Ty, *CC), Op1),
800-
V1->getName() + ".mask");
801-
return BinaryOperator::Create(Op0BO->getOpcode(), XM, YS);
802-
}
803-
804-
break;
805-
}
806-
}
807-
808696
// If the operand is a bitwise operator with a constant RHS, and the
809697
// shift is the only use, we can pull it out of the shift.
810698
const APInt *Op0C;
@@ -820,20 +708,6 @@ Instruction *InstCombinerImpl::FoldShiftByConstant(Value *Op0, Constant *Op1,
820708
return BinaryOperator::Create(Op0BO->getOpcode(), NewShift, NewRHS);
821709
}
822710
}
823-
824-
// If the operand is a subtract with a constant LHS, and the shift
825-
// is the only use, we can pull it out of the shift.
826-
// This folds (shl (sub C1, X), C2) -> (sub (C1 << C2), (shl X, C2))
827-
if (IsLeftShift && Op0BO->getOpcode() == Instruction::Sub &&
828-
match(Op0BO->getOperand(0), m_APInt(Op0C))) {
829-
Constant *NewRHS = ConstantExpr::get(
830-
I.getOpcode(), cast<Constant>(Op0BO->getOperand(0)), Op1);
831-
832-
Value *NewShift = Builder.CreateShl(Op0BO->getOperand(1), Op1);
833-
NewShift->takeName(Op0BO);
834-
835-
return BinaryOperator::CreateSub(NewRHS, NewShift);
836-
}
837711
}
838712

839713
// If we have a select that conditionally executes some binary operator,
@@ -978,6 +852,129 @@ Instruction *InstCombinerImpl::visitShl(BinaryOperator &I) {
978852
return BinaryOperator::CreateShl(X, ConstantInt::get(Ty, AmtSum));
979853
}
980854

855+
// Fold shl(trunc(shift1(x,c1)), c2) -> trunc(shift2(shift1(x,c1),c2))
856+
// If 'shift2' is an ashr, we would have to get the sign bit into a funny
857+
// place. Don't try to do this transformation in this case. Also, we
858+
// require that the input operand is a non-poison shift-by-constant so that
859+
// we have confidence that the shifts will get folded together.
860+
Instruction *TrOp;
861+
const APInt *TrShiftAmt;
862+
if (match(Op0, m_Trunc(m_Instruction(TrOp))) &&
863+
match(TrOp, m_OneUse(m_Shift(m_Value(), m_APInt(TrShiftAmt)))) &&
864+
TrShiftAmt->ult(TrOp->getType()->getScalarSizeInBits())) {
865+
Type *SrcTy = TrOp->getType();
866+
867+
// Okay, we'll do this xform. Make the shift of shift.
868+
unsigned SrcSize = SrcTy->getScalarSizeInBits();
869+
Constant *ShAmt = ConstantInt::get(SrcTy, C->zext(SrcSize));
870+
871+
// (shift2 (shift1 & 0x00FF), c2)
872+
Value *NSh = Builder.CreateBinOp(I.getOpcode(), TrOp, ShAmt, I.getName());
873+
874+
// For logical shifts, the truncation has the effect of making the high
875+
// part of the register be zeros. Emulate this by inserting an AND to
876+
// clear the top bits as needed. This 'and' will usually be zapped by
877+
// other xforms later if dead.
878+
Constant *MaskV =
879+
ConstantInt::get(SrcTy, APInt::getLowBitsSet(SrcSize, BitWidth));
880+
881+
// The mask we constructed says what the trunc would do if occurring
882+
// between the shifts. We want to know the effect *after* the second
883+
// shift. We know that it is a logical shift by a constant, so adjust the
884+
// mask as appropriate.
885+
MaskV = ConstantExpr::get(I.getOpcode(), MaskV, ShAmt);
886+
// shift1 & 0x00FF
887+
Value *And = Builder.CreateAnd(NSh, MaskV, Op0->getName());
888+
// Return the value truncated to the interesting size.
889+
return new TruncInst(And, Ty);
890+
}
891+
892+
BinaryOperator *Op0BO;
893+
if (match(Op0, m_OneUse(m_BinOp(Op0BO)))) {
894+
// Turn ((X >> C) + Y) << C -> (X + (Y << C)) & (~0 << C)
895+
Value *V1;
896+
const APInt *CC;
897+
switch (Op0BO->getOpcode()) {
898+
default:
899+
break;
900+
case Instruction::Add:
901+
case Instruction::And:
902+
case Instruction::Or:
903+
case Instruction::Xor: {
904+
// These operators commute.
905+
// Turn (Y + (X >> C)) << C -> (X + (Y << C)) & (~0 << C)
906+
if (Op0BO->getOperand(1)->hasOneUse() &&
907+
match(Op0BO->getOperand(1), m_Shr(m_Value(V1), m_Specific(Op1)))) {
908+
Value *YS = // (Y << C)
909+
Builder.CreateShl(Op0BO->getOperand(0), Op1, Op0BO->getName());
910+
// (X + (Y << C))
911+
Value *X = Builder.CreateBinOp(Op0BO->getOpcode(), YS, V1,
912+
Op0BO->getOperand(1)->getName());
913+
unsigned Op1Val = C->getLimitedValue(BitWidth);
914+
APInt Bits = APInt::getHighBitsSet(BitWidth, BitWidth - Op1Val);
915+
Constant *Mask = ConstantInt::get(Ty, Bits);
916+
return BinaryOperator::CreateAnd(X, Mask);
917+
}
918+
919+
// Turn (Y + ((X >> C) & CC)) << C -> ((X & (CC << C)) + (Y << C))
920+
Value *Op0BOOp1 = Op0BO->getOperand(1);
921+
if (Op0BOOp1->hasOneUse() &&
922+
match(Op0BOOp1, m_And(m_OneUse(m_Shr(m_Value(V1), m_Specific(Op1))),
923+
m_APInt(CC)))) {
924+
Value *YS = // (Y << C)
925+
Builder.CreateShl(Op0BO->getOperand(0), Op1, Op0BO->getName());
926+
// X & (CC << C)
927+
Value *XM = Builder.CreateAnd(V1, ConstantInt::get(Ty, CC->shl(*C)),
928+
V1->getName() + ".mask");
929+
return BinaryOperator::Create(Op0BO->getOpcode(), YS, XM);
930+
}
931+
LLVM_FALLTHROUGH;
932+
}
933+
934+
case Instruction::Sub: {
935+
// Turn ((X >> C) + Y) << C -> (X + (Y << C)) & (~0 << C)
936+
if (Op0BO->getOperand(0)->hasOneUse() &&
937+
match(Op0BO->getOperand(0), m_Shr(m_Value(V1), m_Specific(Op1)))) {
938+
Value *YS = // (Y << C)
939+
Builder.CreateShl(Op0BO->getOperand(1), Op1, Op0BO->getName());
940+
// (X + (Y << C))
941+
Value *X = Builder.CreateBinOp(Op0BO->getOpcode(), V1, YS,
942+
Op0BO->getOperand(0)->getName());
943+
unsigned Op1Val = C->getLimitedValue(BitWidth);
944+
APInt Bits = APInt::getHighBitsSet(BitWidth, BitWidth - Op1Val);
945+
Constant *Mask = ConstantInt::get(Ty, Bits);
946+
return BinaryOperator::CreateAnd(X, Mask);
947+
}
948+
949+
// Turn (((X >> C)&CC) + Y) << C -> (X + (Y << C)) & (CC << C)
950+
if (Op0BO->getOperand(0)->hasOneUse() &&
951+
match(Op0BO->getOperand(0),
952+
m_And(m_OneUse(m_Shr(m_Value(V1), m_Specific(Op1))),
953+
m_APInt(CC)))) {
954+
Value *YS = // (Y << C)
955+
Builder.CreateShl(Op0BO->getOperand(1), Op1, Op0BO->getName());
956+
// X & (CC << C)
957+
Value *XM = Builder.CreateAnd(V1, ConstantInt::get(Ty, CC->shl(*C)),
958+
V1->getName() + ".mask");
959+
return BinaryOperator::Create(Op0BO->getOpcode(), XM, YS);
960+
}
961+
962+
break;
963+
}
964+
}
965+
966+
// If the operand is a subtract with a constant LHS, and the shift
967+
// is the only use, we can pull it out of the shift.
968+
// This folds (shl (sub C1, X), C) -> (sub (C1 << C), (shl X, C))
969+
if (Op0BO->getOpcode() == Instruction::Sub &&
970+
match(Op0BO->getOperand(0), m_APInt(C1))) {
971+
Constant *NewLHS = ConstantInt::get(Ty, C1->shl(*C));
972+
Value *NewShift = Builder.CreateShl(Op0BO->getOperand(1), Op1);
973+
NewShift->takeName(Op0BO);
974+
return BinaryOperator::CreateSub(NewLHS, NewShift);
975+
}
976+
}
977+
981978
// If the shifted-out value is known-zero, then this is a NUW shift.
982979
if (!I.hasNoUnsignedWrap() &&
983980
MaskedValueIsZero(Op0, APInt::getHighBitsSet(BitWidth, ShAmtC), 0,

0 commit comments

Comments
 (0)