Index: llvm/lib/Target/M680x0/M680x0AsmPrinter.h =================================================================== --- /dev/null +++ llvm/lib/Target/M680x0/M680x0AsmPrinter.h @@ -0,0 +1,63 @@ +//===-- M680x0AsmPrinter.h - M680x0 LLVM Assembly Printer -------- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file contains M680x0 assembler printer declarations. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_M680X0_M680X0ASMPRINTER_H +#define LLVM_LIB_TARGET_M680X0_M680X0ASMPRINTER_H + +#include "M680x0MCInstLower.h" +#include "M680x0TargetMachine.h" + +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Target/TargetMachine.h" + +namespace llvm { +class MCStreamer; +class MachineInstr; +class MachineBasicBlock; +class Module; +class raw_ostream; + +class M680x0Subtarget; +class M680x0MachineFunctionInfo; + +class LLVM_LIBRARY_VISIBILITY M680x0AsmPrinter : public AsmPrinter { + + void EmitInstrWithMacroNoAT(const MachineInstr *MI); + +public: + const M680x0Subtarget *Subtarget; + const M680x0MachineFunctionInfo *MMFI; + std::unique_ptr MCInstLowering; + + explicit M680x0AsmPrinter(TargetMachine &TM, + std::unique_ptr Streamer) + : AsmPrinter(TM, std::move(Streamer)) { + Subtarget = static_cast(TM).getSubtargetImpl(); + } + + StringRef getPassName() const override { return "M680x0 Assembly Printer"; } + + virtual bool runOnMachineFunction(MachineFunction &MF) override; + + void emitInstruction(const MachineInstr *MI) override; + void emitFunctionBodyStart() override; + void emitFunctionBodyEnd() override; + void emitStartOfAsmFile(Module &M) override; + void emitEndOfAsmFile(Module &M) override; +}; +} // namespace llvm + +#endif Index: llvm/lib/Target/M680x0/M680x0AsmPrinter.cpp =================================================================== --- /dev/null +++ llvm/lib/Target/M680x0/M680x0AsmPrinter.cpp @@ -0,0 +1,100 @@ +//===-- M680x0AsmPrinter.cpp - M680x0 LLVM Assembly Printer -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file contains a printer that converts from our internal representation +/// of machine-dependent LLVM code to GAS-format M680x0 assembly language. +/// +//===----------------------------------------------------------------------===// + +// TODO #33 make it print Motorola asm + +#include "M680x0AsmPrinter.h" + +#include "M680x0.h" +#include "M680x0InstrInfo.h" +#include "M680x0MachineFunction.h" + +#include "MCTargetDesc/M680x0InstPrinter.h" +#include "MCTargetDesc/M680x0BaseInfo.h" + +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/Twine.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Mangler.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstBuilder.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetOptions.h" +#include + +using namespace llvm; + +#define DEBUG_TYPE "m680x0-asm-printer" + +bool M680x0AsmPrinter::runOnMachineFunction(MachineFunction &MF) { + MMFI = MF.getInfo(); + MCInstLowering = std::make_unique(MF, *this); + AsmPrinter::runOnMachineFunction(MF); + return true; +} + +void M680x0AsmPrinter::emitInstruction(const MachineInstr *MI) { + switch (MI->getOpcode()) { + default: { + if (MI->isPseudo()) { + LLVM_DEBUG(dbgs() << "Pseudo opcode(" << MI->getOpcode() + << ") found in EmitInstruction()\n"); + llvm_unreachable("Cannot proceed"); + } + break; + } + case M680x0::TAILJMPj: + case M680x0::TAILJMPq: + // Lower these as normal, but add some comments. + OutStreamer->AddComment("TAILCALL"); + break; + } + + MCInst TmpInst0; + MCInstLowering->Lower(MI, TmpInst0); + OutStreamer->emitInstruction(TmpInst0, getSubtargetInfo()); +} + +void M680x0AsmPrinter::emitFunctionBodyStart() { + // TODO #33 +} + +void M680x0AsmPrinter::emitFunctionBodyEnd() { + // TODO #33 +} + +void M680x0AsmPrinter::emitStartOfAsmFile(Module &M) { + OutStreamer->emitSyntaxDirective(); +} + +void M680x0AsmPrinter::emitEndOfAsmFile(Module &M) {} + +extern "C" void LLVMInitializeM680x0AsmPrinter() { + RegisterAsmPrinter X(TheM680x0Target); +} Index: llvm/lib/Target/M680x0/M680x0MCInstLower.h =================================================================== --- /dev/null +++ llvm/lib/Target/M680x0/M680x0MCInstLower.h @@ -0,0 +1,56 @@ +//===-- M680x0MCInstLower.h - Lower MachineInstr to MCInst -----*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file contains code to lower M680x0 MachineInstrs to their +/// corresponding MCInst records. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_M680X0_M680X0MCINSTLOWER_H +#define LLVM_LIB_TARGET_M680X0_M680X0MCINSTLOWER_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/MachineOperand.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/Support/Compiler.h" + +namespace llvm { +class MCContext; +class MCInst; +class MCOperand; +class MachineInstr; +class MachineFunction; +class M680x0AsmPrinter; + +/// This class is used to lower an MachineInstr into an MCInst. +class M680x0MCInstLower { + typedef MachineOperand::MachineOperandType MachineOperandType; + MCContext &Ctx; + MachineFunction &MF; + const TargetMachine &TM; + const MCAsmInfo &MAI; + M680x0AsmPrinter &AsmPrinter; + +public: + M680x0MCInstLower(MachineFunction &MF, M680x0AsmPrinter &AP); + + /// Lower an MO_GlobalAddress or MO_ExternalSymbol operand to an MCSymbol. + MCSymbol *GetSymbolFromOperand(const MachineOperand &MO) const; + + MCOperand LowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym) const; + + Optional LowerOperand(const MachineInstr *MI, + const MachineOperand &MO) const; + + void Lower(const MachineInstr *MI, MCInst &OutMI) const; +}; +} // namespace llvm + +#endif Index: llvm/lib/Target/M680x0/M680x0MCInstLower.cpp =================================================================== --- /dev/null +++ llvm/lib/Target/M680x0/M680x0MCInstLower.cpp @@ -0,0 +1,182 @@ +//===-- M680x0MCInstLower.cpp - M680x0 MachineInstr to MCInst ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file contains code to lower M680x0 MachineInstrs to their +/// corresponding MCInst records. +/// +//===----------------------------------------------------------------------===// + +#include "M680x0MCInstLower.h" + +#include "M680x0AsmPrinter.h" +#include "M680x0InstrInfo.h" + +#include "MCTargetDesc/M680x0BaseInfo.h" + +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineOperand.h" +#include "llvm/IR/Mangler.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" + +using namespace llvm; + +#define DEBUG_TYPE "m68k-mc-inst-lower" + +M680x0MCInstLower::M680x0MCInstLower(MachineFunction &MF, M680x0AsmPrinter &AP) + : Ctx(MF.getContext()), MF(MF), TM(MF.getTarget()), MAI(*TM.getMCAsmInfo()), + AsmPrinter(AP) {} + +MCSymbol * +M680x0MCInstLower::GetSymbolFromOperand(const MachineOperand &MO) const { + assert((MO.isGlobal() || MO.isSymbol() || MO.isMBB()) && + "Isn't a symbol reference"); + + const auto& TT = TM.getTargetTriple(); + if (MO.isGlobal() && TT.isOSBinFormatELF()) + return AsmPrinter.getSymbolPreferLocal(*MO.getGlobal()); + + const DataLayout &DL = MF.getDataLayout(); + + MCSymbol *Sym = nullptr; + SmallString<128> Name; + StringRef Suffix; + + if (!Suffix.empty()) + Name += DL.getPrivateGlobalPrefix(); + + if (MO.isGlobal()) { + const GlobalValue *GV = MO.getGlobal(); + AsmPrinter.getNameWithPrefix(Name, GV); + } else if (MO.isSymbol()) { + Mangler::getNameWithPrefix(Name, MO.getSymbolName(), DL); + } else if (MO.isMBB()) { + assert(Suffix.empty()); + Sym = MO.getMBB()->getSymbol(); + } + + Name += Suffix; + if (!Sym) + Sym = Ctx.getOrCreateSymbol(Name); + + return Sym; +} + +MCOperand M680x0MCInstLower::LowerSymbolOperand(const MachineOperand &MO, + MCSymbol *Sym) const { + // FIXME We would like an efficient form for this, so we don't have to do a + // lot of extra uniquing. This fixme is originally from X86 + const MCExpr *Expr = nullptr; + MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None; + + switch (MO.getTargetFlags()) { + default: + llvm_unreachable("Unknown target flag on GV operand"); + case M680x0II::MO_NO_FLAG: + case M680x0II::MO_ABSOLUTE_ADDRESS: + case M680x0II::MO_PC_RELATIVE_ADDRESS: + break; + case M680x0II::MO_GOTPCREL: + RefKind = MCSymbolRefExpr::VK_GOTPCREL; + break; + case M680x0II::MO_GOT: + RefKind = MCSymbolRefExpr::VK_GOT; + break; + case M680x0II::MO_GOTOFF: + RefKind = MCSymbolRefExpr::VK_GOTOFF; + break; + case M680x0II::MO_PLT: + RefKind = MCSymbolRefExpr::VK_PLT; + break; + } + + if (!Expr) { + Expr = MCSymbolRefExpr::create(Sym, RefKind, Ctx); + } + + if (!MO.isJTI() && !MO.isMBB() && MO.getOffset()) { + Expr = MCBinaryExpr::createAdd( + Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx); + } + + return MCOperand::createExpr(Expr); +} + +Optional +M680x0MCInstLower::LowerOperand(const MachineInstr *MI, + const MachineOperand &MO) const { + switch (MO.getType()) { + default: + LLVM_DEBUG(MI->dump()); + llvm_unreachable("unknown operand type"); + case MachineOperand::MO_Register: + // Ignore all implicit register operands. + if (MO.isImplicit()) + return None; + return MCOperand::createReg(MO.getReg()); + case MachineOperand::MO_Immediate: + return MCOperand::createImm(MO.getImm()); + case MachineOperand::MO_MachineBasicBlock: + case MachineOperand::MO_GlobalAddress: + case MachineOperand::MO_ExternalSymbol: + return LowerSymbolOperand(MO, GetSymbolFromOperand(MO)); + case MachineOperand::MO_MCSymbol: + return LowerSymbolOperand(MO, MO.getMCSymbol()); + case MachineOperand::MO_JumpTableIndex: + return LowerSymbolOperand(MO, AsmPrinter.GetJTISymbol(MO.getIndex())); + case MachineOperand::MO_ConstantPoolIndex: + return LowerSymbolOperand(MO, AsmPrinter.GetCPISymbol(MO.getIndex())); + case MachineOperand::MO_BlockAddress: + return LowerSymbolOperand( + MO, AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress())); + case MachineOperand::MO_RegisterMask: + // Ignore call clobbers. + return None; + } +} + +void M680x0MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { + OutMI.setOpcode(MI->getOpcode()); + + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + Optional MCOp = LowerOperand(MI, MO); + + if (MCOp.hasValue() && MCOp.getValue().isValid()) + OutMI.addOperand(MCOp.getValue()); + } + + switch (OutMI.getOpcode()) { + + // TAILJMPj, TAILJMPq - Lower to the correct jump instructions. + case M680x0::TAILJMPj: + case M680x0::TAILJMPq: { + unsigned Opcode; + switch (OutMI.getOpcode()) { + default: + llvm_unreachable("Invalid opcode"); + case M680x0::TAILJMPj: + Opcode = M680x0::JMP32j; + break; + case M680x0::TAILJMPq: + Opcode = M680x0::BRA8; + break; + } + + MCOperand Saved = OutMI.getOperand(0); + OutMI = MCInst(); + OutMI.setOpcode(Opcode); + OutMI.addOperand(Saved); + break; + } + } +} Index: llvm/test/CodeGen/M680x0/ASM/Alloc/dyn_alloca_aligned.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/M680x0/ASM/Alloc/dyn_alloca_aligned.ll @@ -0,0 +1,9 @@ +; RUN: llc < %s -mtriple=m680x0-linux-gnu -verify-machineinstrs | FileCheck %s -check-prefix=x00 +define i32 @A(i32 %Size) { +; x00: sub.l %d1, %d0 +; x00-NEXT: and.l #-128 +; x00-NEXT: move.l %d0, %sp + %A = alloca i8, i32 %Size, align 128 + %A_addr = ptrtoint i8* %A to i32 + ret i32 %A_addr +} Index: llvm/test/CodeGen/M680x0/ASM/Arith/add-with-overflow.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/M680x0/ASM/Arith/add-with-overflow.ll @@ -0,0 +1,62 @@ +; RUN: llc < %s -mtriple=m680x0-linux -verify-machineinstrs | FileCheck %s -check-prefix=x00 + +declare {i32, i1} @llvm.sadd.with.overflow.i32(i32, i32) +declare {i32, i1} @llvm.uadd.with.overflow.i32(i32, i32) + + +; x00-LABEL: test5: +; x00: add.l +; x00-NEXT: bvs +define fastcc i32 @test5(i32 %v1, i32 %v2, i32* %X) nounwind { +entry: + %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 %v2) + %sum = extractvalue {i32, i1} %t, 0 + %obit = extractvalue {i32, i1} %t, 1 + br i1 %obit, label %overflow, label %normal + +normal: + store i32 0, i32* %X + br label %overflow + +overflow: + ret i32 %sum +} + +; x00-LABEL: test6: +; x00: add.l +; x00-NEXT: bcs +define fastcc i1 @test6(i32 %v1, i32 %v2, i32* %X) nounwind { +entry: + %t = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %v1, i32 %v2) + %sum = extractvalue {i32, i1} %t, 0 + %obit = extractvalue {i32, i1} %t, 1 + br i1 %obit, label %carry, label %normal + +normal: + store i32 0, i32* %X + br label %carry + +carry: + ret i1 false +} + +; x00-LABEL: test7: +; x00: move.l (4,%sp), %d0 +; x00-NEXT: add.l (8,%sp), %d0 +; x00-NEXT: scs %d1 +; x00-NEXT: rts +define {i32, i1} @test7(i32 %v1, i32 %v2) nounwind { + %t = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %v1, i32 %v2) + ret {i32, i1} %t +} + +; x00-LABEL: test10: +; x00: add.l #1 +; x00-NEXT: svs +; x00-NEXT: rts +define fastcc i1 @test10(i32 %x) nounwind { +entry: + %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %x, i32 1) + %obit = extractvalue {i32, i1} %t, 1 + ret i1 %obit +} Index: llvm/test/CodeGen/M680x0/ASM/Arith/add.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/M680x0/ASM/Arith/add.ll @@ -0,0 +1,84 @@ +; RUN: llc < %s -mtriple=m680x0-linux -verify-machineinstrs | FileCheck %s -check-prefix=x00 + +; x00-LABEL: test1: +; x00: move.l (12,%sp), %d0 +; x00-NEXT: add.l (4,%sp), %d0 +; x00-NEXT: move.l (8,%sp), %d1 +; x00-NEXT: rts + +define i64 @test1(i64 %A, i32 %B) nounwind { + %tmp12 = zext i32 %B to i64 + %tmp3 = shl i64 %tmp12, 32 + %tmp5 = add i64 %tmp3, %A + ret i64 %tmp5 +} + + +; x00-LABEL: test2: +; x00: move.l %d0, [[Addr:%a[0-7]]] +; x00-NEXT: add.l #128, ([[Addr]]) + +define void @test2(i32* inreg %a) nounwind { + %aa = load i32, i32* %a + %b = add i32 %aa, 128 + store i32 %b, i32* %a + ret void +} + + +; x00-LABEL: test2_fast: +; x00: add.l #128, (%a0) + +define fastcc void @test2_fast(i32* inreg %a) nounwind { + %aa = load i32, i32* %a + %b = add i32 %aa, 128 + store i32 %b, i32* %a + ret void +} + + +; x00-LABEL: test3: +; x00 move.l (%a0), %d0 +; x00-NEXT move.l #-2147483648, %d1 +; x00-NEXT add.l (4,%a0), %d1 +; x00-NEXT addx.l #0, %d0 +; x00-NEXT move.l %d1, (4,%a0) +; x00-NEXT move.l %d0, (%a0) +; x00-NEXT rts +define fastcc void @test3(i64* inreg %a) nounwind { + %aa = load i64, i64* %a + %b = add i64 %aa, 2147483648 + store i64 %b, i64* %a + ret void +} + + +; x00-LABEL: test4: +; x00 move.l #128, %d0 +; x00-NEXT add.l (4,%a0), %d0 +; x00-NEXT move.l (%a0), %d1 +; x00-NEXT move.l %d0, (4,%a0) +; x00-NEXT addx.l #0, %d1 +; x00-NEXT move.l %d1, (%a0) +; x00-NEXT rts +define fastcc void @test4(i64* inreg %a) nounwind { + %aa = load i64, i64* %a + %b = add i64 %aa, 128 + store i64 %b, i64* %a + ret void +} + +; x00-LABEL: test9: +; x00: sub.l #10 +; x00-NEXT: seq +; x00-NEXT: and.l +; x00-NEXT: sub.l +; x00-NEXT: move.l +; x00-NEXT: rts + +define fastcc i32 @test9(i32 %x, i32 %y) nounwind readnone { + %cmp = icmp eq i32 %x, 10 + %sub = sext i1 %cmp to i32 + %cond = add i32 %sub, %y + ret i32 %cond +} Index: llvm/test/CodeGen/M680x0/ASM/Arith/divide-by-constant.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/M680x0/ASM/Arith/divide-by-constant.ll @@ -0,0 +1,127 @@ +; RUN: llc < %s -mtriple=m680x0-linux -verify-machineinstrs | FileCheck %s -check-prefix=x00 + +; TODO fold the shifts +; x00-LABEL: test1: +; x00: mulu #-1985 +; x00-NEXT: lsr.l #8 +; x00-NEXT: lsr.l #8 +; x00-NEXT: lsr.w #5 +define zeroext i16 @test1(i16 zeroext %x) nounwind { +entry: + %div = udiv i16 %x, 33 + ret i16 %div +} + +; x00-LABEL: test2: +; x00: mulu #-21845 +; x00-NEXT: lsr.l #8 +; x00-NEXT: lsr.l #8 +; x00-NEXT: lsr.w #1 +define zeroext i16 @test2(i8 signext %x, i16 zeroext %c) { +entry: + %div = udiv i16 %c, 3 + ret i16 %div +} + + +; x00-LABEL: test3: +; x00: move.b (11 +; x00-NEXT: and.l #255 +; x00-NEXT: muls #171 +; x00-NEXT: move.w #9 +; x00-NEXT: lsr.w +define zeroext i8 @test3(i8 zeroext %x, i8 zeroext %c) { +entry: + %div = udiv i8 %c, 3 + ret i8 %div +} + +; x00-LABEL: test4: +; x00: muls #1986 +define signext i16 @test4(i16 signext %x) nounwind { +entry: + %div = sdiv i16 %x, 33 ; [#uses=1] + ret i16 %div +} + +; x00-LABEL: test5: +; x00: jsr __udivsi3 +define i32 @test5(i32 %A) nounwind { + %tmp1 = udiv i32 %A, 1577682821 ; [#uses=1] + ret i32 %tmp1 +} + +; TODO fold shift +; x00-LABEL: test6: +; x00: muls #26215 +; x00: move.w #15 +; x00: lsr.w +; x00: asr.w #2 +define signext i16 @test6(i16 signext %x) nounwind { +entry: + %div = sdiv i16 %x, 10 + ret i16 %div +} + +; x00-LABEL: test7: +; x00: jsr __udivsi3 +define i32 @test7(i32 %x) nounwind { + %div = udiv i32 %x, 28 + ret i32 %div +} + +; x00-LABEL: test8: +; x00: lsr.b #1 +; x00: and.l #255 +; x00: muls #211 +; x00: move.w #13 +; x00: lsr.w +define i8 @test8(i8 %x) nounwind { + %div = udiv i8 %x, 78 + ret i8 %div +} + +; x00-LABEL: test9: +; x00: lsr.b #2 +; x00: and.l #255 +; x00: muls #71 +; x00: move.w #11 +; x00: lsr.w +define i8 @test9(i8 %x) nounwind { + %div = udiv i8 %x, 116 + ret i8 %div +} + +; x00-LABEL: testsize1: +; x00: asr.l +; x00: lsr.l +; x00: asr.l +define i32 @testsize1(i32 %x) minsize nounwind { +entry: + %div = sdiv i32 %x, 32 + ret i32 %div +} + +; x00-LABEL: testsize2: +; x00: jsr __divsi3 +define i32 @testsize2(i32 %x) minsize nounwind { +entry: + %div = sdiv i32 %x, 33 + ret i32 %div +} + +; x00-LABEL: testsize3: +; x00: lsr.l #5 +define i32 @testsize3(i32 %x) minsize nounwind { +entry: + %div = udiv i32 %x, 32 + ret i32 %div +} + +; x00-LABEL: testsize4: +; x00: jsr __udivsi3 +define i32 @testsize4(i32 %x) minsize nounwind { +entry: + %div = udiv i32 %x, 33 + ret i32 %div +} Index: llvm/test/CodeGen/M680x0/ASM/Arith/imul.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/M680x0/ASM/Arith/imul.ll @@ -0,0 +1,135 @@ +; RUN: llc < %s -O0 -mtriple=m680x0-linux | FileCheck %s --check-prefix=x00 + +; x00-LABEL: mul4_32: +; x00: lsl.l +define i32 @mul4_32(i32 %A) { + %mul = mul i32 %A, 4 + ret i32 %mul +} + +; x00-LABEL: mul4_64: +; x00: lsr.l +; x00: lsl.l +; x00: or.l +; x00: lsl.l +define i64 @mul4_64(i64 %A) { + %mul = mul i64 %A, 4 + ret i64 %mul +} + +; x00-LABEL: mul4096_32: +; x00: lsl.l +define i32 @mul4096_32(i32 %A) { + %mul = mul i32 %A, 4096 + ret i32 %mul +} + +; x00-LABEL: mul4096_64: +; x00: lsr.l +; x00: lsl.l +; x00: or.l +; x00: lsl.l +define i64 @mul4096_64(i64 %A) { + %mul = mul i64 %A, 4096 + ret i64 %mul +} + +; x00-LABEL: mulmin4096_32: +; x00: lsl.l +; x00-NEXT: neg.l +define i32 @mulmin4096_32(i32 %A) { + %mul = mul i32 %A, -4096 + ret i32 %mul +} + +; x00-LABEL: mulmin4096_64: +; x00: lsr.l +; x00: lsl.l +; x00: or.l +; x00: lsl.l +; x00: neg.l +; x00: negx.l +define i64 @mulmin4096_64(i64 %A) { + %mul = mul i64 %A, -4096 + ret i64 %mul +} + +; No i32 multiply for M68000 +; x00-LABEL: mul3_32: +; x00: jsr __mulsi3 +define i32 @mul3_32(i32 %A) { + %mul = mul i32 %A, 3 + ret i32 %mul +} + +; x00-LABEL: mul3_64: +; x00: jsr __muldi3 +define i64 @mul3_64(i64 %A) { + %mul = mul i64 %A, 3 + ret i64 %mul +} + +; x00-LABEL: mul40_32: +; x00: jsr __mulsi3 +define i32 @mul40_32(i32 %A) { + %mul = mul i32 %A, 40 + ret i32 %mul +} + +; x00-LABEL: mul40_64: +; x00: jsr __muldi3 +define i64 @mul40_64(i64 %A) { + %mul = mul i64 %A, 40 + ret i64 %mul +} + +; x00-LABEL: mul4_32_minsize: +; x00: lsl.l +define i32 @mul4_32_minsize(i32 %A) minsize { + %mul = mul i32 %A, 4 + ret i32 %mul +} + +; X64-LABEL: mul40_32_minsize: +; X64: jsr __mulsi3 +define i32 @mul40_32_minsize(i32 %A) minsize { + %mul = mul i32 %A, 40 + ret i32 %mul +} + +; x00-LABEL: mul33_32: +; x00: __mulsi3 +define i32 @mul33_32(i32 %A) { + %mul = mul i32 %A, 33 + ret i32 %mul +} + +; x00-LABEL: mul31_32: +; x00: __mulsi3 +define i32 @mul31_32(i32 %A) { + %mul = mul i32 %A, 31 + ret i32 %mul +} + +; x00-LABEL: mul0_32: +; x00: move.l #0 +define i32 @mul0_32(i32 %A) { + %mul = mul i32 %A, 0 + ret i32 %mul +} + +; x00-LABEL: mul4294967295_32: +; x00: neg.l %d0 +define i32 @mul4294967295_32(i32 %A) { + %mul = mul i32 %A, 4294967295 + ret i32 %mul +} + +; x00-LABEL: mul18446744073709551615_64: +; x00: neg.l %d0 +; x00: negx.l %d1 +; x00: rts +define i64 @mul18446744073709551615_64(i64 %A) { + %mul = mul i64 %A, 18446744073709551615 + ret i64 %mul +} Index: llvm/test/CodeGen/M680x0/ASM/Arith/lshr.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/M680x0/ASM/Arith/lshr.ll @@ -0,0 +1,16 @@ +; RUN: llc < %s -mtriple=m680x0-linux | FileCheck %s --check-prefix=x00 + +; Function Attrs: norecurse nounwind readnone +; x00-LABEL c_isspace: +; x00: move.l #8388639, %d0 +; x00: lsr.l %d1, %d0 +; x00: and.l #1, %d0 +define zeroext i1 @c_isspace(i32 %c) local_unnamed_addr #0 { +entry: + %switch.tableidx = add i32 %c, -9 + %switch.cast = trunc i32 %switch.tableidx to i24 + %switch.downshift = lshr i24 -8388577, %switch.cast + %0 = and i24 %switch.downshift, 1 + %switch.masked = icmp ne i24 %0, 0 + ret i1 %switch.masked +} Index: llvm/test/CodeGen/M680x0/ASM/Arith/mul64.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/M680x0/ASM/Arith/mul64.ll @@ -0,0 +1,10 @@ +; RUN: llc < %s -mtriple=m680x0-linux -verify-machineinstrs | FileCheck %s --check-prefix=x00 + +; Currenlty making the libcall is ok, x20 supports i32 mul/div which +; yields saner expansion for i64 mul +; x00-LABEL: foo: +; x00: jsr __muldi3 +define i64 @foo(i64 %t, i64 %u) nounwind { + %k = mul i64 %t, %u + ret i64 %k +} Index: llvm/test/CodeGen/M680x0/ASM/Arith/sdiv-exact.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/M680x0/ASM/Arith/sdiv-exact.ll @@ -0,0 +1,18 @@ +; RUN: llc -mtriple=m680x0-linux -verify-machineinstrs < %s | FileCheck %s -check-prefix=x00 + +; x00-LABEL: test1: +; x00: move.l #-1030792151 +; x00: jsr __mulsi3 +define i32 @test1(i32 %x) { + %div = sdiv exact i32 %x, 25 + ret i32 %div +} + +; x00-LABEL: test2: +; x00: asr.l #3 +; x00: move.l #-1431655765 +; x00: jsr __mulsi3 +define i32 @test2(i32 %x) { + %div = sdiv exact i32 %x, 24 + ret i32 %div +} Index: llvm/test/CodeGen/M680x0/ASM/Arith/smul-with-overflow.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/M680x0/ASM/Arith/smul-with-overflow.ll @@ -0,0 +1,68 @@ +; RUN: llc < %s -mtriple=m680x0-linux -verify-machineinstrs | FileCheck %s -check-prefix=x00 + +declare i32 @printf(i8*, ...) nounwind +declare {i32, i1} @llvm.smul.with.overflow.i32(i32, i32) +declare { i63, i1 } @llvm.smul.with.overflow.i63(i63, i63) + +@ok = internal constant [4 x i8] c"%d\0A\00" +@no = internal constant [4 x i8] c"no\0A\00" + +; x00-LABEL: test1: +; x00: jsr __muldi3 +; x00: sne +define fastcc i1 @test1(i32 %v1, i32 %v2) nounwind { +entry: + %t = call {i32, i1} @llvm.smul.with.overflow.i32(i32 %v1, i32 %v2) + %sum = extractvalue {i32, i1} %t, 0 + %obit = extractvalue {i32, i1} %t, 1 + br i1 %obit, label %overflow, label %normal + +normal: + %t1 = tail call i32 (i8*, ...) @printf( i8* getelementptr ([4 x i8], [4 x i8]* @ok, i32 0, i32 0), i32 %sum ) nounwind + ret i1 true + +overflow: + %t2 = tail call i32 (i8*, ...) @printf( i8* getelementptr ([4 x i8], [4 x i8]* @no, i32 0, i32 0) ) nounwind + ret i1 false +} + +; x00-LABEL: test2: +; x00: jsr __muldi3 +; x00: sne +define fastcc i1 @test2(i32 %v1, i32 %v2) nounwind { +entry: + %t = call {i32, i1} @llvm.smul.with.overflow.i32(i32 %v1, i32 %v2) + %sum = extractvalue {i32, i1} %t, 0 + %obit = extractvalue {i32, i1} %t, 1 + br i1 %obit, label %overflow, label %normal + +overflow: + %t2 = tail call i32 (i8*, ...) @printf( i8* getelementptr ([4 x i8], [4 x i8]* @no, i32 0, i32 0) ) nounwind + ret i1 false + +normal: + %t1 = tail call i32 (i8*, ...) @printf( i8* getelementptr ([4 x i8], [4 x i8]* @ok, i32 0, i32 0), i32 %sum ) nounwind + ret i1 true +} + +; x00-LABEL: test3: +; x00: add.l +; x00-NEXT: add.l +define i32 @test3(i32 %a, i32 %b) nounwind readnone { +entry: + %tmp0 = add i32 %b, %a + %tmp1 = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %tmp0, i32 2) + %tmp2 = extractvalue { i32, i1 } %tmp1, 0 + ret i32 %tmp2 +} + +; x00-LABEL: test4: +; x00: add.l +; x00: jsr __muldi3 +define i32 @test4(i32 %a, i32 %b) nounwind readnone { +entry: + %tmp0 = add i32 %b, %a + %tmp1 = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %tmp0, i32 4) + %tmp2 = extractvalue { i32, i1 } %tmp1, 0 + ret i32 %tmp2 +} Index: llvm/test/CodeGen/M680x0/ASM/Arith/sub-with-overflow.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/M680x0/ASM/Arith/sub-with-overflow.ll @@ -0,0 +1,56 @@ +; RUN: llc < %s -mtriple=m680x0-linux -verify-machineinstrs | FileCheck %s -check-prefix=x00 + +declare i32 @printf(i8*, ...) nounwind +declare {i32, i1} @llvm.ssub.with.overflow.i32(i32, i32) +declare {i32, i1} @llvm.usub.with.overflow.i32(i32, i32) + +@ok = internal constant [4 x i8] c"%d\0A\00" +@no = internal constant [4 x i8] c"no\0A\00" + +; x00-LABEL: func1: +; x00: sub.l (20,%sp) +; x00-NEXT: bvc +define i1 @func1(i32 %v1, i32 %v2) nounwind { +entry: + %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %v1, i32 %v2) + %sum = extractvalue {i32, i1} %t, 0 + %obit = extractvalue {i32, i1} %t, 1 + br i1 %obit, label %overflow, label %normal + +normal: + %t1 = tail call i32 (i8*, ...) @printf( i8* getelementptr ([4 x i8], [4 x i8]* @ok, i32 0, i32 0), i32 %sum ) nounwind + ret i1 true + +overflow: + %t2 = tail call i32 (i8*, ...) @printf( i8* getelementptr ([4 x i8], [4 x i8]* @no, i32 0, i32 0) ) nounwind + ret i1 false +} + +; x00-LABEL: func2: +; x00: sub.l (20,%sp) +; x00-NEXT: bcc +define i1 @func2(i32 %v1, i32 %v2) nounwind { +entry: + %t = call {i32, i1} @llvm.usub.with.overflow.i32(i32 %v1, i32 %v2) + %sum = extractvalue {i32, i1} %t, 0 + %obit = extractvalue {i32, i1} %t, 1 + br i1 %obit, label %carry, label %normal + +normal: + %t1 = tail call i32 (i8*, ...) @printf( i8* getelementptr ([4 x i8], [4 x i8]* @ok, i32 0, i32 0), i32 %sum ) nounwind + ret i1 true + +carry: + %t2 = tail call i32 (i8*, ...) @printf( i8* getelementptr ([4 x i8], [4 x i8]* @no, i32 0, i32 0) ) nounwind + ret i1 false +} + +; x00-LABEL: func3: +; x00: sub.l #1 +; x00-NEXT: svs +define i1 @func3(i32 %x) nounwind { +entry: + %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %x, i32 1) + %obit = extractvalue {i32, i1} %t, 1 + ret i1 %obit +} Index: llvm/test/CodeGen/M680x0/ASM/Arith/sub.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/M680x0/ASM/Arith/sub.ll @@ -0,0 +1,12 @@ +; RUN: llc -mtriple=m680x0-linux < %s -verify-machineinstrs | FileCheck %s -check-prefix=x00 + +; x00-LABEL: test1: +; x00: eori.l #31 +; x00-NEXT: move.l #32 +; x00-NEXT: sub.l +; x00-NEXT: rts +define i32 @test1(i32 %x) { + %xor = xor i32 %x, 31 + %sub = sub i32 32, %xor + ret i32 %sub +} Index: llvm/test/CodeGen/M680x0/ASM/Arith/umul-with-overflow.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/M680x0/ASM/Arith/umul-with-overflow.ll @@ -0,0 +1,38 @@ +; RUN: llc < %s -mtriple=m680x0-linux-gnu -verify-machineinstrs| FileCheck %s -check-prefix=x00 + +declare {i32, i1} @llvm.umul.with.overflow.i32(i32 %a, i32 %b) + +; x00-LABEL: a: +; x00-NOT: asr +; x00: jsr __muldi3 +; x00-NEXT cmpi.l #0, %d1 +; x00-NEXT sne +define i1 @a(i32 %x) nounwind { + %res = call {i32, i1} @llvm.umul.with.overflow.i32(i32 %x, i32 3) + %obil = extractvalue {i32, i1} %res, 1 + ret i1 %obil +} + +; x00-LABEL: test2: +; x00: add.l +; x00-NEXT: add.l +; x00-NEXT: rts +define i32 @test2(i32 %a, i32 %b) nounwind readnone { +entry: + %tmp0 = add i32 %b, %a + %tmp1 = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %tmp0, i32 2) + %tmp2 = extractvalue { i32, i1 } %tmp1, 0 + ret i32 %tmp2 +} + +; x00-LABEL: test3: +; x00: add.l +; x00-NOT: asr +; x00: jsr __muldi3 +define i32 @test3(i32 %a, i32 %b) nounwind readnone { +entry: + %tmp0 = add i32 %b, %a + %tmp1 = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %tmp0, i32 4) + %tmp2 = extractvalue { i32, i1 } %tmp1, 0 + ret i32 %tmp2 +} Index: llvm/test/CodeGen/M680x0/ASM/CConv/c-args-inreg.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/M680x0/ASM/CConv/c-args-inreg.ll @@ -0,0 +1,28 @@ +; RUN: llc < %s -mtriple=m680x0-pc-linux -relocation-model=pic -verify-machineinstrs | FileCheck -check-prefix=x00 %s + +; +; Pass first two arguments in registers %d0 and %d1 + +; x00-LABEL: foo_inreg: +; x00: move.l %d0, [[Reg:%a[0-7]]] +; x00: move.l %d1, ([[Reg]]) +; x00: rts + +define void @foo_inreg(i32* nocapture inreg %out, i32 inreg %in) nounwind { +entry: + store i32 %in, i32* %out, align 4 + ret void +} + +; x00-LABEL: bar_inreg: +; x00-DAG: move.l %d0, [[Out:%a[0-7]]] +; x00-DAG: move.l %d1, [[In:%a[0-7]]] +; x00: move.l ([[In]]), ([[Out]]) +; x00: rts + +define void @bar_inreg(i32* nocapture inreg %pOut, i32* nocapture inreg %pIn) nounwind { +entry: + %0 = load i32, i32* %pIn, align 4 + store i32 %0, i32* %pOut, align 4 + ret void +} Index: llvm/test/CodeGen/M680x0/ASM/CConv/c-args.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/M680x0/ASM/CConv/c-args.ll @@ -0,0 +1,66 @@ +; RUN: llc < %s -mtriple=m680x0-pc-linux -relocation-model=pic -verify-machineinstrs | FileCheck -check-prefix=x00 %s + +; +; C Call passes all arguments on stack ... + +; x00-LABEL: test1: +; x00: move.l (4,%sp), [[Reg:%a[0-7]]] +; x00: move.l (8,%sp), ([[Reg]]) +; x00: rts +define void @test1(i32* nocapture %out, i32 %in) nounwind { +entry: + store i32 %in, i32* %out, align 4 + ret void +} + +; x00-LABEL: test2: +; x00-DAG: move.l (4,%sp), [[Out:%a[0-7]]] +; x00-DAG: move.l (8,%sp), [[In:%a[0-7]]] +; x00: move.l ([[In]]), ([[Out]]) +; x00: rts +define void @test2(i32* nocapture %pOut, i32* nocapture %pIn) nounwind { +entry: + %0 = load i32, i32* %pIn, align 4 + store i32 %0, i32* %pOut, align 4 + ret void +} + +; x00-LABEL: test3: +; x00: move.l (4,%sp), [[Reg:%a[0-7]]] +; x00: move.b (11,%sp), ([[Reg]]) +; x00: rts +define void @test3(i8* nocapture %out, i8 %in) nounwind { +entry: + store i8 %in, i8* %out, align 1 + ret void +} + +; x00-LABEL: test4: +; x00: move.l (4,%sp), [[Reg:%a[0-7]]] +; x00: move.w (10,%sp), ([[Reg]]) +; x00: rts +define void @test4(i16* nocapture %out, i16 %in) nounwind { +entry: + store i16 %in, i16* %out, align 2 + ret void +} + +; x00-LABEL: test5: +; x00: move.b (7,%sp), [[Reg:%d[0-7]]] +; x00: add.b (11,%sp), [[Reg]] +; x00: rts +define i8 @test5(i8 %a, i8 %b) nounwind { +entry: + %add = add i8 %a, %b + ret i8 %add +} + +; x00-LABEL: test6: +; x00: move.w (6,%sp), [[Reg:%d[0-7]]] +; x00: add.w (10,%sp), [[Reg]] +; x00: rts +define i16 @test6(i16 %a, i16 %b) nounwind { +entry: + %add = add i16 %a, %b + ret i16 %add +} Index: llvm/test/CodeGen/M680x0/ASM/CConv/c-call.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/M680x0/ASM/CConv/c-call.ll @@ -0,0 +1,55 @@ +; RUN: llc < %s -mtriple=m680x0-pc-linux -relocation-model=pic -verify-machineinstrs | FileCheck -check-prefix=x00 %s + +; +; Pass all arguments on the stack in reverse order + +; x00-LABEL: test1: +; x00-DAG: move.l #5, (16,%sp) +; x00-DAG: move.l #4, (12,%sp) +; x00-DAG: move.l #3, (8,%sp) +; x00-DAG: move.l #2, (4,%sp) +; x00-DAG: move.l #1, (%sp) +; x00-NEXT: jsr (test1_callee@PLT,%pc) +; x00-NEXT: move.l + +define i32 @test1() nounwind uwtable { +entry: + call void @test1_callee(i32 1, i32 2, i32 3, i32 4, i32 5) nounwind + ret i32 0 +} + +declare void @test1_callee(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e); + +; x00-LABEL: test2: +; x00-DAG: move.l #5, (16,%sp) +; x00-DAG: move.l #4, (12,%sp) +; x00-DAG: move.l #3, (8,%sp) +; x00-DAG: move.l #2, (4,%sp) +; x00-DAG: move.l #1, (%sp) +; x00-NEXT: jsr (test2_callee@PLT,%pc) +; x00-NEXT: move.w + +define i16 @test2() nounwind uwtable { +entry: + call void @test2_callee(i16 1, i16 2, i16 3, i16 4, i16 5) nounwind + ret i16 0 +} + +declare void @test2_callee(i16 %a, i16 %b, i16 %c, i16 %d, i16 %e); + +; x00-LABEL: test3: +; x00-DAG: move.l #5, (16,%sp) +; x00-DAG: move.l #4, (12,%sp) +; x00-DAG: move.l #3, (8,%sp) +; x00-DAG: move.l #2, (4,%sp) +; x00-DAG: move.l #1, (%sp) +; x00-NEXT: jsr (test3_callee@PLT,%pc) +; x00-NEXT: move.b + +define i8 @test3() nounwind uwtable { +entry: + call void @test3_callee(i8 1, i8 2, i8 3, i8 4, i8 5) nounwind + ret i8 0 +} + +declare void @test3_callee(i8 %a, i8 %b, i8 %c, i8 %d, i8 %e); Index: llvm/test/CodeGen/M680x0/ASM/CConv/fastcc-args.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/M680x0/ASM/CConv/fastcc-args.ll @@ -0,0 +1,40 @@ +; RUN: llc < %s -mtriple=m680x0-pc-linux -relocation-model=pic -verify-machineinstrs | FileCheck -check-prefix=x00 %s + +; +; C Call passes all arguments on stack ... + +; x00-LABEL: test1: +; x00: move.l %d0, (%a0) +; x00-NEXT: rts + +define fastcc void @test1(i32* nocapture %out, i32 %in) nounwind { +entry: + store i32 %in, i32* %out, align 4 + ret void +} + +; x00-LABEL: test2: +; x00: move.l (%a1), (%a0) +; x00-NEXT: rts + +define fastcc void @test2(i32* nocapture %pOut, i32* nocapture %pIn) nounwind { +entry: + %0 = load i32, i32* %pIn, align 4 + store i32 %0, i32* %pOut, align 4 + ret void +} + + +; x00-LABEL: test3: +; x00: add.l %d1, %d0 +; x00-NEXT: add.l %a0, %d0 +; x00-NEXT: add.l %a1, %d0 +; x00-NEXT: add.l (4,%sp), %d0 + +define fastcc i32 @test3(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e) nounwind { + %1 = add i32 %a, %b + %2 = add i32 %1, %c + %3 = add i32 %2, %d + %4 = add i32 %3, %e + ret i32 %4 +} Index: llvm/test/CodeGen/M680x0/ASM/CConv/fastcc-call.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/M680x0/ASM/CConv/fastcc-call.ll @@ -0,0 +1,41 @@ +; RUN: llc < %s -mtriple=m680x0-pc-linux -relocation-model=pic -verify-machineinstrs | FileCheck -check-prefix=x00 %s + +; +; Pass first 4 arguments in registers %d0,%d1,%a0,%a1 the rest goes onto stack + +; x00-LABEL: foo1: +; x00-DAG: move.l #5, (%sp) +; x00-DAG: move.l #4, %a1 +; x00-DAG: move.l #3, %a0 +; x00-DAG: move.l #2, %d1 +; x00-DAG: move.l #1, %d0 +; x00-NEXT: jsr (bar1@PLT,%pc) + +define i32 @foo1() nounwind uwtable { +entry: + call fastcc void @bar1(i32 1, i32 2, i32 3, i32 4, i32 5) nounwind + ret i32 0 +} + +declare fastcc void @bar1(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e); + + +; +; Pass pointers in %a registers if there are any free left + +; x00-LABEL: foo2: +; x00-DAG: lea (8,%sp), %a0 +; x00-DAG: lea (4,%sp), %a1 +; x00-DAG: move.l #2, %d0 +; x00-DAG: move.l #4, %d1 +; x00-DAG: jsr (bar2@PLT,%pc) + +define i32 @foo2() nounwind uwtable { +entry: + %a = alloca i32, align 4 + %b = alloca i32, align 4 + call fastcc void @bar2(i32* %a, i32 2, i32* %b, i32 4) nounwind + ret i32 0 +} + +declare fastcc void @bar2(i32* %a, i32 %b, i32* %c, i32 %d); Index: llvm/test/CodeGen/M680x0/ASM/CodeModel/medium-pic.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/M680x0/ASM/CodeModel/medium-pic.ll @@ -0,0 +1,219 @@ +; RUN: llc < %s -O2 -mtriple=m680x0-linux-gnu -verify-machineinstrs \ +; RUN: -code-model=medium -relocation-model=pic \ +; RUN: | FileCheck %s -check-prefix=x00 + +@ptr = external global i32* +@dst = external global i32 +@src = external global i32 + +; x00-LABEL: test0: +; x00: move.l (dst@GOTPCREL,%pc), %a0 +; x00-NEXT: move.l (ptr@GOTPCREL,%pc), %a1 +; x00-NEXT: %a0, (%a1) +; x00-NEXT: move.l (src@GOTPCREL,%pc), %a1 +; x00-NEXT: (%a1), (%a0) +; x00-NEXT: rts +define void @test0() nounwind { +entry: + store i32* @dst, i32** @ptr + %tmp.s = load i32, i32* @src + store i32 %tmp.s, i32* @dst + ret void +} + +@ptr2 = global i32* null +@dst2 = global i32 0 +@src2 = global i32 0 + +; x00-LABEL: test1: +; x00: move.l (dst2@GOTPCREL,%pc), %a0 +; x00-NEXT: move.l (ptr2@GOTPCREL,%pc), %a1 +; x00-NEXT: %a0, (%a1) +; x00-NEXT: move.l (src2@GOTPCREL,%pc), %a1 +; x00-NEXT: (%a1), (%a0) +; x00-NEXT: rts +define void @test1() nounwind { +entry: + store i32* @dst2, i32** @ptr2 + %tmp.s = load i32, i32* @src2 + store i32 %tmp.s, i32* @dst2 + ret void +} + +declare i8* @malloc(i32) + +; x00-LABEL: test2: +; x00: move.l #40, (%sp) +; x00: jsr (malloc@PLT,%pc) +define void @test2() nounwind { +entry: + %ptr = call i8* @malloc(i32 40) + ret void +} + +@pfoo = external global void(...)* +declare void(...)* @afoo(...) + +; x00-LABEL: test3: +; x00: jsr (afoo@PLT,%pc) +; x00-NEXT: move.l %d0, %a0 +; x00-NEXT: move.l (pfoo@GOTPCREL,%pc), %a1 +; x00-NEXT: move.l %a0, (%a1) +; x00-NEXT: jsr (%a0) +define void @test3() nounwind { +entry: + %tmp = call void(...)*(...) @afoo() + store void(...)* %tmp, void(...)** @pfoo + %tmp1 = load void(...)*, void(...)** @pfoo + call void(...) %tmp1() + ret void +} + +declare void @foo(...) + +; x00-LABEL: test4: +; x00: jsr (foo@PLT,%pc) +define void @test4() nounwind { +entry: + call void(...) @foo() + ret void +} + +@ptr6 = internal global i32* null +@dst6 = internal global i32 0 +@src6 = internal global i32 0 + +; x00-LABEL: test5: +; x00 lea (dst6,%pc), %a0 +; x00 move.l %a0, (ptr6,%pc) +; x00 move.l (src6,%pc), (%a0) +define void @test5() nounwind { +entry: + store i32* @dst6, i32** @ptr6 + %tmp.s = load i32, i32* @src6 + store i32 %tmp.s, i32* @dst6 + ret void +} + + +;;; Test constant pool references. +;; FIXME no constant pool atm +;; 00: .LCPI6_0: +;; 00-LABEL: test6: +;; 00: calll .L6$pb +;; 00: .L6$pb: +;; 00: addl $_GLOBAL_OFFSET_TABLE_+(.L{{.*}}-.L6$pb), +;; 00: fldl .LCPI6_0@GOTOFF( +;define double @test6(i32 %a.u) nounwind { +;entry: +; %tmp = icmp eq i32 %a.u,0 +; %retval = select i1 %tmp, double 4.561230e+02, double 1.234560e+02 +; ret double %retval +;} + + +; Test jump table references. +; +; x00-LABEL: test7: +; x00: move.l (4,%sp), %d0 +; x00-NEXT: add.l #-1, %d0 +; x00-NEXT: move.l %d0, %d1 +; x00-NEXT: sub.l #12, %d1 +; x00-NEXT: bhi .LBB{{.*}}_14 +; x00: lea (_GLOBAL_OFFSET_TABLE_@GOTPCREL,%pc), %a0 +; x00: lsl.l #2, %d0 +; x00: add.l #.LJTI{{.*}}_0@GOTOFF, %a1 +; x00: add.l (0,%a1,%d0), %a0 +; x00-NEXT: jmp (%a0) +; +; x00: .LBB{{.*}}_2: +; x00-NEXT: bra foo1@PLT +; x00: .LBB{{.*}}_8: +; x00-NEXT: bra foo1@PLT +; x00: .LBB{{.*}}_14: +; x00-NEXT: bra foo6@PLT +; x00: .LBB{{.*}}_9: +; x00-NEXT: bra foo2@PLT +; x00: .LBB{{.*}}_10: +; x00-NEXT: bra foo6@PLT +; x00: .LBB{{.*}}_12: +; x00-NEXT: bra foo4@PLT +; x00: .LBB{{.*}}_3: +; x00-NEXT: bra foo2@PLT +; x00: .LBB{{.*}}_5: +; x00-NEXT: bra foo3@PLT +; x00: .LBB{{.*}}_6: +; x00-NEXT: bra foo4@PLT +; x00: .LBB{{.*}}_11: +; x00-NEXT: bra foo3@PLT +; x00: .LBB{{.*}}_4: +; x00-NEXT: bra foo6@PLT +; x00: .LBB{{.*}}_7: +; x00-NEXT: bra foo5@PLT +; x00: .LBB{{.*}}_13: +; x00-NEXT: bra foo5@PLT +; +; x00: .LJTI{{.*}}_0: +; x00: .long .LBB{{.*}}_2@GOTOFF +; x00: .long .LBB{{.*}}_8@GOTOFF +; x00: .long .LBB{{.*}}_14@GOTOFF +; x00: .long .LBB{{.*}}_9@GOTOFF +; x00: .long .LBB{{.*}}_10@GOTOFF +; x00: .long .LBB{{.*}}_12@GOTOFF +; x00: .long .LBB{{.*}}_3@GOTOFF +; x00: .long .LBB{{.*}}_5@GOTOFF +; x00: .long .LBB{{.*}}_6@GOTOFF +; x00: .long .LBB{{.*}}_11@GOTOFF +; x00: .long .LBB{{.*}}_4@GOTOFF +; x00: .long .LBB{{.*}}_7@GOTOFF +; x00: .long .LBB{{.*}}_13@GOTOFF +define void @test7(i32 %n.u) nounwind { +entry: + switch i32 %n.u, label %bb12 [i32 1, label %bb i32 2, label %bb6 i32 4, label %bb7 i32 5, label %bb8 i32 6, label %bb10 i32 7, label %bb1 i32 8, label %bb3 i32 9, label %bb4 i32 10, label %bb9 i32 11, label %bb2 i32 12, label %bb5 i32 13, label %bb11 ] +bb: + tail call void(...) @foo1() + ret void +bb1: + tail call void(...) @foo2() + ret void +bb2: + tail call void(...) @foo6() + ret void +bb3: + tail call void(...) @foo3() + ret void +bb4: + tail call void(...) @foo4() + ret void +bb5: + tail call void(...) @foo5() + ret void +bb6: + tail call void(...) @foo1() + ret void +bb7: + tail call void(...) @foo2() + ret void +bb8: + tail call void(...) @foo6() + ret void +bb9: + tail call void(...) @foo3() + ret void +bb10: + tail call void(...) @foo4() + ret void +bb11: + tail call void(...) @foo5() + ret void +bb12: + tail call void(...) @foo6() + ret void +} + +declare void @foo1(...) +declare void @foo2(...) +declare void @foo6(...) +declare void @foo3(...) +declare void @foo4(...) +declare void @foo5(...) Index: llvm/test/CodeGen/M680x0/ASM/CodeModel/medium-pie-global-access.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/M680x0/ASM/CodeModel/medium-pie-global-access.ll @@ -0,0 +1,102 @@ +; RUN: llc < %s -O2 -mtriple=m680x0-linux-gnu -verify-machineinstrs \ +; RUN: -code-model=medium -relocation-model=pic \ +; RUN: | FileCheck %s -check-prefix=x00 + +; External Linkage +@a = global i32 0, align 4 + +; x00-LABEL: my_access_global_a: +; x00: lea (_GLOBAL_OFFSET_TABLE_@GOTPCREL,%pc), %a0 +; x00: move.l #a@GOTOFF, %d0 +; x00: move.l (0,%a0,%d0), %d0 +; x00-NEXT: rts +define i32 @my_access_global_a() #0 { +entry: + %0 = load i32, i32* @a, align 4 + ret i32 %0 +} + +; WeakAny Linkage +@b = weak global i32 0, align 4 + +; x00-LABEL: my_access_global_b: +; x00: lea (_GLOBAL_OFFSET_TABLE_@GOTPCREL,%pc), %a0 +; x00-NEXT: move.l #b@GOTOFF, %d0 +; x00-NEXT: move.l (0,%a0,%d0), %d0 +define i32 @my_access_global_b() #0 { +entry: + %0 = load i32, i32* @b, align 4 + ret i32 %0 +} + +; Internal Linkage +@c = internal global i32 0, align 4 + +; x00-LABEL: my_access_global_c: +; x00: lea (_GLOBAL_OFFSET_TABLE_@GOTPCREL,%pc), %a0 +; x00-NEXT: move.l #c@GOTOFF, %d0 +; x00-NEXT: move.l (0,%a0,%d0), %d0 +define i32 @my_access_global_c() #0 { +entry: + %0 = load i32, i32* @c, align 4 + ret i32 %0 +} + +; External Linkage, only declaration. +@d = external global i32, align 4 + +; x00-LABEL: my_access_global_load_d: +; x00: move.l (d@GOTPCREL,%pc), %a0 +; x00-NEXT: move.l (%a0), %d0 +define i32 @my_access_global_load_d() #0 { +entry: + %0 = load i32, i32* @d, align 4 + ret i32 %0 +} + +; External Linkage, only declaration, store a value. +; x00-LABEL: my_access_global_store_d: +; x00: move.l (d@GOTPCREL,%pc), %a0 +; x00-NEXT: move.l #2, (%a0) +define i32 @my_access_global_store_d() #0 { +entry: + store i32 2, i32* @d, align 4 + ret i32 0 +} + +; External Linkage, function pointer access. +declare i32 @access_fp(i32 ()*) +declare i32 @foo() + +; x00-LABEL: my_access_fp_foo: +; x00: move.l (foo@GOTPCREL,%pc), (%sp) +; x00-NEXT: jsr (access_fp@PLT,%pc) +define i32 @my_access_fp_foo() #0 { +entry: + %call = call i32 @access_fp(i32 ()* @foo) + ret i32 %call +} + +; LinkOnceODR Linkage, function pointer access. + +$bar = comdat any + +define linkonce_odr i32 @bar() comdat { +entry: + ret i32 0 +} + +; x00-LABEL: my_access_fp_bar: +; x00: lea (_GLOBAL_OFFSET_TABLE_@GOTPCREL,%pc), %a0 +; x00-NEXT: add.l #bar@GOTOFF, %a0 +; x00-NEXT: move.l %a0, (%sp) +; x00-NEXT: jsr (access_fp@PLT,%pc) +define i32 @my_access_fp_bar() #0 { +entry: + %call = call i32 @access_fp(i32 ()* @bar) + ret i32 %call +} + +!llvm.module.flags = !{!0, !1} +!0 = !{i32 1, !"PIC Level", i32 1} +!1 = !{i32 1, !"PIE Level", i32 1} Index: llvm/test/CodeGen/M680x0/ASM/CodeModel/medium-pie.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/M680x0/ASM/CodeModel/medium-pie.ll @@ -0,0 +1,44 @@ +; RUN: llc < %s -O0 -mtriple=m680x0-linux-gnu -verify-machineinstrs \ +; RUN: -code-model=medium -relocation-model=pic \ +; RUN:| FileCheck %s -check-prefix=x00 + +define weak void @weak_foo() { + ret void +} + +define weak_odr void @weak_odr_foo() { + ret void +} + +define internal void @internal_foo() { + ret void +} + +declare i32 @ext_baz() + +define void @foo() { + ret void +} + + +; x00-LABEL: bar: +; x00: jsr (foo,%pc) +; x00: jsr (weak_odr_foo,%pc) +; x00: jsr (weak_foo,%pc) +; x00: jsr (internal_foo,%pc) +; x00: jsr (ext_baz@PLT,%pc) +define void @bar() { +entry: + call void @foo() + call void @weak_odr_foo() + call void @weak_foo() + call void @internal_foo() + call i32 @ext_baz() + ret void +} + +; -fpie for local global data tests should be added here + +!llvm.module.flags = !{!0, !1} +!0 = !{i32 1, !"PIC Level", i32 1} +!1 = !{i32 1, !"PIE Level", i32 1} Index: llvm/test/CodeGen/M680x0/ASM/CodeModel/medium-static.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/M680x0/ASM/CodeModel/medium-static.ll @@ -0,0 +1,212 @@ +; RUN: llc < %s -O2 -mtriple=m680x0-linux-gnu -verify-machineinstrs \ +; RUN: -code-model=medium -relocation-model=static \ +; RUN: | FileCheck %s -check-prefix=x00 + +@ptr = external global i32* +@dst = external global i32 +@src = external global i32 + +; x00-LABEL: test0: +; x00: move.l #dst, ptr +; x00-NEXT: move.l src, dst +; x00-NEXT: rts +define void @test0() nounwind { +entry: + store i32* @dst, i32** @ptr + %tmp.s = load i32, i32* @src + store i32 %tmp.s, i32* @dst + ret void +} + +@ptr2 = global i32* null +@dst2 = global i32 0 +@src2 = global i32 0 + +; x00-LABEL: test1: +; x00: move.l #dst2, ptr2 +; x00-NEXT: move.l src2, dst2 +; x00-NEXT: rts +define void @test1() nounwind { +entry: + store i32* @dst2, i32** @ptr2 + %tmp.s = load i32, i32* @src2 + store i32 %tmp.s, i32* @dst2 + ret void +} + +declare i8* @malloc(i32) + +; x00-LABEL: test2: +; x00: move.l #40, (%sp) +; x00: jsr malloc +define void @test2() nounwind { +entry: + %ptr = call i8* @malloc(i32 40) + ret void +} + +@pfoo = external global void(...)* +declare void(...)* @afoo(...) + +; x00-LABEL: test3: +; x00: jsr afoo +; x00-NEXT: move.l %d0, %a0 +; x00-NEXT: move.l %a0, pfoo +; x00-NEXT: jsr (%a0) +define void @test3() nounwind { +entry: + %tmp = call void(...)*(...) @afoo() + store void(...)* %tmp, void(...)** @pfoo + %tmp1 = load void(...)*, void(...)** @pfoo + call void(...) %tmp1() + ret void +} + +declare void @foo(...) + +; x00-LABEL: test4: +; x00: jsr foo +define void @test4() nounwind { +entry: + call void(...) @foo() + ret void +} + +@ptr6 = internal global i32* null +@dst6 = internal global i32 0 +@src6 = internal global i32 0 + +; x00-LABEL: test5: +; x00 lea (dst6,%pc), %a0 +; x00 move.l %a0, (ptr6,%pc) +; x00 move.l (src6,%pc), (%a0) +define void @test5() nounwind { +entry: + store i32* @dst6, i32** @ptr6 + %tmp.s = load i32, i32* @src6 + store i32 %tmp.s, i32* @dst6 + ret void +} + + +;;; Test constant pool references. +;; FIXME no constant pool atm +;; 00: .LCPI6_0: +;; 00-LABEL: test6: +;; 00: calll .L6$pb +;; 00: .L6$pb: +;; 00: addl $_GLOBAL_OFFSET_TABLE_+(.L{{.*}}-.L6$pb), +;; 00: fldl .LCPI6_0@GOTOFF( +;define double @test6(i32 %a.u) nounwind { +;entry: +; %tmp = icmp eq i32 %a.u,0 +; %retval = select i1 %tmp, double 4.561230e+02, double 1.234560e+02 +; ret double %retval +;} + + +; Test jump table references. +; +; x00-LABEL: test7: +; +; x00: move.l (4,%sp), %d0 +; x00-NEXT: add.l #-1, %d0 +; x00-NEXT: move.l %d0, %d1 +; x00-NEXT: sub.l #12, %d1 +; x00-NEXT: bhi .LBB{{.*}}_14 +; x00: lsl.l #2, %d0 +; x00-NEXT: move.l #.LJTI{{.*}}_0, %a0 +; x00-NEXT: move.l (0,%a0,%d0), %a0 +; x00-NEXT: jmp (%a0) +; +; x00: .LBB{{.*}}_2: +; x00-NEXT: bra foo1 +; x00: .LBB{{.*}}_8: +; x00-NEXT: bra foo1 +; x00: .LBB{{.*}}_14: +; x00-NEXT: bra foo6 +; x00: .LBB{{.*}}_9: +; x00-NEXT: bra foo2 +; x00: .LBB{{.*}}_10: +; x00-NEXT: bra foo6 +; x00: .LBB{{.*}}_12: +; x00-NEXT: bra foo4 +; x00: .LBB{{.*}}_3: +; x00-NEXT: bra foo2 +; x00: .LBB{{.*}}_5: +; x00-NEXT: bra foo3 +; x00: .LBB{{.*}}_6: +; x00-NEXT: bra foo4 +; x00: .LBB{{.*}}_11: +; x00-NEXT: bra foo3 +; x00: .LBB{{.*}}_4: +; x00-NEXT: bra foo6 +; x00: .LBB{{.*}}_7: +; x00-NEXT: bra foo5 +; x00: .LBB{{.*}}_13: +; x00-NEXT: bra foo5 +; +; x00: .p2align 2 +; x00: .long .LBB{{.*}}_2 +; x00: .long .LBB{{.*}}_8 +; x00: .long .LBB{{.*}}_14 +; x00: .long .LBB{{.*}}_9 +; x00: .long .LBB{{.*}}_10 +; x00: .long .LBB{{.*}}_12 +; x00: .long .LBB{{.*}}_3 +; x00: .long .LBB{{.*}}_5 +; x00: .long .LBB{{.*}}_6 +; x00: .long .LBB{{.*}}_11 +; x00: .long .LBB{{.*}}_4 +; x00: .long .LBB{{.*}}_7 +; x00: .long .LBB{{.*}}_13 +define void @test7(i32 %n.u) nounwind { +entry: + switch i32 %n.u, label %bb12 [i32 1, label %bb i32 2, label %bb6 i32 4, label %bb7 i32 5, label %bb8 i32 6, label %bb10 i32 7, label %bb1 i32 8, label %bb3 i32 9, label %bb4 i32 10, label %bb9 i32 11, label %bb2 i32 12, label %bb5 i32 13, label %bb11 ] +bb: + tail call void(...) @foo1() + ret void +bb1: + tail call void(...) @foo2() + ret void +bb2: + tail call void(...) @foo6() + ret void +bb3: + tail call void(...) @foo3() + ret void +bb4: + tail call void(...) @foo4() + ret void +bb5: + tail call void(...) @foo5() + ret void +bb6: + tail call void(...) @foo1() + ret void +bb7: + tail call void(...) @foo2() + ret void +bb8: + tail call void(...) @foo6() + ret void +bb9: + tail call void(...) @foo3() + ret void +bb10: + tail call void(...) @foo4() + ret void +bb11: + tail call void(...) @foo5() + ret void +bb12: + tail call void(...) @foo6() + ret void +} + +declare void @foo1(...) +declare void @foo2(...) +declare void @foo6(...) +declare void @foo3(...) +declare void @foo4(...) +declare void @foo5(...) Index: llvm/test/CodeGen/M680x0/ASM/CodeModel/small-pic.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/M680x0/ASM/CodeModel/small-pic.ll @@ -0,0 +1,219 @@ +; RUN: llc < %s -O2 -mtriple=m680x0-linux-gnu -verify-machineinstrs \ +; RUN: -code-model=small -relocation-model=pic \ +; RUN: | FileCheck %s -check-prefix=x00 + +@ptr = external global i32* +@dst = external global i32 +@src = external global i32 + +; x00-LABEL: test0: +; x00: move.l (dst@GOTPCREL,%pc), %a0 +; x00-NEXT: move.l (ptr@GOTPCREL,%pc), %a1 +; x00-NEXT: %a0, (%a1) +; x00-NEXT: move.l (src@GOTPCREL,%pc), %a1 +; x00-NEXT: (%a1), (%a0) +; x00-NEXT: rts +define void @test0() nounwind { +entry: + store i32* @dst, i32** @ptr + %tmp.s = load i32, i32* @src + store i32 %tmp.s, i32* @dst + ret void +} + +@ptr2 = global i32* null +@dst2 = global i32 0 +@src2 = global i32 0 + +; x00-LABEL: test1: +; x00: move.l (dst2@GOTPCREL,%pc), %a0 +; x00-NEXT: move.l (ptr2@GOTPCREL,%pc), %a1 +; x00-NEXT: %a0, (%a1) +; x00-NEXT: move.l (src2@GOTPCREL,%pc), %a1 +; x00-NEXT: (%a1), (%a0) +; x00-NEXT: rts +define void @test1() nounwind { +entry: + store i32* @dst2, i32** @ptr2 + %tmp.s = load i32, i32* @src2 + store i32 %tmp.s, i32* @dst2 + ret void +} + +declare i8* @malloc(i32) + +; x00-LABEL: test2: +; x00: move.l #40, (%sp) +; x00: jsr (malloc@PLT,%pc) +define void @test2() nounwind { +entry: + %ptr = call i8* @malloc(i32 40) + ret void +} + +@pfoo = external global void(...)* +declare void(...)* @afoo(...) + +; x00-LABEL: test3: +; x00: jsr (afoo@PLT,%pc) +; x00-NEXT: move.l %d0, %a0 +; x00-NEXT: move.l (pfoo@GOTPCREL,%pc), %a1 +; x00-NEXT: move.l %a0, (%a1) +; x00-NEXT: jsr (%a0) +define void @test3() nounwind { +entry: + %tmp = call void(...)*(...) @afoo() + store void(...)* %tmp, void(...)** @pfoo + %tmp1 = load void(...)*, void(...)** @pfoo + call void(...) %tmp1() + ret void +} + +declare void @foo(...) + +; x00-LABEL: test4: +; x00: jsr (foo@PLT,%pc) +define void @test4() nounwind { +entry: + call void(...) @foo() + ret void +} + +@ptr6 = internal global i32* null +@dst6 = internal global i32 0 +@src6 = internal global i32 0 + +; x00-LABEL: test5: +; x00 lea (dst6,%pc), %a0 +; x00 move.l %a0, (ptr6,%pc) +; x00 move.l (src6,%pc), (%a0) +define void @test5() nounwind { +entry: + store i32* @dst6, i32** @ptr6 + %tmp.s = load i32, i32* @src6 + store i32 %tmp.s, i32* @dst6 + ret void +} + + +;;; Test constant pool references. +;; FIXME no constant pool atm +;; 00: .LCPI6_0: +;; 00-LABEL: test6: +;; 00: calll .L6$pb +;; 00: .L6$pb: +;; 00: addl $_GLOBAL_OFFSET_TABLE_+(.L{{.*}}-.L6$pb), +;; 00: fldl .LCPI6_0@GOTOFF( +;define double @test6(i32 %a.u) nounwind { +;entry: +; %tmp = icmp eq i32 %a.u,0 +; %retval = select i1 %tmp, double 4.561230e+02, double 1.234560e+02 +; ret double %retval +;} + + +; Test jump table references. +; +; x00-LABEL: test7: +; +; x00: move.l (4,%sp), %d0 +; x00-NEXT: add.l #-1, %d0 +; x00-NEXT: move.l %d0, %d1 +; x00-NEXT: sub.l #12, %d1 +; x00-NEXT: bhi .LBB{{.*}}_14 +; x00: lsl.l #2, %d0 +; x00-NEXT: lea (.LJTI{{.*}}_0,%pc), %a0 +; x00-NEXT: add.l (0,%a0,%d0), %a0 +; x00-NEXT: jmp (%a0) +; +; x00: .LBB{{.*}}_2: +; x00-NEXT: bra foo1@PLT +; x00: .LBB{{.*}}_8: +; x00-NEXT: bra foo1@PLT +; x00: .LBB{{.*}}_14: +; x00-NEXT: bra foo6@PLT +; x00: .LBB{{.*}}_9: +; x00-NEXT: bra foo2@PLT +; x00: .LBB{{.*}}_10: +; x00-NEXT: bra foo6@PLT +; x00: .LBB{{.*}}_12: +; x00-NEXT: bra foo4@PLT +; x00: .LBB{{.*}}_3: +; x00-NEXT: bra foo2@PLT +; x00: .LBB{{.*}}_5: +; x00-NEXT: bra foo3@PLT +; x00: .LBB{{.*}}_6: +; x00-NEXT: bra foo4@PLT +; x00: .LBB{{.*}}_11: +; x00-NEXT: bra foo3@PLT +; x00: .LBB{{.*}}_4: +; x00-NEXT: bra foo6@PLT +; x00: .LBB{{.*}}_7: +; x00-NEXT: bra foo5@PLT +; x00: .LBB{{.*}}_13: +; x00-NEXT: bra foo5@PLT +; +; x00: .p2align 2 +; x00: .long .LBB{{.*}}_2-.LJTI{{.*}}_0 +; x00: .long .LBB{{.*}}_8-.LJTI{{.*}}_0 +; x00: .long .LBB{{.*}}_14-.LJTI{{.*}}_0 +; x00: .long .LBB{{.*}}_9-.LJTI{{.*}}_0 +; x00: .long .LBB{{.*}}_10-.LJTI{{.*}}_0 +; x00: .long .LBB{{.*}}_12-.LJTI{{.*}}_0 +; x00: .long .LBB{{.*}}_3-.LJTI{{.*}}_0 +; x00: .long .LBB{{.*}}_5-.LJTI{{.*}}_0 +; x00: .long .LBB{{.*}}_6-.LJTI{{.*}}_0 +; x00: .long .LBB{{.*}}_11-.LJTI{{.*}}_0 +; x00: .long .LBB{{.*}}_4-.LJTI{{.*}}_0 +; x00: .long .LBB{{.*}}_7-.LJTI{{.*}}_0 +; x00: .long .LBB{{.*}}_13-.LJTI{{.*}}_0 +define void @test7(i32 %n.u) nounwind { +entry: + switch i32 %n.u, label %bb12 [i32 1, label %bb i32 2, label %bb6 i32 4, label %bb7 i32 5, label %bb8 i32 6, label %bb10 i32 7, label %bb1 i32 8, label %bb3 i32 9, label %bb4 i32 10, label %bb9 i32 11, label %bb2 i32 12, label %bb5 i32 13, label %bb11 ] +bb: + tail call void(...) @foo1() + ret void +bb1: + tail call void(...) @foo2() + ret void +bb2: + tail call void(...) @foo6() + ret void +bb3: + tail call void(...) @foo3() + ret void +bb4: + tail call void(...) @foo4() + ret void +bb5: + tail call void(...) @foo5() + ret void +bb6: + tail call void(...) @foo1() + ret void +bb7: + tail call void(...) @foo2() + ret void +bb8: + tail call void(...) @foo6() + ret void +bb9: + tail call void(...) @foo3() + ret void +bb10: + tail call void(...) @foo4() + ret void +bb11: + tail call void(...) @foo5() + ret void +bb12: + tail call void(...) @foo6() + ret void +} + +declare void @foo1(...) +declare void @foo2(...) +declare void @foo6(...) +declare void @foo3(...) +declare void @foo4(...) +declare void @foo5(...) Index: llvm/test/CodeGen/M680x0/ASM/CodeModel/small-pie-global-access.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/M680x0/ASM/CodeModel/small-pie-global-access.ll @@ -0,0 +1,95 @@ +; RUN: llc < %s -O2 -mtriple=m680x0-linux-gnu -verify-machineinstrs \ +; RUN: -code-model=small -relocation-model=pic \ +; RUN: | FileCheck %s -check-prefix=x00 + +; External Linkage +@a = global i32 0, align 4 + +; x00-LABEL: my_access_global_a: +; x00: move.l (a,%pc), %d0 +; x00-NEXT: rts +define i32 @my_access_global_a() #0 { +entry: + %0 = load i32, i32* @a, align 4 + ret i32 %0 +} + +; WeakAny Linkage +@b = weak global i32 0, align 4 + +; x00-LABEL: my_access_global_b: +; x00: move.l (b,%pc), %d0 +define i32 @my_access_global_b() #0 { +entry: + %0 = load i32, i32* @b, align 4 + ret i32 %0 +} + +; Internal Linkage +@c = internal global i32 0, align 4 + +; x00-LABEL: my_access_global_c: +; x00: move.l (c,%pc), %d0 +define i32 @my_access_global_c() #0 { +entry: + %0 = load i32, i32* @c, align 4 + ret i32 %0 +} + +; External Linkage, only declaration. +@d = external global i32, align 4 + +; x00-LABEL: my_access_global_load_d: +; x00: move.l (d@GOTPCREL,%pc), %a0 +; x00-NEXT: move.l (%a0), %d0 +define i32 @my_access_global_load_d() #0 { +entry: + %0 = load i32, i32* @d, align 4 + ret i32 %0 +} + +; External Linkage, only declaration, store a value. +; x00-LABEL: my_access_global_store_d: +; x00: move.l (d@GOTPCREL,%pc), %a0 +; x00-NEXT: move.l #2, (%a0) +define i32 @my_access_global_store_d() #0 { +entry: + store i32 2, i32* @d, align 4 + ret i32 0 +} + +; External Linkage, function pointer access. +declare i32 @access_fp(i32 ()*) +declare i32 @foo() + +; x00-LABEL: my_access_fp_foo: +; x00: move.l (foo@GOTPCREL,%pc), (%sp) +; x00-NEXT: jsr (access_fp@PLT,%pc) +define i32 @my_access_fp_foo() #0 { +entry: + %call = call i32 @access_fp(i32 ()* @foo) + ret i32 %call +} + +; LinkOnceODR Linkage, function pointer access. + +$bar = comdat any + +define linkonce_odr i32 @bar() comdat { +entry: + ret i32 0 +} + +; x00-LABEL: my_access_fp_bar: +; x00: lea (bar,%pc), %a0 +; x00-NEXT: move.l %a0, (%sp) +; x00-NEXT: jsr (access_fp@PLT,%pc) +define i32 @my_access_fp_bar() #0 { +entry: + %call = call i32 @access_fp(i32 ()* @bar) + ret i32 %call +} + +!llvm.module.flags = !{!0, !1} +!0 = !{i32 1, !"PIC Level", i32 1} +!1 = !{i32 1, !"PIE Level", i32 1} Index: llvm/test/CodeGen/M680x0/ASM/CodeModel/small-pie.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/M680x0/ASM/CodeModel/small-pie.ll @@ -0,0 +1,44 @@ +; RUN: llc < %s -O0 -mtriple=m680x0-linux-gnu -verify-machineinstrs \ +; RUN: -code-model=small -relocation-model=pic \ +; RUN: | FileCheck %s -check-prefix=x00 + +define weak void @weak_foo() { + ret void +} + +define weak_odr void @weak_odr_foo() { + ret void +} + +define internal void @internal_foo() { + ret void +} + +declare i32 @ext_baz() + +define void @foo() { + ret void +} + + +; x00-LABEL: bar: +; x00: jsr (foo,%pc) +; x00: jsr (weak_odr_foo,%pc) +; x00: jsr (weak_foo,%pc) +; x00: jsr (internal_foo,%pc) +; x00: jsr (ext_baz@PLT,%pc) +define void @bar() { +entry: + call void @foo() + call void @weak_odr_foo() + call void @weak_foo() + call void @internal_foo() + call i32 @ext_baz() + ret void +} + +; -fpie for local global data tests should be added here + +!llvm.module.flags = !{!0, !1} +!0 = !{i32 1, !"PIC Level", i32 1} +!1 = !{i32 1, !"PIE Level", i32 1} Index: llvm/test/CodeGen/M680x0/ASM/CodeModel/small-static.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/M680x0/ASM/CodeModel/small-static.ll @@ -0,0 +1,216 @@ +; RUN: llc < %s -O2 -mtriple=m680x0-linux-gnu -verify-machineinstrs \ +; RUN: -code-model=small -relocation-model=static \ +; RUN: | FileCheck %s -check-prefix=x00 + +@ptr = external global i32* +@dst = external global i32 +@src = external global i32 + +; x00-LABEL: test0: +; x00: lea (dst,%pc), %a0 +; x00: lea (ptr,%pc), %a1 +; x00-NEXT: move.l %a0, (%a1) +; x00-NEXT: move.l (src,%pc), (%a0) +; x00-NEXT: rts +define void @test0() nounwind { +entry: + store i32* @dst, i32** @ptr + %tmp.s = load i32, i32* @src + store i32 %tmp.s, i32* @dst + ret void +} + +@ptr2 = global i32* null +@dst2 = global i32 0 +@src2 = global i32 0 + +; x00-LABEL: test1: +; x00: lea (dst2,%pc), %a0 +; x00-NEXT move.l %a0, (ptr2,%pc) +; x00-NEXT move.l (src2,%pc), (dst2,%pc) +; x00-NEXT rts +define void @test1() nounwind { +entry: + store i32* @dst2, i32** @ptr2 + %tmp.s = load i32, i32* @src2 + store i32 %tmp.s, i32* @dst2 + ret void +} + +declare i8* @malloc(i32) + +; x00-LABEL: test2: +; x00: move.l #40, (%sp) +; x00: jsr malloc +define void @test2() nounwind { +entry: + %ptr = call i8* @malloc(i32 40) + ret void +} + +@pfoo = external global void(...)* +declare void(...)* @afoo(...) + +; x00-LABEL: test3: +; x00: jsr afoo +; x00-NEXT: move.l %d0, %a0 +; x00-NEXT: lea (pfoo,%pc), %a1 +; x00-NEXT: move.l %a0, (%a1) +; x00-NEXT: jsr (%a0) +define void @test3() nounwind { +entry: + %tmp = call void(...)*(...) @afoo() + store void(...)* %tmp, void(...)** @pfoo + %tmp1 = load void(...)*, void(...)** @pfoo + call void(...) %tmp1() + ret void +} + +declare void @foo(...) + +; x00-LABEL: test4: +; x00: jsr foo +define void @test4() nounwind { +entry: + call void(...) @foo() + ret void +} + +@ptr6 = internal global i32* null +@dst6 = internal global i32 0 +@src6 = internal global i32 0 + +; x00-LABEL: test5: +; x00 lea (dst6,%pc), %a0 +; x00 move.l %a0, (ptr6,%pc) +; x00 move.l (src6,%pc), (%a0) +define void @test5() nounwind { +entry: + store i32* @dst6, i32** @ptr6 + %tmp.s = load i32, i32* @src6 + store i32 %tmp.s, i32* @dst6 + ret void +} + + +;;; Test constant pool references. +;; FIXME no constant pool atm +;; 00: .LCPI6_0: +;; 00-LABEL: test6: +;; 00: calll .L6$pb +;; 00: .L6$pb: +;; 00: addl $_GLOBAL_OFFSET_TABLE_+(.L{{.*}}-.L6$pb), +;; 00: fldl .LCPI6_0@GOTOFF( +;define double @test6(i32 %a.u) nounwind { +;entry: +; %tmp = icmp eq i32 %a.u,0 +; %retval = select i1 %tmp, double 4.561230e+02, double 1.234560e+02 +; ret double %retval +;} + + +; Test jump table references. +; +; x00-LABEL: test7: +; +; x00: move.l (4,%sp), %d0 +; x00-NEXT: add.l #-1, %d0 +; x00-NEXT: move.l %d0, %d1 +; x00-NEXT: sub.l #12, %d1 +; x00-NEXT: bhi .LBB{{.*}}_14 +; x00: lsl.l #2, %d0 +; x00-NEXT: lea (.LJTI{{.*}}_0,%pc), %a0 +; x00-NEXT: move.l (0,%a0,%d0), %a0 +; x00-NEXT: jmp (%a0) +; +; x00: .LBB{{.*}}_2: +; x00-NEXT: bra foo1 +; x00: .LBB{{.*}}_8: +; x00-NEXT: bra foo1 +; x00: .LBB{{.*}}_14: +; x00-NEXT: bra foo6 +; x00: .LBB{{.*}}_9: +; x00-NEXT: bra foo2 +; x00: .LBB{{.*}}_10: +; x00-NEXT: bra foo6 +; x00: .LBB{{.*}}_12: +; x00-NEXT: bra foo4 +; x00: .LBB{{.*}}_3: +; x00-NEXT: bra foo2 +; x00: .LBB{{.*}}_5: +; x00-NEXT: bra foo3 +; x00: .LBB{{.*}}_6: +; x00-NEXT: bra foo4 +; x00: .LBB{{.*}}_11: +; x00-NEXT: bra foo3 +; x00: .LBB{{.*}}_4: +; x00-NEXT: bra foo6 +; x00: .LBB{{.*}}_7: +; x00-NEXT: bra foo5 +; x00: .LBB{{.*}}_13: +; x00-NEXT: bra foo5 +; +; x00: .p2align 2 +; x00: .long .LBB{{.*}}_2 +; x00: .long .LBB{{.*}}_8 +; x00: .long .LBB{{.*}}_14 +; x00: .long .LBB{{.*}}_9 +; x00: .long .LBB{{.*}}_10 +; x00: .long .LBB{{.*}}_12 +; x00: .long .LBB{{.*}}_3 +; x00: .long .LBB{{.*}}_5 +; x00: .long .LBB{{.*}}_6 +; x00: .long .LBB{{.*}}_11 +; x00: .long .LBB{{.*}}_4 +; x00: .long .LBB{{.*}}_7 +; x00: .long .LBB{{.*}}_13 +define void @test7(i32 %n.u) nounwind { +entry: + switch i32 %n.u, label %bb12 [i32 1, label %bb i32 2, label %bb6 i32 4, label %bb7 i32 5, label %bb8 i32 6, label %bb10 i32 7, label %bb1 i32 8, label %bb3 i32 9, label %bb4 i32 10, label %bb9 i32 11, label %bb2 i32 12, label %bb5 i32 13, label %bb11 ] +bb: + tail call void(...) @foo1() + ret void +bb1: + tail call void(...) @foo2() + ret void +bb2: + tail call void(...) @foo6() + ret void +bb3: + tail call void(...) @foo3() + ret void +bb4: + tail call void(...) @foo4() + ret void +bb5: + tail call void(...) @foo5() + ret void +bb6: + tail call void(...) @foo1() + ret void +bb7: + tail call void(...) @foo2() + ret void +bb8: + tail call void(...) @foo6() + ret void +bb9: + tail call void(...) @foo3() + ret void +bb10: + tail call void(...) @foo4() + ret void +bb11: + tail call void(...) @foo5() + ret void +bb12: + tail call void(...) @foo6() + ret void +} + +declare void @foo1(...) +declare void @foo2(...) +declare void @foo6(...) +declare void @foo3(...) +declare void @foo4(...) +declare void @foo5(...) Index: llvm/test/CodeGen/M680x0/ASM/Control/cmp.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/M680x0/ASM/Control/cmp.ll @@ -0,0 +1,209 @@ +; RUN: llc < %s -mtriple=m680x0-linux-gnu -verify-machineinstrs | FileCheck %s --check-prefix=x00 + +; x00-LABEL: test1: +; x00: cmpi.l #0, (%a0) +; x00: beq +define i32 @test1(i32* %y) nounwind { + %tmp = load i32, i32* %y ; [#uses=1] + %tmp.upgrd.1 = icmp eq i32 %tmp, 0 ; [#uses=1] + br i1 %tmp.upgrd.1, label %cond_true, label %cond_false + +cond_false: ; preds = %0 + ret i32 0 + +cond_true: ; preds = %0 + ret i32 1 +} + +; x00-LABEL: test2: +; x00: and.l #536870911 +; TODO There is no need for cmpi.l, and.l sets Z as well +; x00: cmpi.l #0 +; x00: beq +define i32 @test2(i32* %y) nounwind { + %tmp = load i32, i32* %y ; [#uses=1] + %tmp1 = shl i32 %tmp, 3 ; [#uses=1] + %tmp1.upgrd.2 = icmp eq i32 %tmp1, 0 ; [#uses=1] + br i1 %tmp1.upgrd.2, label %cond_true, label %cond_false + +cond_false: ; preds = %0 + ret i32 0 + +cond_true: ; preds = %0 + ret i32 1 +} + +; x00-LABEL: test2b: +; x00: and.b #31 +; x00: cmpi.b #0 +; x00: beq +define i8 @test2b(i8* %y) nounwind { + %tmp = load i8, i8* %y ; [#uses=1] + %tmp1 = shl i8 %tmp, 3 ; [#uses=1] + %tmp1.upgrd.2 = icmp eq i8 %tmp1, 0 ; [#uses=1] + br i1 %tmp1.upgrd.2, label %cond_true, label %cond_false + +cond_false: ; preds = %0 + ret i8 0 + +cond_true: ; preds = %0 + ret i8 1 +} + +; x00-LABEL: test3: +; x00: or.l +; x00-NEXT: seq %d0 +; x00-NEXT: move.l %d0, %d1 +; x00-NEXT: and.l #255, %d1 +; x00-NEXT: move.l #0, %d0 +define i64 @test3(i64 %x) nounwind { + %t = icmp eq i64 %x, 0 + %r = zext i1 %t to i64 + ret i64 %r +} + +; x00-LABEL: test4: +; x00: sub.l #1 +; x00: subx.l +; x00: slt +define i64 @test4(i64 %x) nounwind { + %t = icmp slt i64 %x, 1 + %r = zext i1 %t to i64 + ret i64 %r +} + +; x00-LABEL: test6: +; x00: move.l (12,%sp), %d0 +; x00: or.l (8,%sp), %d0 +; x00: beq +define i32 @test6() nounwind align 2 { + %A = alloca {i64, i64}, align 8 + %B = getelementptr inbounds {i64, i64}, {i64, i64}* %A, i64 0, i32 1 + %C = load i64, i64* %B + %D = icmp eq i64 %C, 0 + br i1 %D, label %T, label %F +T: + ret i32 1 + +F: + ret i32 0 +} + +; x00-LABEL: test7: +; x00: cmpi.l #0, (4,%sp) +; x00: seq +define i32 @test7(i64 %res) nounwind { +entry: + %lnot = icmp ult i64 %res, 4294967296 + %lnot.ext = zext i1 %lnot to i32 + ret i32 %lnot.ext +} + +; x00-LABEL: test8: +; x00: move.l (4,%sp), %d0 +; x00: sub.l #3, %d0 +; x00: scs %d0 +define i32 @test8(i64 %res) nounwind { +entry: + %lnot = icmp ult i64 %res, 12884901888 + %lnot.ext = zext i1 %lnot to i32 + ret i32 %lnot.ext +} + +; x00-LABEL: test11: +; x00: move.l (4,%sp), %d0 +; x00: and.l #-32768, %d0 +; x00: eori.l #32768, %d0 +; x00: seq +define i32 @test11(i64 %l) nounwind { +entry: + %shr.mask = and i64 %l, -140737488355328 + %cmp = icmp eq i64 %shr.mask, 140737488355328 + %conv = zext i1 %cmp to i32 + ret i32 %conv +} + +; x00-LABEL: test13: +; x00: move.b (7,%sp) +; x00: and.b #8 +; x00: cmpi.b #0 +define i32 @test13(i32 %mask, i32 %base, i32 %intra) { + %and = and i32 %mask, 8 + %tobool = icmp ne i32 %and, 0 + %cond = select i1 %tobool, i32 %intra, i32 %base + ret i32 %cond +} + +; x00-LABEL: test14: +; x00: move.l +; x00: lsr.l #7 +; x00: cmpi.l #0 +; x00: bpl +define i32 @test14(i32 %mask, i32 %base, i32 %intra) #0 { + %s = lshr i32 %mask, 7 + %tobool = icmp sgt i32 %s, -1 + %cond = select i1 %tobool, i32 %intra, i32 %base + ret i32 %cond +} + +; x00-LABEL: test15: +; x00: scc +; x00: seq +; x00: or.b +define zeroext i1 @test15(i32 %bf.load, i32 %n) { + %bf.lshr = lshr i32 %bf.load, 16 + %cmp2 = icmp eq i32 %bf.lshr, 0 + %cmp5 = icmp uge i32 %bf.lshr, %n + %.cmp5 = or i1 %cmp2, %cmp5 + ret i1 %.cmp5 +} + +; x00-LABEL: test16: +; x00: move.w #15 +; x00: move.w (6,%sp), %d0 +; x00: lsr.w +; x00: eori.b #1 +define i8 @test16(i16 signext %L) { + %lshr = lshr i16 %L, 15 + %trunc = trunc i16 %lshr to i8 + %not = xor i8 %trunc, 1 + ret i8 %not +} + +; x00-LABEL: test18: +; x00: move.l #31 +; x00: move.l +; x00: lsr.l +; x00: eori.b #1 +define i8 @test18(i64 %L) { + %lshr = lshr i64 %L, 63 + %trunc = trunc i64 %lshr to i8 + %not = xor i8 %trunc, 1 + ret i8 %not +} + +@d = global i8 0, align 1 + + +; x00-LABEL: test20 +; x00: and.l +; x00: sne +; x00: add.l +; x00: sne +; x00: cmpi.l +; x00: sne +define void @test20(i32 %bf.load, i8 %x1, i8* %b_addr) { + %bf.shl = shl i32 %bf.load, 8 + %bf.ashr = ashr exact i32 %bf.shl, 8 + %tobool4 = icmp ne i32 %bf.ashr, 0 + %conv = zext i1 %tobool4 to i32 + %conv6 = zext i8 %x1 to i32 + %add = add nuw nsw i32 %conv, %conv6 + %tobool7 = icmp ne i32 %add, 0 + %frombool = zext i1 %tobool7 to i8 + store i8 %frombool, i8* %b_addr, align 1 + %tobool14 = icmp ne i32 %bf.shl, 0 + %frombool15 = zext i1 %tobool14 to i8 + store i8 %frombool15, i8* @d, align 1 + ret void +} Index: llvm/test/CodeGen/M680x0/ASM/Control/long-setcc.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/M680x0/ASM/Control/long-setcc.ll @@ -0,0 +1,32 @@ +; RUN: llc < %s -mtriple=m680x0-linux -verify-machineinstrs | FileCheck %s -check-prefix=x00 + +; x00: t1 +; x00: lsr.l +; x00-NOT: lsr.l +; x00: rts + +define i1 @t1(i64 %x) nounwind { + %B = icmp slt i64 %x, 0 + ret i1 %B +} + + +; x00: t2 +; x00: cmpi.l +; x00-NEXT: seq +; x00-NEXT: rts + +define i1 @t2(i64 %x) nounwind { + %tmp = icmp ult i64 %x, 4294967296 + ret i1 %tmp +} + + +; x00: t3 +; x00: move.b #0, %d0 +; x00: rts + +define i1 @t3(i32 %x) nounwind { + %tmp = icmp ugt i32 %x, -1 + ret i1 %tmp +} Index: llvm/test/CodeGen/M680x0/ASM/Control/setcc.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/M680x0/ASM/Control/setcc.ll @@ -0,0 +1,91 @@ +; RUN: llc < %s -mtriple=m680x0-linux -verify-machineinstrs | FileCheck %s -check-prefix=x00 + +;; TODO All these can be improved + +; x00-LABEL: t1: +; x00: move.w +; x00: and.l #65535, %d0 +; x00: sub.l #26, %d0 +; x00: shi %d0 +; x00: and.l #255, %d0 +; x00: lsl.l #5, %d0 + +define zeroext i16 @t1(i16 zeroext %x) nounwind readnone ssp { +entry: + %0 = icmp ugt i16 %x, 26 ; [#uses=1] + %iftmp.1.0 = select i1 %0, i16 32, i16 0 ; [#uses=1] + ret i16 %iftmp.1.0 +} + + +; x00-LABEL: t2: +; x00: move.w +; x00: and.l #65535, %d0 +; x00: sub.l #26, %d0 +; x00: scs %d0 +; x00: and.l #255, %d0 +; x00: lsl.l #5, %d0 + +define zeroext i16 @t2(i16 zeroext %x) nounwind readnone ssp { +entry: + %0 = icmp ult i16 %x, 26 ; [#uses=1] + %iftmp.0.0 = select i1 %0, i16 32, i16 0 ; [#uses=1] + ret i16 %iftmp.0.0 +} + +; x00-LABEL: t3: +; x00: move.l #0, %d2 +; x00: sub.l #18, %d1 +; x00: subx.l %d2, %d0 +; x00: scs +; x00: and.l +; x00: lsl.l + +define fastcc i64 @t3(i64 %x) nounwind readnone ssp { +entry: + %0 = icmp ult i64 %x, 18 ; [#uses=1] + %iftmp.2.0 = select i1 %0, i64 64, i64 0 ; [#uses=1] + ret i64 %iftmp.2.0 +} + + +; x00-LABEL: t5: +; x00: move.l #31 +; x00: move.l (4 +; x00: lsr.l +; x00: eori.b +; +; Should be: +; cmp.l +; smi +; since we are intereseted in sign bit only + +define i8 @t5(i32 %a) { +entry: + %.lobit = lshr i32 %a, 31 + %trunc = trunc i32 %.lobit to i8 + %.not = xor i8 %trunc, 1 + ret i8 %.not +} + + +; x00-LABEL: t6: +; x00: move.l #31 +; x00: move.l (4 +; x00: lsr.l +; x00: eori.b +; x00: and.l +; +; Should be: +; cmp.l +; smi +; since we are intereseted in sign bit only +; and.l in the end is superfluous + +define zeroext i1 @t6(i32 %a) { +entry: + %.lobit = lshr i32 %a, 31 + %trunc = trunc i32 %.lobit to i1 + %.not = xor i1 %trunc, 1 + ret i1 %.not +} Index: llvm/test/CodeGen/M680x0/ASM/Std/varargs.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/M680x0/ASM/Std/varargs.ll @@ -0,0 +1,31 @@ +; RUN: llc < %s -mtriple=m680x0-linux -verify-machineinstrs | FileCheck %s -check-prefix=x00 + +%struct.va_list = type { i8* } + +; x00-LABEL test: +; x00: lea (16,%sp), %a +; x00: add.l #4, %a0 +; x00: move.l %a0, (4,%sp) +define i32 @test(i32 %X, ...) { + ; Initialize variable argument processing + %ap = alloca %struct.va_list + %ap2 = bitcast %struct.va_list* %ap to i8* + call void @llvm.va_start(i8* %ap2) + + ; Read a single integer argument + %tmp = va_arg i8* %ap2, i32 + + ; Demonstrate usage of llvm.va_copy and llvm.va_end + %aq = alloca i8* + %aq2 = bitcast i8** %aq to i8* + call void @llvm.va_copy(i8* %aq2, i8* %ap2) + call void @llvm.va_end(i8* %aq2) + + ; Stop processing of arguments. + call void @llvm.va_end(i8* %ap2) + ret i32 %tmp +} + +declare void @llvm.va_start(i8*) +declare void @llvm.va_copy(i8*, i8*) +declare void @llvm.va_end(i8*)