#define DEBUG_TYPE "delay-slot-filler"
#include "Sparc.h"
+#include "SparcSubtarget.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
/// layout, etc.
///
TargetMachine &TM;
+ const SparcSubtarget *Subtarget;
static char ID;
Filler(TargetMachine &tm)
- : MachineFunctionPass(ID), TM(tm) { }
+ : MachineFunctionPass(ID), TM(tm),
+ Subtarget(&TM.getSubtarget<SparcSubtarget>()) {
+ }
virtual const char *getPassName() const {
return "SPARC Delay Slot Filler";
bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
bool Changed = false;
+ const TargetInstrInfo *TII = TM.getInstrInfo();
+
for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ) {
MachineBasicBlock::iterator MI = I;
++I;
continue;
}
+ if (!Subtarget->isV9() &&
+ (MI->getOpcode() == SP::FCMPS || MI->getOpcode() == SP::FCMPD
+ || MI->getOpcode() == SP::FCMPQ)) {
+ BuildMI(MBB, I, MI->getDebugLoc(), TII->get(SP::NOP));
+ Changed = true;
+ continue;
+ }
+
// If MI has no delay slot, skip.
if (!MI->hasDelaySlot())
continue;
++FilledSlots;
Changed = true;
- const TargetInstrInfo *TII = TM.getInstrInfo();
if (D == MBB.end())
BuildMI(MBB, I, MI->getDebugLoc(), TII->get(SP::NOP));
else
// Floating-point Compare Instructions, p. 148
// Note: the 2nd template arg is different for these guys.
// Note 2: the result of a FCMP is not available until the 2nd cycle
-// after the instr is retired, but there is no interlock. This behavior
-// is modelled with a forced noop after the instruction.
+// after the instr is retired, but there is no interlock in Sparc V8.
+// This behavior is modeled with a forced noop after the instruction in
+// DelaySlotFiller.
+
let Defs = [FCC] in {
def FCMPS : F3_3c<2, 0b110101, 0b001010001,
(outs), (ins FPRegs:$src1, FPRegs:$src2),
- "fcmps $src1, $src2\n\tnop",
+ "fcmps $src1, $src2",
[(SPcmpfcc f32:$src1, f32:$src2)]>;
def FCMPD : F3_3c<2, 0b110101, 0b001010010,
(outs), (ins DFPRegs:$src1, DFPRegs:$src2),
- "fcmpd $src1, $src2\n\tnop",
+ "fcmpd $src1, $src2",
[(SPcmpfcc f64:$src1, f64:$src2)]>;
def FCMPQ : F3_3c<2, 0b110101, 0b001010011,
(outs), (ins QFPRegs:$src1, QFPRegs:$src2),
- "fcmpq $src1, $src2\n\tnop",
+ "fcmpq $src1, $src2",
[(SPcmpfcc f128:$src1, f128:$src2)]>,
Requires<[HasHardQuad]>;
}
entry:
;V8-LABEL: test_select_int_fcc:
;V8: fcmps
+;V8-NEXT: nop
;V8: {{fbe|fbne}}
;V9-LABEL: test_select_int_fcc:
;V9: fcmps
+;V9-NEXT-NOT: nop
;V9-NOT: {{fbe|fbne}}
;V9: mov{{e|ne}} %fcc0
%0 = fcmp une float %f, 0.000000e+00
entry:
;V8-LABEL: test_select_dfp_fcc:
;V8: fcmpd
+;V8-NEXT: nop
;V8: {{fbne|fbe}}
;V9-LABEL: test_select_dfp_fcc:
;V9: fcmpd
+;V9-NEXT-NOT: nop
;V9-NOT: {{fbne|fbe}}
;V9: fmovd{{e|ne}} %fcc0
%0 = fcmp une double %f, 0.000000e+00
; HARD-LABEL: f128_compare
; HARD: fcmpq
+; HARD-NEXT: nop
; SOFT-LABEL: f128_compare
; SOFT: _Q_cmp