llvm-project icon indicating copy to clipboard operation
llvm-project copied to clipboard

miscompile of a frozen poison by AArch64 backend

Open regehr opened this issue 2 years ago • 3 comments

Here's a slightly modified version of a function found in the LLVM test suite:

define i32 @f(i32 %0) {
  %2 = ashr i32 %0, 32
  %3 = freeze i32 %2
  %4 = ashr i32 %3, 3
  %5 = mul i32 %3, %4
  ret i32 %5
}

It's a bit of a pain to demonstrate how it gets miscompiled, so please bear with me. %2 is poison so then %3 is an arbitrary i32, %4 is an arbitrary i32 that has 4 signbits and then %5 is (%3 * (%3 >>a 3)). This function can return any i32 that satisfies this equation.

On the AArch64 side, this is the generated code:

f:
	asr	w8, w8, #3
	mul	w0, w8, w8
	ret

Notice that it multiplies the shifted value by itself, instead of multiplying the shifted value by the unshifted value, which is what the original code does. This leads to returning impossible values such as 0x4676cf69 that are not solutions to the equation above.

A correct backend can return a constant satisfying the equation (such as 0) or it could generate code similar to this that faithfully performs the math:

f:
	asr	w9, w8, #3
	mul	w0, w8, w9
	ret

cc @nunoplopes @ryan-berger @nbushehri @Hatsunespica

regehr avatar Oct 12 '22 16:10 regehr

@llvm/issue-subscribers-backend-aarch64

llvmbot avatar Oct 12 '22 16:10 llvmbot

SelectionDAG is correct. It's the translation to MachineIR where we lose the freeze and start propagating undef.

*** MachineFunction at end of ISel ***                                           
# Machine code for function f: IsSSA, TracksLiveness                             
                                                                                 
bb.0 (%ir-block.1):                                                              
  %2:gr32 = IMPLICIT_DEF                                                         
  %1:gr32 = COPY killed %2:gr32                                                  
  %3:gr32 = SAR32ri %1:gr32(tied-def 0), 3, implicit-def dead $eflags            
  %4:gr32 = IMUL32rr %1:gr32(tied-def 0), killed %3:gr32, implicit-def dead $eflags
  $eax = COPY %4:gr32                                                            
  RET 0, $eax                                                                    
                                                                                 
# End machine code for function f.  

topperc avatar Oct 12 '22 17:10 topperc

x86 is also the same:

f:                                      # @f
        sar     eax, 3
        imul    eax, eax
        ret

bcl5980 avatar Oct 14 '22 10:10 bcl5980