/// nullptr.
MachineInstr *tryReplaceCopy(MachineInstr *MI) const;
+ /// Change the MachineInstr \p MI into the equivalent extend to 32 bit
+ /// register if it is safe to do so. Return the replacement instruction if
+ /// OK, otherwise return nullptr.
+ MachineInstr *tryReplaceExtend(unsigned New32BitOpcode,
+ MachineInstr *MI) const;
+
// Change the MachineInstr \p MI into an eqivalent 32 bit instruction if
// possible. Return the replacement instruction if OK, return nullptr
// otherwise.
// %ax = KILL %ax, implicit killed %eax
// RET 0, %ax
unsigned Opc = OrigMI->getOpcode(); (void)Opc;
- // These are the opcodes currently handled by the pass, if something
- // else will be added we need to ensure that new opcode has the same
- // properties.
- assert((Opc == X86::MOV8rm || Opc == X86::MOV16rm || Opc == X86::MOV8rr ||
- Opc == X86::MOV16rr) &&
- "Unexpected opcode.");
+ // These are the opcodes currently known to work with the code below, if
+ // something // else will be added we need to ensure that new opcode has the
+ // same properties.
+ if (Opc != X86::MOV8rm && Opc != X86::MOV16rm && Opc != X86::MOV8rr &&
+ Opc != X86::MOV16rr)
+ return false;
bool IsDefined = false;
for (auto &MO: OrigMI->implicit_operands()) {
return MIB;
}
+MachineInstr *FixupBWInstPass::tryReplaceExtend(unsigned New32BitOpcode,
+ MachineInstr *MI) const {
+ Register NewDestReg;
+ if (!getSuperRegDestIfDead(MI, NewDestReg))
+ return nullptr;
+
+ // Don't interfere with formation of CBW instructions which should be a
+ // shorter encoding than even the MOVSX32rr8. It's also immunte to partial
+ // merge issues on Intel CPUs.
+ if (MI->getOpcode() == X86::MOVSX16rr8 &&
+ MI->getOperand(0).getReg() == X86::AX &&
+ MI->getOperand(1).getReg() == X86::AL)
+ return nullptr;
+
+ // Safe to change the instruction.
+ MachineInstrBuilder MIB =
+ BuildMI(*MF, MI->getDebugLoc(), TII->get(New32BitOpcode), NewDestReg);
+
+ unsigned NumArgs = MI->getNumOperands();
+ for (unsigned i = 1; i < NumArgs; ++i)
+ MIB.add(MI->getOperand(i));
+
+ MIB.setMemRefs(MI->memoperands());
+
+ return MIB;
+}
+
MachineInstr *FixupBWInstPass::tryReplaceInstr(MachineInstr *MI,
MachineBasicBlock &MBB) const {
// See if this is an instruction of the type we are currently looking for.
// of the register.
return tryReplaceCopy(MI);
+ case X86::MOVSX16rr8:
+ return tryReplaceExtend(X86::MOVSX32rr8, MI);
+ case X86::MOVSX16rm8:
+ return tryReplaceExtend(X86::MOVSX32rm8, MI);
+ case X86::MOVZX16rr8:
+ return tryReplaceExtend(X86::MOVZX32rr8, MI);
+ case X86::MOVZX16rm8:
+ return tryReplaceExtend(X86::MOVZX32rm8, MI);
+
default:
// nothing to do here.
break;
}
; CHECK-LABEL: test_sdiv8:
-; CHECK: movsbw
+; CHECK: movsbl
; CHECK: idivb
define i8 @test_srem8(i8 %dividend, i8 %divisor) nounwind {
}
; CHECK-LABEL: test_srem8:
-; CHECK: movsbw
+; CHECK: movsbl
; CHECK: idivb
define i8 @test_udiv8(i8 %dividend, i8 %divisor) nounwind {
}
; CHECK-LABEL: test_udiv8:
-; CHECK: movzbw
+; CHECK: movzbl
; CHECK: divb
define i8 @test_urem8(i8 %dividend, i8 %divisor) nounwind {
}
; CHECK-LABEL: test_urem8:
-; CHECK: movzbw
+; CHECK: movzbl
; CHECK: divb
define i16 @test_sdiv16(i16 %dividend, i16 %divisor) nounwind {