[LLVMdev] Cast to SCEVAddRecExpr

Nema, Ashutosh Ashutosh.Nema at amd.com
Wed Apr 1 03:06:40 PDT 2015


Thanks Sanjoy.

> To be pedantic, "var[i<<1]" is not an add recurrence, but "&var[i <<
> 1]" is an add recurrence.  I'll assume that's that you meant.
Yes, I meant the same.

> I think that is because in C, multiplication is nsw but left shift is
> not and so "i << 1" can legitimately sign-overflow but i * 2 cannot
> sign-overflow.  I'd venture a guess that this lets LLVM transform a
> sign-extend of an add-rec to an add-rec sign-extends.
I agree here, we want LLVM to transform sign-extend of add-rec to 
add-rec of sign extend in possible cases. Currently I don’t see LLVM is doing this.
i.e.:
(sext i32 addrec{2,+,2}<%for.body4> to i64)
Will convert it to:
addrec{(sext i32 '2' to i64), + , (sext i32 '2' to i64)} <%for.body4>

If this looks OK, I'll make changes and come up with a patch.

With sign-extend (SCEVSignExtendExpr) similarly we have to take care and 
handle other casts as well  (i.e. SCEVTruncateExpr, SCEVZeroExtendExpr).

Regards,
Ashutosh

-----Original Message-----
From: Sanjoy Das [mailto:sanjoy at playingwithpointers.com] 
Sent: Tuesday, March 31, 2015 9:41 AM
To: Nema, Ashutosh
Cc: Nick Lewycky; llvmdev at cs.uiuc.edu
Subject: Re: [LLVMdev] Cast to SCEVAddRecExpr

On Mon, Mar 30, 2015 at 8:47 PM, Nema, Ashutosh <Ashutosh.Nema at amd.com> wrote:
> Sorry typo in test case, Please ignore previous mail.
>
> Consider below case:
>
> for (j=1; j < itr; j++) {
>      - - - -
>      for (i=1; i < itr; i++) {
>      {
>        temp=  var[i << 1];
>         - - - - -
>      }
> }
>
> In the above example, we are unable to get "SCEVAddRecExpr" for "var[i  << 1]"

To be pedantic, "var[i<<1]" is not an add recurrence, but "&var[i <<
1]" is an add recurrence.  I'll assume that's that you meant.

If I run the following example through opt -analyze -scalar-evolution:

define void @x(i1* %c, i64* %ptr) {
 entry:
  br label %loop

 loop:
  %i = phi i64 [ 0, %entry ], [ %i.inc, %loop ]
  %i.inc = add i64 %i, 1
  %d = shl i64 %i.inc, 1
  %gep = getelementptr i64, i64* %ptr, i64 %d
  %cc = load volatile i1, i1* %c
  br i1 %cc, label %exit, label %loop

 exit:
  ret void
}


I get the SCEV -->  {(16 + %ptr),+,16}<%loop> for %gep.  So SCEV /can/
interpret i<<1 as i*2 under some specific circumstances.

Going back to your original question:

> Instead if I change "var[i << 1]" to "var[i * 2]" then I'm getting "SCEVAddRecExpr".

I think that is because in C, multiplication is nsw but left shift is
not and so "i << 1" can legitimately sign-overflow but i * 2 cannot
sign-overflow.  I'd venture a guess that this lets LLVM transform a
sign-extend of an add-rec to an add-rec sign-extends.

Caveat: I have not looked at the C specification to determine that
left shifts are allowed to sign-overflow.  I concluded that left
shifts are not nsw by looking at the llvm IR emitted by clang (the
left shift generated from "i << 1" is not marked nsw).

-- Sanjoy




More information about the llvm-dev mailing list