[llvm] r221693 - LLVM incorrectly folds xor into select

Oliver Stannard oliver.stannard at arm.com
Thu Nov 13 07:01:51 PST 2014


The test case I committed and all of the ones you suggested are not affected
by this patch. I made a last-minute change to the test to make it more
robust, here is the original which is miscompiled without the patch:

  ; Do not fold the xor into the select
  define i32 @t15_5(i32 %p) {
  entry:
  ; ARM: mov     [[REG:r[0-9]+]], #2
  ; ARM: cmp     r0, #8
  ; ARM: movwgt  [[REG:r[0-9]+]], #1
  ; ARM: eor     r0, [[REG:r[0-9]+]], #1

  ; T2: movs    [[REG:r[0-9]+]], #2
  ; T2: cmp     [[REG:r[0-9]+]], #8
  ; T2: it      gt
  ; T2: movgt   [[REG:r[0-9]+]], #1
  ; T2: eor     r0, [[REG:r[0-9]+]], #1
    %cmp = icmp sgt i32 %p, 8
    %a = select i1 %cmp, i32 1, i32 2
    %xor = xor i32 %a, 1
    ret i32 %xor
  }

The problem is that isSetCCEquivalent checks for a SELECT_CC between values
that can be used for true and false, but the transformations that rely on
this assume that the values *are* being used as boolean values. This is not
always the case, on ARM (and other targets that use UndefinedBooleanContent)
every even value is considered to be false, so %a is accepted by
isSetCCEquivalent. I originally thought this only affects the XOR case, but
the optimisations for AND and OR can also cause miscompilations with
carefully chosen constants. I think the safest thing to do here is to modify
isSetCCEquivalent to never consider SELECT_CC when a target uses
UndefinedBooleanContent, and I have a patch up at
http://reviews.llvm.org/D6249 to implement this.

Oliver

> -----Original Message-----
> From: Jonathan Roelofs [mailto:jonathan at codesourcery.com]
> Sent: 11 November 2014 18:27
> To: Tim Northover; Oliver Stannard
> Cc: llvm-commits at cs.uiuc.edu
> Subject: Re: [llvm] r221693 - LLVM incorrectly folds xor into select
> 
> 
> 
> On 11/11/14 11:07 AM, Jonathan Roelofs wrote:
> >
> >
> > On 11/11/14 11:00 AM, Tim Northover wrote:
> >>>
> >>> Would you mind also adding tests for what you expect these two to
> be lowered as:
> >>>
> >>> define i32 @t15_2(i32 %p1, i32 %p2, i32 %p3) {
> >>> entry:
> >>>   %cmp = icmp sgt i32 %p1, 8
> >>>   %a = select i1 %cmp, i32 %p2, i32 %p3
> >>>   %xor = xor i32 %a, -1
> >>>   ret i32 %xor
> >>> }
> >>
> >> Isn't this the test that was already added?
> > No...
> >
> > %xor = xor i32 %a, -1
> >
> > vs
> >
> > %xor = xor i32 %a, 1
> >
> > Sorry I didn't call that out more explicitly.
> 
> One more, which I think the case you should actually be checking, given
> the
> setcc peephole that this patch is about:
> 
> define i32 @t15_4(i32 %p1, i32 %p2, i32 %p3) {
> entry:
>    %cmp = icmp sgt i32 %p1, 8
>    %notcmp = xor i1 %cmp, 1
>    %a = select i1 %notcmp, i32 %p2, i32 %p3
>    ret i32 %a
> }
> 
> Are there cases where the result of a setcc is not an i1?
> 
> 
> Jon
> 
> >
> >
> > Cheers,
> >
> > Jon
> >>
> >> Cheers.
> >>
> >> Tim.
> >>
> >
> 
> --
> Jon Roelofs
> jonathan at codesourcery.com
> CodeSourcery / Mentor Embedded








More information about the llvm-commits mailing list