Issue 87011
Summary [SLP] Missing sign extension of demoted type before zero extension
Labels new issue
Assignees
Reporter patrick-rivos
    LLVM IR:
```llvm ir
target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"
target triple = "riscv64-unknown-linux-gnu"

@h = global [16 x i64] zeroinitializer
@.str = constant [5 x i8] c"%lX\0A\00"

define i32 @main() #0 {
entry:
  %sext.0 = sext i8 0 to i32
  %sext.1 = sext i8 0 to i32

  %lshr.0 = lshr i32 0, %sext.0
  %lshr.1 = lshr i32 0, %sext.1

  %or.0 = or i32 %lshr.0, -1
  %or.1 = or i32 %lshr.1, 0

  %zext.0 = zext i32 %or.0 to i64
  %zext.1 = zext i32 %or.1 to i64

  store i64 %zext.0, ptr @h, align 8
  store i64 %zext.1, ptr getelementptr inbounds ([16 x i64], ptr @h, i64 0, i64 1), align 8

  %0 = load i64, ptr @h, align 8

  %call = tail call i32 (ptr, ...) @printf(ptr @.str, i64 %0)
  ret i32 0
}

declare i32 @printf(ptr, ...)

attributes #0 = { "target-features"="+64bit,+a,+v" }
```

SLP pass result:
``` llvm ir
; ModuleID = 'optimized.bc'
source_filename = "lto-works-reduced.ll"
target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"
target triple = "riscv64-unknown-linux-gnu"

@h = global [16 x i64] zeroinitializer
@.str = constant [5 x i8] c"%lX\0A\00"

define i32 @main() #0 {
entry:
  store <2 x i64> <i64 1, i64 0>, ptr @h, align 8
  %0 = load i64, ptr @h, align 8
  %call = tail call i32 (ptr, ...) @printf(ptr @.str, i64 %0)
  ret i32 0
}

declare i32 @printf(ptr, ...)

attributes #0 = { "target-features"="+64bit,+a,+v" }
```

Expected output: `FFFFFFFF`
SLP output: `1`

DemandedBits debug log:
```
DemandedBits: Root:   store i64 %zext.0, ptr @h, align 8
DemandedBits: Root:   store i64 %zext.1, ptr getelementptr inbounds ([16 x i64], ptr @h, i64 0, i64 1), align 8
DemandedBits: Root:   %call = tail call i32 (ptr, ...) @printf(ptr @.str, i64 %0)
DemandedBits: Root:   ret i32 0
DemandedBits: Visiting:   %call = tail call i32 (ptr, ...) @printf(ptr @.str, i64 %0) Alive Out: 0x0
DemandedBits: Visiting:   %0 = load i64, ptr @h, align 8 Alive Out: 0xffffffffffffffff
DemandedBits: Visiting:   %zext.1 = zext i32 %or.1 to i64 Alive Out: 0xffffffffffffffff
DemandedBits: Visiting:   %or.1 = or i32 %lshr.1, 0 Alive Out: 0xffffffff
DemandedBits: Visiting:   %lshr.1 = lshr i32 0, %sext.1 Alive Out: 0xffffffff
DemandedBits: Visiting:   %sext.1 = sext i8 0 to i32 Alive Out: 0xffffffff
DemandedBits: Visiting:   %zext.0 = zext i32 %or.0 to i64 Alive Out: 0xffffffffffffffff
DemandedBits: Visiting: %or.0 = or i32 %lshr.0, -1 Alive Out: 0xffffffff
DemandedBits: Visiting: %lshr.0 = lshr i32 0, %sext.0 Alive Out: 0x0
DemandedBits: Visiting: %sext.0 = sext i8 0 to i32 Alive Out: 0x0
```

What's happening:
```
[0, 0]
 |
sext.{0,1} -> [0, 0]
 |
lshr.{0,1} [0, 0] -> [0, 0]
 |
or.{0,1} [-1, 0]  -> [-1, 0] {-1 is identical to 1 since this reduced to i1}
 |
sext.{0,1} i32  -> [1, 0] {ZExt'd the i1 to i64}
```

The SLP pass determines that the MaxBitWidth is 1 and does not sign-extend to i32 before zero extending.

I think these are possible solutions:
1. Sign-extend to the original input datatype before ZExt ops where MaxBitWidth < `op->getSrcTy() bits` and the zext input `!KnownPositive`.
2. Restrict the MaxBitWidth to be at least `zext->getSrcTy() bits` for ops preceding the zext

SLP bug, so @alexey-bataev
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to