@@ -1172,75 +1172,75 @@ static Instruction *moveAddAfterMinMax(IntrinsicInst *II,
11721172 : BinaryOperator::CreateNUWAdd (NewMinMax, Add->getOperand (1 ));
11731173}
11741174
1175- // Try canonicalize min/max(x << shamt, c<<shamt) into max(x, c) << shamt
1176- static Instruction *moveShiftAfterMinMax (IntrinsicInst *II, InstCombiner::BuilderTy &Builder) {
1175+ // Try canonicalize max(max(X,C1) binop C2, C3) -> max(X binop C2, C3)
1176+ static Instruction *moveShiftAfterMinMax (IntrinsicInst *II,
1177+ InstCombiner::BuilderTy &Builder) {
11771178 Intrinsic::ID MinMaxID = II->getIntrinsicID ();
1178- assert ((MinMaxID == Intrinsic::smax || MinMaxID == Intrinsic::smin ||
1179- MinMaxID == Intrinsic::umax || MinMaxID == Intrinsic::umin) &&
1180- " Expected a min or max intrinsic" );
1181-
1179+ assert (isa<MinMaxIntrinsic>(II) &&
1180+ " Expected a min or max intrinsic" );
1181+
11821182 Value *Op0 = II->getArgOperand (0 ), *Op1 = II->getArgOperand (1 );
11831183 Value *InnerMax;
11841184 const APInt *C;
1185- if (!match (Op0, m_OneUse (m_BinOp (m_Value (InnerMax), m_APInt (C)))) ||
1185+ if (!match (Op0, m_OneUse (m_BinOp (m_Value (InnerMax), m_APInt (C)))) ||
11861186 !match (Op1, m_APInt (C)))
1187- return nullptr ;
1188-
1189- auto * BinOpInst = cast<BinaryOperator>(Op0);
1187+ return nullptr ;
1188+
1189+ auto * BinOpInst = cast<BinaryOperator>(Op0);
11901190 Instruction::BinaryOps BinOp = BinOpInst->getOpcode ();
1191- Value *X;
1191+
11921192 InnerMax = BinOpInst->getOperand (0 );
1193- // std::cout<< InnerMax->dump() <<std::endl;
1194- if (!match (InnerMax,m_OneUse (m_Intrinsic<Intrinsic::umax>(m_Value (X),m_APInt (C))))){
1195- if (!match (InnerMax,m_OneUse (m_Intrinsic<Intrinsic::smax>(m_Value (X),m_APInt (C))))){
1196- if (!match (InnerMax,m_OneUse (m_Intrinsic<Intrinsic::umin>(m_Value (X),m_APInt (C))))){
1197- if (!match (InnerMax,m_OneUse (m_Intrinsic<Intrinsic::smin>(m_Value (X),m_APInt (C))))){
1198- return nullptr ;
1199- }}}}
1200-
1201- auto *InnerMaxInst = cast<IntrinsicInst>(InnerMax);
12021193
1203- bool IsSigned = MinMaxID == Intrinsic::smax || MinMaxID == Intrinsic::smin;
1204- if ((IsSigned && !BinOpInst->hasNoSignedWrap ()) ||
1205- (!IsSigned && !BinOpInst->hasNoUnsignedWrap ()))
1206- return nullptr ;
1194+ auto *InnerMinMaxInst = dyn_cast<MinMaxIntrinsic>(BinOpInst->getOperand (0 ));
1195+
1196+ if (!InnerMinMaxInst || !InnerMinMaxInst->hasOneUse ())
1197+ return nullptr ;
1198+
1199+ bool IsSigned = InnerMinMaxInst->isSigned ();
1200+ if (InnerMinMaxInst->getIntrinsicID () != MinMaxID)
1201+ return nullptr ;
1202+
1203+ if ((IsSigned && !BinOpInst->hasNoSignedWrap ()) ||
1204+ (!IsSigned && !BinOpInst->hasNoUnsignedWrap ()))
1205+ return nullptr ;
12071206
12081207 // Check if BinOp is a left shift
12091208 if (BinOp != Instruction::Shl) {
12101209 return nullptr ;
12111210 }
12121211
1213- APInt C2=llvm::dyn_cast<llvm::ConstantInt>(BinOpInst->getOperand (1 ))->getValue () ;
1214- APInt C3=llvm::dyn_cast<llvm::ConstantInt>(II->getArgOperand (1 ))->getValue ();
1215- APInt C1= llvm::dyn_cast<llvm::ConstantInt>(InnerMaxInst ->getOperand (1 ))->getValue ();
1212+ APInt C2 =llvm::dyn_cast<llvm::ConstantInt>(BinOpInst->getOperand (1 ))->getValue ();
1213+ APInt C3 =llvm::dyn_cast<llvm::ConstantInt>(II->getArgOperand (1 ))->getValue ();
1214+ APInt C1 = llvm::dyn_cast<llvm::ConstantInt>(InnerMinMaxInst ->getOperand (1 ))->getValue ();
12161215
12171216 // Compute C1 * 2^C2
12181217 APInt Two = APInt (C2.getBitWidth (), 2 );
1219- APInt Pow2C2 = Two.shl (C2); // 2^C2
1218+ APInt Pow2C2 = Two.shl (C2); // 2^C2
12201219 APInt C1TimesPow2C2 = C1 * Pow2C2; // C1 * 2^C2
12211220
12221221 // Check C3 >= C1 * 2^C2
12231222 if (C3.ult (C1TimesPow2C2)) {
12241223 return nullptr ;
12251224 }
12261225
1227- // Create new x binop c2
1228- Value *NewBinOp = Builder.CreateBinOp (BinOp, InnerMaxInst->getOperand (0 ), BinOpInst->getOperand (1 ) );
1229-
1230- // Create new min/max intrinsic with new binop and c3
1231-
1232- if (IsSigned){
1233- cast<Instruction>(NewBinOp) -> setHasNoSignedWrap (true );
1234- cast<Instruction>(NewBinOp) -> setHasNoUnsignedWrap (false );
1235- }else {
1236- cast<Instruction>(NewBinOp) -> setHasNoUnsignedWrap (true );
1237- cast<Instruction>(NewBinOp) -> setHasNoSignedWrap (false );
1226+ // Create new x binop c2
1227+ Value *NewBinOp = Builder.CreateBinOp (BinOp, InnerMinMaxInst->getOperand (0 ),
1228+ BinOpInst->getOperand (1 ));
1229+
1230+ // Create new min/max intrinsic with new binop and c3
1231+ if (auto *NewBinInst = dyn_cast<Instruction>(NewBinOp))
1232+ if (IsSigned) {
1233+ cast<Instruction>(NewBinOp)->setHasNoSignedWrap (true );
1234+ cast<Instruction>(NewBinOp)->setHasNoUnsignedWrap (false );
1235+ } else {
1236+ cast<Instruction>(NewBinOp)->setHasNoUnsignedWrap (true );
1237+ cast<Instruction>(NewBinOp)->setHasNoSignedWrap (false );
12381238 }
1239-
12401239
12411240 // Get the intrinsic function for MinMaxID
12421241 Type *Ty = II->getType ();
1243- Function *MinMaxFn = Intrinsic::getDeclaration (II->getModule (), MinMaxID, {Ty});
1242+ Function *MinMaxFn =
1243+ Intrinsic::getDeclaration (II->getModule (), MinMaxID, {Ty});
12441244
12451245 // Create new min/max intrinsic: MinMaxID(NewBinOp, C3) (not inserted)
12461246 Value *Args[] = {NewBinOp, Op1};
@@ -1249,6 +1249,8 @@ static Instruction *moveShiftAfterMinMax(IntrinsicInst *II, InstCombiner::Builde
12491249 return NewMax;
12501250}
12511251
1252+
1253+
12521254// / Match a sadd_sat or ssub_sat which is using min/max to clamp the value.
12531255Instruction *InstCombinerImpl::matchSAddSubSat (IntrinsicInst &MinMax1) {
12541256 Type *Ty = MinMax1.getType ();
0 commit comments