Dan Salvato b09b05a83e
[M68k] Fix incorrect boolean content type (#152572)
M68k's SETCC instruction (`scc`) distinctly fills the destination byte
with all 1s. If boolean contents are set to `ZeroOrOneBooleanContent`,
LLVM can mistakenly think the destination holds `0x01` instead of `0xff`
and emit broken code as a result. This change corrects the boolean
content type to `ZeroOrNegativeOneBooleanContent`.

For example, this IR:

```llvm
define dso_local signext range(i8 0, 2) i8 @testBool(i32 noundef %a) local_unnamed_addr #0 {
entry:
  %cmp = icmp eq i32 %a, 4660
  %. = zext i1 %cmp to i8
  ret i8 %.
}
```

would previously build as:

```asm
testBool:                               ; @testBool
	cmpi.l	#4660, (4,%sp)
	seq	%d0
	and.l	#255, %d0
	rts
```

Notice the `zext` is erroneously not clearing the low bits, and thus the
register returns with 255 instead of 1. This patch fixes the issue:

```asm
testBool:                               ; @testBool
	cmpi.l	#4660, (4,%sp)
	seq	%d0
	and.l	#1, %d0
	rts
```

Most of the tests containing `scc` suffered from the same value error as
described above, so those tests have been updated to match the new
output (which also logically corrects them).
2025-08-12 08:46:41 -07:00

137 lines
4.3 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
; RUN: llc < %s -mtriple=m68k-linux -mcpu=M68020 --verify-machineinstrs | FileCheck %s
define internal void @select_i32(i32 %self, ptr nonnull %value) {
; CHECK-LABEL: select_i32:
; CHECK: .cfi_startproc
; CHECK-NEXT: ; %bb.0: ; %start
; CHECK-NEXT: suba.l #4, %sp
; CHECK-NEXT: .cfi_def_cfa_offset -8
; CHECK-NEXT: movem.l %d2, (0,%sp) ; 8-byte Folded Spill
; CHECK-NEXT: cmpi.l #0, (8,%sp)
; CHECK-NEXT: move.w %ccr, %d2
; CHECK-NEXT: sne %d1
; CHECK-NEXT: move.l (12,%sp), %d0
; CHECK-NEXT: move.w %d2, %ccr
; CHECK-NEXT: bne .LBB0_2
; CHECK-NEXT: ; %bb.1: ; %start
; CHECK-NEXT: and.l #255, %d1
; CHECK-NEXT: and.l #1, %d1
; CHECK-NEXT: cmpi.l #0, %d1
; CHECK-NEXT: bne .LBB0_3
; CHECK-NEXT: .LBB0_2: ; %null
; CHECK-NEXT: suba.l %a0, %a0
; CHECK-NEXT: move.l %d0, (%a0)
; CHECK-NEXT: .LBB0_3: ; %exit
; CHECK-NEXT: movem.l (0,%sp), %d2 ; 8-byte Folded Reload
; CHECK-NEXT: adda.l #4, %sp
; CHECK-NEXT: rts
start:
%2 = icmp eq i32 %self, 0
%3 = select i1 %2, i32 0, i32 1
switch i32 %3, label %exit [
i32 0, label %nonnull
i32 1, label %null
]
nonnull: ; preds = %start
store ptr %value, ptr null, align 2
br label %exit
null: ; preds = %start
store ptr %value, ptr null, align 2
br label %exit
exit: ; preds = %nonnull, %null
ret void
}
define internal void @select_i16(i16 %self, ptr nonnull %value) {
; CHECK-LABEL: select_i16:
; CHECK: .cfi_startproc
; CHECK-NEXT: ; %bb.0: ; %start
; CHECK-NEXT: suba.l #4, %sp
; CHECK-NEXT: .cfi_def_cfa_offset -8
; CHECK-NEXT: movem.l %d2, (0,%sp) ; 8-byte Folded Spill
; CHECK-NEXT: cmpi.w #0, (10,%sp)
; CHECK-NEXT: move.w %ccr, %d2
; CHECK-NEXT: sne %d1
; CHECK-NEXT: move.l (12,%sp), %d0
; CHECK-NEXT: move.w %d2, %ccr
; CHECK-NEXT: bne .LBB1_2
; CHECK-NEXT: ; %bb.1: ; %start
; CHECK-NEXT: and.l #255, %d1
; CHECK-NEXT: and.w #1, %d1
; CHECK-NEXT: cmpi.w #0, %d1
; CHECK-NEXT: bne .LBB1_3
; CHECK-NEXT: .LBB1_2: ; %null
; CHECK-NEXT: suba.l %a0, %a0
; CHECK-NEXT: move.l %d0, (%a0)
; CHECK-NEXT: .LBB1_3: ; %exit
; CHECK-NEXT: movem.l (0,%sp), %d2 ; 8-byte Folded Reload
; CHECK-NEXT: adda.l #4, %sp
; CHECK-NEXT: rts
start:
%2 = icmp eq i16 %self, 0
%3 = select i1 %2, i16 0, i16 1
switch i16 %3, label %exit [
i16 0, label %nonnull
i16 1, label %null
]
nonnull: ; preds = %start
store ptr %value, ptr null, align 2
br label %exit
null: ; preds = %start
store ptr %value, ptr null, align 2
br label %exit
exit: ; preds = %nonnull, %null
ret void
}
define internal void @select_i8(i8 %self, ptr nonnull %value) {
; CHECK-LABEL: select_i8:
; CHECK: .cfi_startproc
; CHECK-NEXT: ; %bb.0: ; %start
; CHECK-NEXT: suba.l #4, %sp
; CHECK-NEXT: .cfi_def_cfa_offset -8
; CHECK-NEXT: movem.l %d2, (0,%sp) ; 8-byte Folded Spill
; CHECK-NEXT: cmpi.b #0, (11,%sp)
; CHECK-NEXT: move.w %ccr, %d2
; CHECK-NEXT: sne %d1
; CHECK-NEXT: move.l (12,%sp), %d0
; CHECK-NEXT: move.w %d2, %ccr
; CHECK-NEXT: bne .LBB2_2
; CHECK-NEXT: ; %bb.1: ; %start
; CHECK-NEXT: and.b #1, %d1
; CHECK-NEXT: cmpi.b #0, %d1
; CHECK-NEXT: bne .LBB2_3
; CHECK-NEXT: .LBB2_2: ; %null
; CHECK-NEXT: suba.l %a0, %a0
; CHECK-NEXT: move.l %d0, (%a0)
; CHECK-NEXT: .LBB2_3: ; %exit
; CHECK-NEXT: movem.l (0,%sp), %d2 ; 8-byte Folded Reload
; CHECK-NEXT: adda.l #4, %sp
; CHECK-NEXT: rts
start:
%2 = icmp eq i8 %self, 0
%3 = select i1 %2, i8 0, i8 1
switch i8 %3, label %exit [
i8 0, label %nonnull
i8 1, label %null
]
nonnull: ; preds = %start
store ptr %value, ptr null, align 2
br label %exit
null: ; preds = %start
store ptr %value, ptr null, align 2
br label %exit
exit: ; preds = %nonnull, %null
ret void
}