| ; Verify constant propagation of 64-bit extract operations. The internal left |
| ; shift used to position the bitfield must use unsigned arithmetic to avoid |
| ; undefined behavior when high bits in the source value cause signed overflow. |
| ; RUN: llc -mtriple=hexagon -O2 < %s | FileCheck %s |
| |
| target triple = "hexagon" |
| |
| @g0 = common global i64 0, align 8 |
| @g1 = common global i64 0, align 8 |
| |
| ; extractup(0xC00000, 15, 8): extract 15 unsigned bits at offset 8. |
| ; The source value 0xC00000 has bit 23 set (outside the [8,23) extraction |
| ; window), which triggers a left shift of the value by 41 that would overflow |
| ; int64_t. Bits [22:8] = 0x4000 = 16384. |
| define void @test_extractup() #0 { |
| ; CHECK-LABEL: test_extractup: |
| ; CHECK: 16384 |
| ; CHECK-NOT: = extractu |
| entry: |
| %0 = call i64 @llvm.hexagon.S2.extractup(i64 12582912, i32 15, i32 8) |
| store i64 %0, ptr @g0, align 8 |
| ret void |
| } |
| |
| ; extractp(0xC00000, 15, 8): extract 15 signed bits at offset 8. |
| ; Bits [22:8] = 0x4000; bit 14 of the 15-bit field is set (sign bit), |
| ; so the result is sign-extended to -16384. |
| define void @test_extractp() #0 { |
| ; CHECK-LABEL: test_extractp: |
| ; CHECK: -16384 |
| ; CHECK-NOT: = extract |
| entry: |
| %0 = call i64 @llvm.hexagon.S4.extractp(i64 12582912, i32 15, i32 8) |
| store i64 %0, ptr @g1, align 8 |
| ret void |
| } |
| |
| declare i64 @llvm.hexagon.S2.extractup(i64, i32, i32) #1 |
| declare i64 @llvm.hexagon.S4.extractp(i64, i32, i32) #1 |
| |
| attributes #0 = { nounwind "less-precise-fpmad"="false" "frame-pointer"="all" } |
| attributes #1 = { nounwind readnone } |