llvm.org GIT mirror llvm / a70a8a0
ScalarEvolution: Add URem support In LLVM IR the following code: %r = urem <ty> %t, %b is equivalent to: %q = udiv <ty> %t, %b %s = mul <ty> nuw %q, %b %r = sub <ty> nuw %t, %q ; (t / b) * b + (t % b) = t As UDiv, Mul and Sub are already supported by SCEV, URem can be implemented with minimal effort this way. Note: While SRem and SDiv are also related this way, SCEV does not provides SDiv yet. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@306695 91177308-0d34-0410-b5e6-96231b3b80d8 Alexandre Isoard 2 years ago
4 changed file(s) with 64 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
12431243 }
12441244 const SCEV *getUDivExpr(const SCEV *LHS, const SCEV *RHS);
12451245 const SCEV *getUDivExactExpr(const SCEV *LHS, const SCEV *RHS);
1246 const SCEV *getURemExpr(const SCEV *LHS, const SCEV *RHS);
12461247 const SCEV *getAddRecExpr(const SCEV *Start, const SCEV *Step, const Loop *L,
12471248 SCEV::NoWrapFlags Flags);
12481249 const SCEV *getAddRecExpr(SmallVectorImpl &Operands,
29322932 // Okay, it looks like we really DO need an mul expr. Check to see if we
29332933 // already have one, otherwise create a new one.
29342934 return getOrCreateMulExpr(Ops, Flags);
2935 }
2936
2937 /// Represents an unsigned remainder expression based on unsigned division.
2938 const SCEV *ScalarEvolution::getURemExpr(const SCEV *LHS,
2939 const SCEV *RHS) {
2940 assert(getEffectiveSCEVType(LHS->getType()) ==
2941 getEffectiveSCEVType(RHS->getType()) &&
2942 "SCEVURemExpr operand types don't match!");
2943
2944 // TODO:
2945 // - short circuit '%a = %x urem %x --> 0' (why is it not done for udiv?)
2946 // - short circuit '%a = %x urem 0 --> %a' (same as for udiv)
2947 // - update upper-bound and lower-bound cache for the final result
2948 // (or improve how subtraction is estimated)
2949
2950 // Short-circuit easy cases
2951 if (const SCEVConstant *RHSC = dyn_cast(RHS))
2952 if (RHSC->getValue()->equalsInt(1))
2953 return getZero(LHS->getType()); // X urem 1 --> 0
2954
2955 const SCEV *UDiv = getUDivExpr(LHS, RHS);
2956 const SCEV *Mult = getMulExpr(UDiv, RHS, SCEV::FlagNUW);
2957 return getMinusSCEV(LHS, Mult, SCEV::FlagNUW);
29352958 }
29362959
29372960 /// Get a canonical unsigned division expression, or something simpler if
40944117 case Instruction::Sub:
40954118 case Instruction::Mul:
40964119 case Instruction::UDiv:
4120 case Instruction::URem:
40974121 case Instruction::And:
40984122 case Instruction::Or:
40994123 case Instruction::AShr:
54155439 }
54165440 case Instruction::UDiv:
54175441 return getUDivExpr(getSCEV(BO->LHS), getSCEV(BO->RHS));
5442 case Instruction::URem:
5443 return getURemExpr(getSCEV(BO->LHS), getSCEV(BO->RHS));
54185444 case Instruction::Sub: {
54195445 SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap;
54205446 if (BO->Op)
0 ; RUN: opt < %s -scalar-evolution -analyze | FileCheck %s
1
2
3 define void @foo([7 x i8]* %a) {
4 entry:
5 br label %bb
6
7 bb:
8 %idx = phi i64 [ 0, %entry ], [ %idx.incr, %bb ]
9 %i = udiv i64 %idx, 7
10 %j = urem i64 %idx, 7
11 %a.ptr = getelementptr [7 x i8], [7 x i8]* %a, i64 %i, i64 %j
12 ; CHECK: %a.ptr
13 ; CHECK-NEXT: --> {%a,+,1}<%bb>
14 %val = load i8, i8* %a.ptr
15 %idx.incr = add i64 %idx, 1
16 %test = icmp ne i64 %idx.incr, 35
17 br i1 %test, label %bb, label %exit
18
19 exit:
20 ret void
21 }
0 ; RUN: opt < %s -scalar-evolution -analyze | FileCheck %s
1
2 define i8 @foo(i8 %a) {
3 %t0 = urem i8 %a, 27
4 ; CHECK: %t0
5 ; CHECK-NEXT: --> ((-27 * (%a /u 27)) + %a)
6 ret i8 %t0
7 }
8
9 define i8 @bar(i8 %a) {
10 %t1 = urem i8 %a, 1
11 ; CHECK: %t1
12 ; CHECK-NEXT: --> 0
13 ret i8 %t1
14 }