Skip to content

shift/zext-related miscompile by aarch64 backend #55833

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
regehr opened this issue Jun 2, 2022 · 2 comments
Closed

shift/zext-related miscompile by aarch64 backend #55833

regehr opened this issue Jun 2, 2022 · 2 comments

Comments

@regehr
Copy link
Contributor

regehr commented Jun 2, 2022

here's a function:

define i64 @f(i64) {
  %2 = lshr i64 %0, 32
  %3 = shl i64 %2, 16
  %4 = trunc i64 %3 to i32
  %5 = ashr exact i32 %4, 16
  %6 = zext i32 %5 to i64
  ret i64 %6
}

alive2 and the x86-64 backend agree that f(0x0000800000000000) -> 0x00000000ffff8000

using this reasoning:

i64 %2 = #x0000000000008000 (32768)
i64 %3 = #x0000000080000000 (2147483648)
i32 %4 = #x80000000 (2147483648, -2147483648)
i32 %5 = #xffff8000 (4294934528, -32768)
i64 %6 = #x00000000ffff8000 (4294934528)

but separately, it's easy to see that since the last instruction is a zext, the high part of the result must contain zeroes (unless there's been a poison-related problem, but it doesn't look like there has been).

here's what we get from the aarch64 backend in llvm 14 and also top-of-tree:

Johns-MacBook-Pro:~ regehr$ ~/llvm-project/for-alive/bin/llc foo.ll -o -
	.section	__TEXT,__text,regular,pure_instructions
	.build_version macos, 12, 0
	.globl	_f                              ; -- Begin function f
	.p2align	2
_f:                                     ; @f
	.cfi_startproc
; %bb.0:
	sbfx	x0, x0, #32, #16
	ret
	.cfi_endproc
                                        ; -- End function
.subsections_via_symbols
Johns-MacBook-Pro:~ regehr$ 

this ends up with a result where all the high bits are set:

Johns-MacBook-Pro:~ regehr$ cat foo.c
#include <stdio.h>

unsigned long f(unsigned long);

int main(void) {
  printf("%lx\n", f(0x0000800000000000ULL));
}
Johns-MacBook-Pro:~ regehr$ ~/llvm-project/for-alive/bin/llc foo.ll && clang foo.c foo.s && ./a.out
ffffffffffff8000
Johns-MacBook-Pro:~ regehr$ 

cc @ornata @nunoplopes @ryan-berger @nbushehri @zhengyang92 @aqjune @Hatsunespica

@llvmbot
Copy link
Member

llvmbot commented Jun 2, 2022

@llvm/issue-subscribers-backend-aarch64

@davemgreen
Copy link
Collaborator

This looks like a conflict between the selection code in AArch64DAGToDAGISel::tryBitfieldExtractOp and isDef32 used in the zext patterns, meaning it misses a mov w0, w0 that is needed to zero-extend the higher bits.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants