@@ -1223,6 +1223,33 @@ Instruction *InstCombinerImpl::foldSignBitTest(ICmpInst &I) {
12231223 X, ConstantInt::getNullValue (XTy));
12241224}
12251225
1226+ // / Combine away instructions providing they are still equivalent when compared
1227+ // / against 0. i.e do they have any bits set.
1228+ static Value *combineAwayHasAnyBitsSetChain (Value *V,
1229+ InstCombiner::BuilderTy &Builder) {
1230+ auto *I = dyn_cast<Instruction>(V);
1231+ if (!I || I->getOpcode () != Instruction::Or || !I->hasOneUse ())
1232+ return nullptr ;
1233+
1234+ // Remove the shl in or(shl(x, y), z) so long as the shl is nuw or nsw.
1235+ Value *A, *B;
1236+ if (match (I, m_c_Or (m_CombineOr (m_NSWShl (m_Value (A), m_Value ()),
1237+ m_NUWShl (m_Value (A), m_Value ())),
1238+ m_Value (B))))
1239+ return Builder.CreateOr (A, B);
1240+
1241+ // Look deeper into the chain of or's.
1242+ Value *Op0 = I->getOperand (0 );
1243+ if (auto *NOp = combineAwayHasAnyBitsSetChain (Op0, Builder))
1244+ Op0 = NOp;
1245+ Value *Op1 = I->getOperand (1 );
1246+ if (auto *NOp = combineAwayHasAnyBitsSetChain (Op1, Builder))
1247+ Op1 = NOp;
1248+ if (Op0 != I->getOperand (0 ) || Op1 != I->getOperand (1 ))
1249+ return Builder.CreateOr (Op0, Op1);
1250+ return nullptr ;
1251+ }
1252+
12261253// Handle icmp pred X, 0
12271254Instruction *InstCombinerImpl::foldICmpWithZero (ICmpInst &Cmp) {
12281255 CmpInst::Predicate Pred = Cmp.getPredicate ();
@@ -1298,6 +1325,12 @@ Instruction *InstCombinerImpl::foldICmpWithZero(ICmpInst &Cmp) {
12981325 // eq/ne (mul X, Y)) with (icmp eq/ne X/Y) and if X/Y is known non-zero that
12991326 // will fold to a constant elsewhere.
13001327 }
1328+
1329+ // icmp eq/ne or(shl(a), b), 0 -> icmp eq/ne or(a, b), 0
1330+ if (ICmpInst::isEquality (Pred))
1331+ if (auto *Res = combineAwayHasAnyBitsSetChain (Cmp.getOperand (0 ), Builder))
1332+ return new ICmpInst (Pred, Res, Cmp.getOperand (1 ));
1333+
13011334 return nullptr ;
13021335}
13031336
@@ -5046,29 +5079,6 @@ static Instruction *foldICmpOrXX(ICmpInst &I, const SimplifyQuery &Q,
50465079 return nullptr ;
50475080}
50485081
5049- static Value *foldShiftAwayFromOrChain (Instruction &I,
5050- InstCombiner::BuilderTy &Builder) {
5051- if (I.getOpcode () != Instruction::Or)
5052- return nullptr ;
5053- Value *A, *B;
5054- if (match (&I, m_c_Or (m_CombineOr (m_NSWShl (m_Value (A), m_Value ()),
5055- m_NUWShl (m_Value (A), m_Value ())),
5056- m_Value (B))))
5057- return Builder.CreateOr (A, B);
5058-
5059- Value *Op0 = I.getOperand (0 );
5060- if (isa<Instruction>(Op0))
5061- if (auto *X = foldShiftAwayFromOrChain (*cast<Instruction>(Op0), Builder))
5062- Op0 = X;
5063- Value *Op1 = I.getOperand (1 );
5064- if (isa<Instruction>(Op1))
5065- if (auto *X = foldShiftAwayFromOrChain (*cast<Instruction>(Op1), Builder))
5066- Op1 = X;
5067- if (Op0 != I.getOperand (0 ) || Op1 != I.getOperand (1 ))
5068- return Builder.CreateOr (Op0, Op1);
5069- return nullptr ;
5070- }
5071-
50725082static Instruction *foldICmpXorXX (ICmpInst &I, const SimplifyQuery &Q,
50735083 InstCombinerImpl &IC) {
50745084 Value *Op0 = I.getOperand (0 ), *Op1 = I.getOperand (1 ), *A;
@@ -7892,11 +7902,6 @@ Instruction *InstCombinerImpl::visitICmpInst(ICmpInst &I) {
78927902 }
78937903 }
78947904
7895- // icmp eq/ne or(shl(a), b), 0 -> icmp eq/ne or(a, b)
7896- if (I.isEquality () && match (Op1, m_Zero ()) && isa<Instruction>(Op0))
7897- if (auto *Res = foldShiftAwayFromOrChain (*cast<Instruction>(Op0), Builder))
7898- return new ICmpInst (I.getPredicate (), Res, Op1);
7899-
79007905 return Changed ? &I : nullptr ;
79017906}
79027907
0 commit comments