diff --git a/demos/rsrcProbe.apl b/demos/rsrcProbe.apl index 608b345..ebaf67d 100644 Binary files a/demos/rsrcProbe.apl and b/demos/rsrcProbe.apl differ diff --git a/src/llvm/lib/Target/W65816/W65816ISelLowering.cpp b/src/llvm/lib/Target/W65816/W65816ISelLowering.cpp index af05fc6..a57ba95 100644 --- a/src/llvm/lib/Target/W65816/W65816ISelLowering.cpp +++ b/src/llvm/lib/Target/W65816/W65816ISelLowering.cpp @@ -1336,6 +1336,14 @@ SDValue W65816TargetLowering::LowerSELECT_CC(SDValue Op, ISD::CondCode CC = cast(Op.getOperand(4))->get(); SDLoc DL(Op); + // Both arms the same value: no select. The i32 splits below make these + // -- a 0/1 boolean widened to i32 has 0 in both high halves -- and the + // DAG combiner never sees them, as the legalizer lowers each new i16 + // SELECT_CC at once. Left alone, each is a CMP, a branch to the next + // instruction and a spilled PHI. + if (TVal == FVal) + return TVal; + // i32 / i64 SELECT_CC. An i8/i16 result selects straight on the CMP/SBC // chain's flags (or on the equivalent i16 compare). An i32 result needs // two per-half selects and a glue value has only one consumer, so it diff --git a/src/llvm/lib/Target/W65816/W65816RegisterInfo.td b/src/llvm/lib/Target/W65816/W65816RegisterInfo.td index 01525bc..b29f5ff 100644 --- a/src/llvm/lib/Target/W65816/W65816RegisterInfo.td +++ b/src/llvm/lib/Target/W65816/W65816RegisterInfo.td @@ -50,10 +50,13 @@ def P : W65816Reg<8, "p">, DwarfRegNum<[8]>; // registers with cheap LDA/STA dp inter-register moves. This // relieves pressure on the single Acc16 register (A) so greedy // regalloc can succeed on functions with multiple simultaneously- -// live i16 vregs. Caller-save: callees may freely overwrite them, -// so regalloc spills around any call that might touch them. Their -// HWEncoding is never emitted (asmprinter translates IMGn references -// into LDA/STA dp with the right address). +// live i16 vregs. IMG0..IMG7 are caller-save: a call clobbers them, +// so regalloc spills around any call. IMG8..IMG15 are callee-saved: +// W65816ImgCalleeSave saves and restores them in any function that +// writes them, and callers keep values in them across calls, so hand +// asm called from C must not overwrite them without doing the same. +// Their HWEncoding is never emitted (asmprinter translates IMGn +// references into LDA/STA dp with the right address). // // Layout: IMG0..IMG7 at $D0..$DE (legacy slot block); IMG8..IMG15 // at $C0..$CE. Avoid stepping on user DP allocations below $C0. diff --git a/src/llvm/test/CodeGen/W65816/fp-cmp-const-int.ll b/src/llvm/test/CodeGen/W65816/fp-cmp-const-int.ll index e226fb2..baa35c4 100644 --- a/src/llvm/test/CodeGen/W65816/fp-cmp-const-int.ll +++ b/src/llvm/test/CodeGen/W65816/fp-cmp-const-int.ll @@ -70,6 +70,7 @@ define i16 @f_fabs_olt(float %x) { ; CHECK-NOT: jsl ; CHECK: and #0x7fff ; CHECK: cmp #0x4020 +; CHECK-NEXT: lda #0x1 ; CHECK-NEXT: bcc ; CHECK: rtl %a = call float @llvm.fabs.f32(float %x) @@ -84,6 +85,7 @@ define i16 @f_ogt0(float %x) { ; CHECK: adc #0xffff ; CHECK: adc #0xffff ; CHECK: cmp #0x7f80 +; CHECK-NEXT: lda #0x1 ; CHECK-NEXT: bcc ; CHECK: rtl %c = fcmp ogt float %x, 0.0 diff --git a/src/llvm/test/CodeGen/W65816/select-same-arms.ll b/src/llvm/test/CodeGen/W65816/select-same-arms.ll new file mode 100644 index 0000000..4ffd1a4 --- /dev/null +++ b/src/llvm/test/CodeGen/W65816/select-same-arms.ll @@ -0,0 +1,47 @@ +; A select whose two arms are the same value is that value: no compare, no +; branch. A 0/1 boolean widened to i32 (a returned bool, a zext to i32) is +; split into a select per half, and the high half's arms are both 0. The +; legalizer lowers each new i16 SELECT_CC at once, so the DAG combiner's +; same-arms fold never saw it: each one left a second compare of the value, +; a branch to the next instruction and a PHI spilled to a slot. +; +; RUN: llc -mtriple=w65816 -O2 < %s | FileCheck %s + +target triple = "w65816" + +@keys = external global [60 x i8] + +; One compare of the loaded byte, one branch on it. +define zeroext i1 @keyDown(i16 zeroext %key) { +; CHECK-LABEL: keyDown: +; CHECK: lda keys, x +; CHECK: bne .LBB0_3 +; CHECK-NOT: b{{eq|ne}} +; CHECK: rtl +entry: + %cmp = icmp ugt i16 %key, 59 + br i1 %cmp, label %return, label %if.end + +if.end: + %idx = zext nneg i16 %key to i32 + %p = getelementptr inbounds i8, ptr @keys, i32 %idx + %v = load i8, ptr %p, align 1 + %t = icmp ne i8 %v, 0 + br label %return + +return: + %r = phi i1 [ %t, %if.end ], [ false, %entry ] + ret i1 %r +} + +; The high half is the constant, the low half the one select. +define i32 @isZero32(i16 %a) { +; CHECK-LABEL: isZero32: +; CHECK: beq .LBB1_2 +; CHECK-NOT: b{{eq|ne}} +; CHECK: ldx #0x0 +; CHECK: rtl + %c = icmp eq i16 %a, 0 + %r = zext i1 %c to i32 + ret i32 %r +}