@@ -6019,6 +6019,42 @@ const SCEV *ScalarEvolution::createNodeFromSelectLikePHI(PHINode *PN) {
60196019 return nullptr;
60206020}
60216021
6022+ /// Returns SCEV for the first operand of a phi if all phi operands have
6023+ /// identical opcodes and operands
6024+ /// eg.
6025+ /// a: %add = %a + %b
6026+ /// br %c
6027+ /// b: %add1 = %a + %b
6028+ /// br %c
6029+ /// c: %phi = phi [%add, a], [%add1, b]
6030+ /// scev(%phi) => scev(%add)
6031+ const SCEV *
6032+ ScalarEvolution::createNodeForPHIWithIdenticalOperands(PHINode *PN) {
6033+ BinaryOperator *CommonInst = nullptr;
6034+ // Check if instructions are identical.
6035+ for (Value *Incoming : PN->incoming_values()) {
6036+ auto *IncomingInst = dyn_cast<BinaryOperator>(Incoming);
6037+ if (!IncomingInst)
6038+ return nullptr;
6039+ if (CommonInst) {
6040+ if (!CommonInst->isIdenticalToWhenDefined(IncomingInst))
6041+ return nullptr; // Not identical, give up
6042+ } else {
6043+ // Remember binary operator
6044+ CommonInst = IncomingInst;
6045+ }
6046+ }
6047+ if (!CommonInst)
6048+ return nullptr;
6049+
6050+ // Check if SCEV exprs for instructions are identical.
6051+ const SCEV *CommonSCEV = getSCEV(CommonInst);
6052+ bool SCEVExprsIdentical =
6053+ all_of(drop_begin(PN->incoming_values()),
6054+ [this, CommonSCEV](Value *V) { return CommonSCEV == getSCEV(V); });
6055+ return SCEVExprsIdentical ? CommonSCEV : nullptr;
6056+ }
6057+
60226058const SCEV *ScalarEvolution::createNodeForPHI(PHINode *PN) {
60236059 if (const SCEV *S = createAddRecFromPHI(PN))
60246060 return S;
@@ -6030,6 +6066,9 @@ const SCEV *ScalarEvolution::createNodeForPHI(PHINode *PN) {
60306066 /*UseInstrInfo=*/true, /*CanUseUndef=*/false}))
60316067 return getSCEV(V);
60326068
6069+ if (const SCEV *S = createNodeForPHIWithIdenticalOperands(PN))
6070+ return S;
6071+
60336072 if (const SCEV *S = createNodeFromSelectLikePHI(PN))
60346073 return S;
60356074
0 commit comments