Skip to content

Commit 45e2c50

Browse files
authored
[M68k] Fix reverse BTST condition causing opposite failure/success logic (#153086)
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.
1 parent 4e6c88b commit 45e2c50

File tree

2 files changed

+64
-2
lines changed

2 files changed

+64
-2
lines changed

llvm/lib/Target/M68k/M68kISelLowering.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1666,8 +1666,8 @@ static SDValue getBitTestCondition(SDValue Src, SDValue BitNo, ISD::CondCode CC,
16661666

16671667
SDValue BTST = DAG.getNode(M68kISD::BTST, DL, MVT::i32, Src, BitNo);
16681668

1669-
// NOTE BTST sets CCR.Z flag
1670-
M68k::CondCode Cond = CC == ISD::SETEQ ? M68k::COND_NE : M68k::COND_EQ;
1669+
// NOTE BTST sets CCR.Z flag if bit is 0, same as AND with bitmask
1670+
M68k::CondCode Cond = CC == ISD::SETEQ ? M68k::COND_EQ : M68k::COND_NE;
16711671
return DAG.getNode(M68kISD::SETCC, DL, MVT::i8,
16721672
DAG.getConstant(Cond, DL, MVT::i8), BTST);
16731673
}

llvm/test/CodeGen/M68k/Bits/btst.ll

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2+
; RUN: llc < %s -mtriple=m68k-freestanding -verify-machineinstrs | FileCheck %s
3+
4+
define fastcc i16 @switch_to_btst(i16 %a) nounwind {
5+
; CHECK-LABEL: switch_to_btst:
6+
; CHECK: ; %bb.0: ; %entry
7+
; CHECK-NEXT: move.l %d0, %d1
8+
; CHECK-NEXT: and.l #65535, %d1
9+
; CHECK-NEXT: sub.l #11, %d1
10+
; CHECK-NEXT: bhi .LBB0_3
11+
; CHECK-NEXT: ; %bb.1: ; %entry
12+
; CHECK-NEXT: and.l #65535, %d0
13+
; CHECK-NEXT: move.l #3612, %d1
14+
; CHECK-NEXT: btst %d0, %d1
15+
; CHECK-NEXT: beq .LBB0_3
16+
; CHECK-NEXT: ; %bb.2: ; %match
17+
; CHECK-NEXT: moveq #1, %d0
18+
; CHECK-NEXT: rts
19+
; CHECK-NEXT: .LBB0_3: ; %no_match
20+
; CHECK-NEXT: moveq #0, %d0
21+
; CHECK-NEXT: rts
22+
entry:
23+
switch i16 %a, label %no_match [
24+
i16 11, label %match
25+
i16 10, label %match
26+
i16 9, label %match
27+
i16 4, label %match
28+
i16 3, label %match
29+
i16 2, label %match
30+
]
31+
32+
match:
33+
ret i16 1
34+
35+
no_match:
36+
ret i16 0
37+
}
38+
39+
define fastcc i16 @and_mask_to_btst(i8 %a, i8 %b) nounwind {
40+
; CHECK-LABEL: and_mask_to_btst:
41+
; CHECK: ; %bb.0:
42+
; CHECK-NEXT: and.l #7, %d1
43+
; CHECK-NEXT: btst %d1, %d0
44+
; CHECK-NEXT: beq .LBB1_1
45+
; CHECK-NEXT: ; %bb.2: ; %cond_false
46+
; CHECK-NEXT: moveq #0, %d0
47+
; CHECK-NEXT: rts
48+
; CHECK-NEXT: .LBB1_1: ; %cond_true
49+
; CHECK-NEXT: moveq #1, %d0
50+
; CHECK-NEXT: rts
51+
%33 = and i8 %b, 7
52+
%34 = shl nuw i8 1, %33
53+
%35 = and i8 %34, %a
54+
%.not = icmp eq i8 %35, 0
55+
br i1 %.not, label %cond_true, label %cond_false
56+
57+
cond_true:
58+
ret i16 1
59+
60+
cond_false:
61+
ret i16 0
62+
}

0 commit comments

Comments
 (0)