
Given the test case: ```llvm define fastcc i16 @testbtst(i16 %a) nounwind { entry: switch i16 %a, label %no [ i16 11, label %yes i16 10, label %yes i16 9, label %yes i16 4, label %yes i16 3, label %yes i16 2, label %yes ] yes: ret i16 1 no: ret i16 0 } ``` We currently get this result: ```asm testbtst: ; @testbtst ; %bb.0: ; %entry move.l %d0, %d1 and.l #65535, %d1 sub.l #11, %d1 bhi .LBB0_3 ; %bb.1: ; %entry and.l #65535, %d0 move.l #3612, %d1 btst %d0, %d1 bne .LBB0_3 ; <------- Erroneous condition ; %bb.2: ; %yes moveq #1, %d0 rts .LBB0_3: ; %no moveq #0, %d0 rts ``` The cause of this is a line that explicitly reverses the `btst` condition code. But on M68k, `btst` sets condition codes the same as `and` with a bitmask, meaning `EQ` indicates failure (bit is zero) and not success, so the condition does not need to be reversed. In my testing, I've only been able to get switch statements to lower to `btst`, so I wasn't able to explicitly test other options for lowering. But (if possible to trigger) I believe they have the same logical error. For example, in `LowerAndToBTST()`, a comment specifies that it's lowering a case where the `and` result is compared against zero, which means the corresponding `btst` condition should also not be reversed. This patch simply flips the ternary expression in `getBitTestCondition()` to match the ISD condition code with the same M68k code, instead of the opposite.
63 lines
1.6 KiB
LLVM
63 lines
1.6 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
|
; RUN: llc < %s -mtriple=m68k-freestanding -verify-machineinstrs | FileCheck %s
|
|
|
|
define fastcc i16 @switch_to_btst(i16 %a) nounwind {
|
|
; CHECK-LABEL: switch_to_btst:
|
|
; CHECK: ; %bb.0: ; %entry
|
|
; CHECK-NEXT: move.l %d0, %d1
|
|
; CHECK-NEXT: and.l #65535, %d1
|
|
; CHECK-NEXT: sub.l #11, %d1
|
|
; CHECK-NEXT: bhi .LBB0_3
|
|
; CHECK-NEXT: ; %bb.1: ; %entry
|
|
; CHECK-NEXT: and.l #65535, %d0
|
|
; CHECK-NEXT: move.l #3612, %d1
|
|
; CHECK-NEXT: btst %d0, %d1
|
|
; CHECK-NEXT: beq .LBB0_3
|
|
; CHECK-NEXT: ; %bb.2: ; %match
|
|
; CHECK-NEXT: moveq #1, %d0
|
|
; CHECK-NEXT: rts
|
|
; CHECK-NEXT: .LBB0_3: ; %no_match
|
|
; CHECK-NEXT: moveq #0, %d0
|
|
; CHECK-NEXT: rts
|
|
entry:
|
|
switch i16 %a, label %no_match [
|
|
i16 11, label %match
|
|
i16 10, label %match
|
|
i16 9, label %match
|
|
i16 4, label %match
|
|
i16 3, label %match
|
|
i16 2, label %match
|
|
]
|
|
|
|
match:
|
|
ret i16 1
|
|
|
|
no_match:
|
|
ret i16 0
|
|
}
|
|
|
|
define fastcc i16 @and_mask_to_btst(i8 %a, i8 %b) nounwind {
|
|
; CHECK-LABEL: and_mask_to_btst:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: and.l #7, %d1
|
|
; CHECK-NEXT: btst %d1, %d0
|
|
; CHECK-NEXT: beq .LBB1_1
|
|
; CHECK-NEXT: ; %bb.2: ; %cond_false
|
|
; CHECK-NEXT: moveq #0, %d0
|
|
; CHECK-NEXT: rts
|
|
; CHECK-NEXT: .LBB1_1: ; %cond_true
|
|
; CHECK-NEXT: moveq #1, %d0
|
|
; CHECK-NEXT: rts
|
|
%33 = and i8 %b, 7
|
|
%34 = shl nuw i8 1, %33
|
|
%35 = and i8 %34, %a
|
|
%.not = icmp eq i8 %35, 0
|
|
br i1 %.not, label %cond_true, label %cond_false
|
|
|
|
cond_true:
|
|
ret i16 1
|
|
|
|
cond_false:
|
|
ret i16 0
|
|
}
|