@@ -1223,6 +1223,33 @@ Instruction *InstCombinerImpl::foldSignBitTest(ICmpInst &I) {
1223
1223
X, ConstantInt::getNullValue (XTy));
1224
1224
}
1225
1225
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
+
1226
1253
// Handle icmp pred X, 0
1227
1254
Instruction *InstCombinerImpl::foldICmpWithZero (ICmpInst &Cmp) {
1228
1255
CmpInst::Predicate Pred = Cmp.getPredicate ();
@@ -1298,6 +1325,12 @@ Instruction *InstCombinerImpl::foldICmpWithZero(ICmpInst &Cmp) {
1298
1325
// eq/ne (mul X, Y)) with (icmp eq/ne X/Y) and if X/Y is known non-zero that
1299
1326
// will fold to a constant elsewhere.
1300
1327
}
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
+
1301
1334
return nullptr ;
1302
1335
}
1303
1336
@@ -5046,29 +5079,6 @@ static Instruction *foldICmpOrXX(ICmpInst &I, const SimplifyQuery &Q,
5046
5079
return nullptr ;
5047
5080
}
5048
5081
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
-
5072
5082
static Instruction *foldICmpXorXX (ICmpInst &I, const SimplifyQuery &Q,
5073
5083
InstCombinerImpl &IC) {
5074
5084
Value *Op0 = I.getOperand (0 ), *Op1 = I.getOperand (1 ), *A;
@@ -7892,11 +7902,6 @@ Instruction *InstCombinerImpl::visitICmpInst(ICmpInst &I) {
7892
7902
}
7893
7903
}
7894
7904
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
-
7900
7905
return Changed ? &I : nullptr ;
7901
7906
}
7902
7907
0 commit comments