@@ -5997,36 +5997,64 @@ const SCEV *ScalarEvolution::createNodeForSelectOrPHIInstWithICmpInstCond(
5997
5997
return getUnknown(I);
5998
5998
}
5999
5999
6000
- const SCEV *ScalarEvolution::createNodeForSelectOrPHIViaUMinSeq(
6001
- Value *V, Value *Cond, Value *TrueVal, Value *FalseVal) {
6002
- // For now, only deal with i1-typed `select`s.
6003
- if (!V ->getType()->isIntegerTy(1) || !Cond->getType()->isIntegerTy(1) ||
6004
- !TrueVal ->getType()->isIntegerTy(1) ||
6005
- !FalseVal ->getType()->isIntegerTy(1))
6006
- return getUnknown(V );
6000
+ static Optional< const SCEV *>
6001
+ createNodeForSelectViaUMinSeq(ScalarEvolution *SE, const SCEV *CondExpr,
6002
+ const SCEV *TrueExpr, const SCEV *FalseExpr) {
6003
+ assert(CondExpr ->getType()->isIntegerTy(1) &&
6004
+ TrueExpr ->getType() == FalseExpr->getType() &&
6005
+ TrueExpr ->getType()->isIntegerTy(1) &&
6006
+ "Unexpected operands of a select." );
6007
6007
6008
6008
// i1 cond ? i1 x : i1 C --> C + (i1 cond ? (i1 x - i1 C) : i1 0)
6009
6009
// --> C + (umin_seq cond, x - C)
6010
6010
//
6011
6011
// i1 cond ? i1 C : i1 x --> C + (i1 cond ? i1 0 : (i1 x - i1 C))
6012
6012
// --> C + (i1 ~cond ? (i1 x - i1 C) : i1 0)
6013
6013
// --> C + (umin_seq ~cond, x - C)
6014
- if (isa<ConstantInt>(TrueVal) || isa<ConstantInt>(FalseVal)) {
6015
- const SCEV *CondExpr = getSCEV(Cond);
6016
- const SCEV *TrueExpr = getSCEV(TrueVal);
6017
- const SCEV *FalseExpr = getSCEV(FalseVal);
6018
- const SCEV *X, *C;
6019
- if (isa<ConstantInt>(TrueVal)) {
6020
- CondExpr = getNotSCEV(CondExpr);
6021
- X = FalseExpr;
6022
- C = TrueExpr;
6023
- } else {
6024
- X = TrueExpr;
6025
- C = FalseExpr;
6026
- }
6027
- return getAddExpr(
6028
- C, getUMinExpr(CondExpr, getMinusSCEV(X, C), /*Sequential=*/true));
6014
+
6015
+ // FIXME: while we can't legally model the case where both of the hands
6016
+ // are fully variable, we only require that the *difference* is constant.
6017
+ if (!isa<SCEVConstant>(TrueExpr) && !isa<SCEVConstant>(FalseExpr))
6018
+ return None;
6019
+
6020
+ const SCEV *X, *C;
6021
+ if (isa<SCEVConstant>(TrueExpr)) {
6022
+ CondExpr = SE->getNotSCEV(CondExpr);
6023
+ X = FalseExpr;
6024
+ C = TrueExpr;
6025
+ } else {
6026
+ X = TrueExpr;
6027
+ C = FalseExpr;
6029
6028
}
6029
+ return SE->getAddExpr(C, SE->getUMinExpr(CondExpr, SE->getMinusSCEV(X, C),
6030
+ /*Sequential=*/true));
6031
+ }
6032
+
6033
+ static Optional<const SCEV *> createNodeForSelectViaUMinSeq(ScalarEvolution *SE,
6034
+ Value *Cond,
6035
+ Value *TrueVal,
6036
+ Value *FalseVal) {
6037
+ if (!isa<ConstantInt>(TrueVal) && !isa<ConstantInt>(FalseVal))
6038
+ return None;
6039
+
6040
+ return createNodeForSelectViaUMinSeq(
6041
+ SE, SE->getSCEV(Cond), SE->getSCEV(TrueVal), SE->getSCEV(FalseVal));
6042
+ }
6043
+
6044
+ const SCEV *ScalarEvolution::createNodeForSelectOrPHIViaUMinSeq(
6045
+ Value *V, Value *Cond, Value *TrueVal, Value *FalseVal) {
6046
+ assert(Cond->getType()->isIntegerTy(1) && "Select condition is not an i1?");
6047
+ assert(TrueVal->getType() == FalseVal->getType() &&
6048
+ V->getType() == TrueVal->getType() &&
6049
+ "Types of select hands and of the result must match.");
6050
+
6051
+ // For now, only deal with i1-typed `select`s.
6052
+ if (!V->getType()->isIntegerTy(1))
6053
+ return getUnknown(V);
6054
+
6055
+ if (Optional<const SCEV *> S =
6056
+ createNodeForSelectViaUMinSeq(this, Cond, TrueVal, FalseVal))
6057
+ return *S;
6030
6058
6031
6059
return getUnknown(V);
6032
6060
}
0 commit comments