Vendor import of llvm release_80 branch r353167:

https://llvm.org/svn/llvm-project/llvm/branches/release_80@353167
This commit is contained in:
Dimitry Andric 2019-02-05 18:38:58 +00:00
parent 3edec5c15a
commit e79719ce60
61 changed files with 1535 additions and 263 deletions

View File

@ -1280,7 +1280,6 @@ function(get_llvm_lit_path base_dir file_name)
cmake_parse_arguments(ARG "ALLOW_EXTERNAL" "" "" ${ARGN})
if (ARG_ALLOW_EXTERNAL)
set(LLVM_DEFAULT_EXTERNAL_LIT "${LLVM_EXTERNAL_LIT}")
set (LLVM_EXTERNAL_LIT "" CACHE STRING "Command used to spawn lit")
if ("${LLVM_EXTERNAL_LIT}" STREQUAL "")
set(LLVM_EXTERNAL_LIT "${LLVM_DEFAULT_EXTERNAL_LIT}")

View File

@ -48,6 +48,12 @@ Non-comprehensive list of changes in this release
functionality. See `Writing an LLVM Pass
<WritingAnLLVMPass.html#setting-up-the-build-environment>`_.
* For MinGW, references to data variables that might need to be imported
from a dll are accessed via a stub, to allow the linker to convert it to
a dllimport if needed.
* Added support for labels as offsets in ``.reloc`` directive.
.. NOTE
If you would like to document a larger change, then you can add a
subsection about it right here. You can copy the following boilerplate
@ -62,17 +68,44 @@ Changes to the LLVM IR
----------------------
Changes to the AArch64 Target
-----------------------------
* Added support for the ``.arch_extension`` assembler directive, just like
on ARM.
Changes to the ARM Backend
--------------------------
During this release ...
Changes to the Hexagon Target
--------------------------
* Added support for Hexagon/HVX V66 ISA.
Changes to the MIPS Target
--------------------------
During this release ...
* Improved support of GlobalISel instruction selection framework.
* Implemented emission of ``R_MIPS_JALR`` and ``R_MICROMIPS_JALR``
relocations. These relocations provide hints to a linker for optimization
of jumps to protected symbols.
* ORC JIT has been supported for MIPS and MIPS64 architectures.
* Assembler now suggests alternative MIPS instruction mnemonics when
an invalid one is specified.
* Improved support for MIPS N32 ABI.
* Added new instructions (``pll.ps``, ``plu.ps``, ``cvt.s.pu``,
``cvt.s.pl``, ``cvt.ps``, ``sigrie``).
* Numerous bug fixes and code cleanups.
Changes to the PowerPC Target
-----------------------------
@ -123,7 +156,16 @@ Changes to the DAG infrastructure
External Open Source Projects Using LLVM 8
==========================================
* A project...
Zig Programming Language
------------------------
`Zig <https://ziglang.org>`_ is a system programming language intended to be
an alternative to C. It provides high level features such as generics, compile
time function execution, and partial evaluation, while exposing low level LLVM
IR features such as aliases and intrinsics. Zig uses Clang to provide automatic
import of .h symbols, including inline functions and simple macros. Zig uses
LLD combined with lazily building compiler-rt to provide out-of-the-box
cross-compiling for all supported targets.
Additional Information

View File

@ -481,6 +481,7 @@ class Value {
mutable llvm::AlignedCharArrayUnion<bool, double, int64_t, llvm::StringRef,
std::string, json::Array, json::Object>
Union;
friend bool operator==(const Value &, const Value &);
};
bool operator==(const Value &, const Value &);

View File

@ -44,6 +44,11 @@ class FunctionImportGlobalProcessing {
/// to promote any non-renamable values.
SmallPtrSet<GlobalValue *, 8> Used;
/// Keep track of any COMDATs that require renaming (because COMDAT
/// leader was promoted and renamed). Maps from original COMDAT to one
/// with new name.
DenseMap<const Comdat *, Comdat *> RenamedComdats;
/// Check if we should promote the given local value to global scope.
bool shouldPromoteLocalToGlobal(const GlobalValue *SGV);

View File

@ -1836,7 +1836,10 @@ TypeIndex CodeViewDebug::lowerTypeMemberFunction(const DISubroutineType *Ty,
unsigned Index = 0;
SmallVector<TypeIndex, 8> ArgTypeIndices;
TypeIndex ReturnTypeIndex = getTypeIndex(ReturnAndArgs[Index++]);
TypeIndex ReturnTypeIndex = TypeIndex::Void();
if (ReturnAndArgs.size() > Index) {
ReturnTypeIndex = getTypeIndex(ReturnAndArgs[Index++]);
}
// If the first argument is a pointer type and this isn't a static method,
// treat it as the special 'this' parameter, which is encoded separately from

View File

@ -1956,8 +1956,10 @@ void DebugLocEntry::finalize(const AsmPrinter &AP,
void DwarfDebug::emitDebugLocEntryLocation(const DebugLocStream::Entry &Entry) {
// Emit the size.
Asm->OutStreamer->AddComment("Loc expr size");
Asm->emitInt16(DebugLocs.getBytes(Entry).size());
if (getDwarfVersion() >= 5)
Asm->EmitULEB128(DebugLocs.getBytes(Entry).size());
else
Asm->emitInt16(DebugLocs.getBytes(Entry).size());
// Emit the entry.
APByteStreamer Streamer(*Asm);
emitDebugLocEntry(Streamer, Entry);

View File

@ -225,12 +225,13 @@ void MachineInstr::addOperand(MachineFunction &MF, const MachineOperand &Op) {
}
#ifndef NDEBUG
bool isMetaDataOp = Op.getType() == MachineOperand::MO_Metadata;
bool isDebugOp = Op.getType() == MachineOperand::MO_Metadata ||
Op.getType() == MachineOperand::MO_MCSymbol;
// OpNo now points as the desired insertion point. Unless this is a variadic
// instruction, only implicit regs are allowed beyond MCID->getNumOperands().
// RegMask operands go between the explicit and implicit operands.
assert((isImpReg || Op.isRegMask() || MCID->isVariadic() ||
OpNo < MCID->getNumOperands() || isMetaDataOp) &&
OpNo < MCID->getNumOperands() || isDebugOp) &&
"Trying to add an operand to a machine instr that is already done!");
#endif

View File

@ -16214,23 +16214,29 @@ static SDValue reduceBuildVecToShuffleWithZero(SDNode *BV, SelectionDAG &DAG) {
// The build vector contains some number of undef elements and exactly
// one other element. That other element must be a zero-extended scalar
// extracted from a vector at a constant index to turn this into a shuffle.
// Also, require that the build vector does not implicitly truncate/extend
// its elements.
// TODO: This could be enhanced to allow ANY_EXTEND as well as ZERO_EXTEND.
EVT VT = BV->getValueType(0);
SDValue Zext = BV->getOperand(ZextElt);
if (Zext.getOpcode() != ISD::ZERO_EXTEND || !Zext.hasOneUse() ||
Zext.getOperand(0).getOpcode() != ISD::EXTRACT_VECTOR_ELT ||
!isa<ConstantSDNode>(Zext.getOperand(0).getOperand(1)))
!isa<ConstantSDNode>(Zext.getOperand(0).getOperand(1)) ||
Zext.getValueSizeInBits() != VT.getScalarSizeInBits())
return SDValue();
// The zero-extend must be a multiple of the source size.
// The zero-extend must be a multiple of the source size, and we must be
// building a vector of the same size as the source of the extract element.
SDValue Extract = Zext.getOperand(0);
unsigned DestSize = Zext.getValueSizeInBits();
unsigned SrcSize = Extract.getValueSizeInBits();
if (DestSize % SrcSize != 0)
if (DestSize % SrcSize != 0 ||
Extract.getOperand(0).getValueSizeInBits() != VT.getSizeInBits())
return SDValue();
// Create a shuffle mask that will combine the extracted element with zeros
// and undefs.
int ZextRatio = DestSize / SrcSize;
int ZextRatio = DestSize / SrcSize;
int NumMaskElts = NumBVOps * ZextRatio;
SmallVector<int, 32> ShufMask(NumMaskElts, -1);
for (int i = 0; i != NumMaskElts; ++i) {
@ -16260,7 +16266,7 @@ static SDValue reduceBuildVecToShuffleWithZero(SDNode *BV, SelectionDAG &DAG) {
SDValue ZeroVec = DAG.getConstant(0, DL, VecVT);
SDValue Shuf = DAG.getVectorShuffle(VecVT, DL, Extract.getOperand(0), ZeroVec,
ShufMask);
return DAG.getBitcast(BV->getValueType(0), Shuf);
return DAG.getBitcast(VT, Shuf);
}
// Check to see if this is a BUILD_VECTOR of a bunch of EXTRACT_VECTOR_ELT

View File

@ -184,7 +184,8 @@ DWARFDebugLoclists::parseOneLocationList(DataExtractor Data, unsigned *Offset,
}
if (Kind != dwarf::DW_LLE_base_address) {
unsigned Bytes = Data.getU16(Offset);
unsigned Bytes =
Version >= 5 ? Data.getULEB128(Offset) : Data.getU16(Offset);
// A single location description describing the location of the object...
StringRef str = Data.getData().substr(*Offset, Bytes);
*Offset += Bytes;

View File

@ -469,6 +469,11 @@ static bool UpgradeX86IntrinsicFunction(Function *F, StringRef Name,
}
}
if (Name == "seh.recoverfp") {
NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::eh_recoverfp);
return true;
}
return false;
}
@ -544,10 +549,6 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) {
NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::thread_pointer);
return true;
}
if (Name == "x86.seh.recoverfp") {
NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::eh_recoverfp);
return true;
}
break;
}

View File

@ -182,6 +182,12 @@ bool operator==(const Value &L, const Value &R) {
case Value::Boolean:
return *L.getAsBoolean() == *R.getAsBoolean();
case Value::Number:
// Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=323
// The same integer must convert to the same double, per the standard.
// However we see 64-vs-80-bit precision comparisons with gcc-7 -O3 -m32.
// So we avoid floating point promotion for exact comparisons.
if (L.Type == Value::T_Integer || R.Type == Value::T_Integer)
return L.getAsInteger() == R.getAsInteger();
return *L.getAsNumber() == *R.getAsNumber();
case Value::String:
return *L.getAsString() == *R.getAsString();

View File

@ -103,6 +103,7 @@
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/Pass.h"
#include "llvm/Support/CodeGen.h"
@ -146,25 +147,31 @@ class AArch64SpeculationHardening : public MachineFunctionPass {
BitVector RegsAlreadyMasked;
bool functionUsesHardeningRegister(MachineFunction &MF) const;
bool instrumentControlFlow(MachineBasicBlock &MBB);
bool instrumentControlFlow(MachineBasicBlock &MBB,
bool &UsesFullSpeculationBarrier);
bool endsWithCondControlFlow(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
MachineBasicBlock *&FBB,
AArch64CC::CondCode &CondCode) const;
void insertTrackingCode(MachineBasicBlock &SplitEdgeBB,
AArch64CC::CondCode &CondCode, DebugLoc DL) const;
void insertSPToRegTaintPropagation(MachineBasicBlock *MBB,
void insertSPToRegTaintPropagation(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI) const;
void insertRegToSPTaintPropagation(MachineBasicBlock *MBB,
void insertRegToSPTaintPropagation(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
unsigned TmpReg) const;
void insertFullSpeculationBarrier(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
DebugLoc DL) const;
bool slhLoads(MachineBasicBlock &MBB);
bool makeGPRSpeculationSafe(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
MachineInstr &MI, unsigned Reg);
bool lowerSpeculationSafeValuePseudos(MachineBasicBlock &MBB);
bool lowerSpeculationSafeValuePseudos(MachineBasicBlock &MBB,
bool UsesFullSpeculationBarrier);
bool expandSpeculationSafeValue(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI);
MachineBasicBlock::iterator MBBI,
bool UsesFullSpeculationBarrier);
bool insertCSDB(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
DebugLoc DL);
};
@ -207,15 +214,19 @@ bool AArch64SpeculationHardening::endsWithCondControlFlow(
return true;
}
void AArch64SpeculationHardening::insertFullSpeculationBarrier(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
DebugLoc DL) const {
// A full control flow speculation barrier consists of (DSB SYS + ISB)
BuildMI(MBB, MBBI, DL, TII->get(AArch64::DSB)).addImm(0xf);
BuildMI(MBB, MBBI, DL, TII->get(AArch64::ISB)).addImm(0xf);
}
void AArch64SpeculationHardening::insertTrackingCode(
MachineBasicBlock &SplitEdgeBB, AArch64CC::CondCode &CondCode,
DebugLoc DL) const {
if (UseControlFlowSpeculationBarrier) {
// insert full control flow speculation barrier (DSB SYS + ISB)
BuildMI(SplitEdgeBB, SplitEdgeBB.begin(), DL, TII->get(AArch64::ISB))
.addImm(0xf);
BuildMI(SplitEdgeBB, SplitEdgeBB.begin(), DL, TII->get(AArch64::DSB))
.addImm(0xf);
insertFullSpeculationBarrier(SplitEdgeBB, SplitEdgeBB.begin(), DL);
} else {
BuildMI(SplitEdgeBB, SplitEdgeBB.begin(), DL, TII->get(AArch64::CSELXr))
.addDef(MisspeculatingTaintReg)
@ -227,7 +238,7 @@ void AArch64SpeculationHardening::insertTrackingCode(
}
bool AArch64SpeculationHardening::instrumentControlFlow(
MachineBasicBlock &MBB) {
MachineBasicBlock &MBB, bool &UsesFullSpeculationBarrier) {
LLVM_DEBUG(dbgs() << "Instrument control flow tracking on MBB: " << MBB);
bool Modified = false;
@ -263,55 +274,105 @@ bool AArch64SpeculationHardening::instrumentControlFlow(
}
// Perform correct code generation around function calls and before returns.
{
SmallVector<MachineInstr *, 4> ReturnInstructions;
SmallVector<MachineInstr *, 4> CallInstructions;
// The below variables record the return/terminator instructions and the call
// instructions respectively; including which register is available as a
// temporary register just before the recorded instructions.
SmallVector<std::pair<MachineInstr *, unsigned>, 4> ReturnInstructions;
SmallVector<std::pair<MachineInstr *, unsigned>, 4> CallInstructions;
// if a temporary register is not available for at least one of the
// instructions for which we need to transfer taint to the stack pointer, we
// need to insert a full speculation barrier.
// TmpRegisterNotAvailableEverywhere tracks that condition.
bool TmpRegisterNotAvailableEverywhere = false;
for (MachineInstr &MI : MBB) {
if (MI.isReturn())
ReturnInstructions.push_back(&MI);
else if (MI.isCall())
CallInstructions.push_back(&MI);
}
RegScavenger RS;
RS.enterBasicBlock(MBB);
Modified |=
(ReturnInstructions.size() > 0) || (CallInstructions.size() > 0);
for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); I++) {
MachineInstr &MI = *I;
if (!MI.isReturn() && !MI.isCall())
continue;
for (MachineInstr *Return : ReturnInstructions)
insertRegToSPTaintPropagation(Return->getParent(), Return, AArch64::X17);
for (MachineInstr *Call : CallInstructions) {
// Just after the call:
MachineBasicBlock::iterator i = Call;
i++;
insertSPToRegTaintPropagation(Call->getParent(), i);
// Just before the call:
insertRegToSPTaintPropagation(Call->getParent(), Call, AArch64::X17);
}
// The RegScavenger represents registers available *after* the MI
// instruction pointed to by RS.getCurrentPosition().
// We need to have a register that is available *before* the MI is executed.
if (I != MBB.begin())
RS.forward(std::prev(I));
// FIXME: The below just finds *a* unused register. Maybe code could be
// optimized more if this looks for the register that isn't used for the
// longest time around this place, to enable more scheduling freedom. Not
// sure if that would actually result in a big performance difference
// though. Maybe RegisterScavenger::findSurvivorBackwards has some logic
// already to do this - but it's unclear if that could easily be used here.
unsigned TmpReg = RS.FindUnusedReg(&AArch64::GPR64commonRegClass);
LLVM_DEBUG(dbgs() << "RS finds "
<< ((TmpReg == 0) ? "no register " : "register ");
if (TmpReg != 0) dbgs() << printReg(TmpReg, TRI) << " ";
dbgs() << "to be available at MI " << MI);
if (TmpReg == 0)
TmpRegisterNotAvailableEverywhere = true;
if (MI.isReturn())
ReturnInstructions.push_back({&MI, TmpReg});
else if (MI.isCall())
CallInstructions.push_back({&MI, TmpReg});
}
if (TmpRegisterNotAvailableEverywhere) {
// When a temporary register is not available everywhere in this basic
// basic block where a propagate-taint-to-sp operation is needed, just
// emit a full speculation barrier at the start of this basic block, which
// renders the taint/speculation tracking in this basic block unnecessary.
insertFullSpeculationBarrier(MBB, MBB.begin(),
(MBB.begin())->getDebugLoc());
UsesFullSpeculationBarrier = true;
Modified = true;
} else {
for (auto MI_Reg : ReturnInstructions) {
assert(MI_Reg.second != 0);
LLVM_DEBUG(
dbgs()
<< " About to insert Reg to SP taint propagation with temp register "
<< printReg(MI_Reg.second, TRI)
<< " on instruction: " << *MI_Reg.first);
insertRegToSPTaintPropagation(MBB, MI_Reg.first, MI_Reg.second);
Modified = true;
}
for (auto MI_Reg : CallInstructions) {
assert(MI_Reg.second != 0);
LLVM_DEBUG(dbgs() << " About to insert Reg to SP and back taint "
"propagation with temp register "
<< printReg(MI_Reg.second, TRI)
<< " around instruction: " << *MI_Reg.first);
// Just after the call:
insertSPToRegTaintPropagation(
MBB, std::next((MachineBasicBlock::iterator)MI_Reg.first));
// Just before the call:
insertRegToSPTaintPropagation(MBB, MI_Reg.first, MI_Reg.second);
Modified = true;
}
}
return Modified;
}
void AArch64SpeculationHardening::insertSPToRegTaintPropagation(
MachineBasicBlock *MBB, MachineBasicBlock::iterator MBBI) const {
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) const {
// If full control flow speculation barriers are used, emit a control flow
// barrier to block potential miss-speculation in flight coming in to this
// function.
if (UseControlFlowSpeculationBarrier) {
// insert full control flow speculation barrier (DSB SYS + ISB)
BuildMI(*MBB, MBBI, DebugLoc(), TII->get(AArch64::DSB)).addImm(0xf);
BuildMI(*MBB, MBBI, DebugLoc(), TII->get(AArch64::ISB)).addImm(0xf);
insertFullSpeculationBarrier(MBB, MBBI, DebugLoc());
return;
}
// CMP SP, #0 === SUBS xzr, SP, #0
BuildMI(*MBB, MBBI, DebugLoc(), TII->get(AArch64::SUBSXri))
BuildMI(MBB, MBBI, DebugLoc(), TII->get(AArch64::SUBSXri))
.addDef(AArch64::XZR)
.addUse(AArch64::SP)
.addImm(0)
.addImm(0); // no shift
// CSETM x16, NE === CSINV x16, xzr, xzr, EQ
BuildMI(*MBB, MBBI, DebugLoc(), TII->get(AArch64::CSINVXr))
BuildMI(MBB, MBBI, DebugLoc(), TII->get(AArch64::CSINVXr))
.addDef(MisspeculatingTaintReg)
.addUse(AArch64::XZR)
.addUse(AArch64::XZR)
@ -319,7 +380,7 @@ void AArch64SpeculationHardening::insertSPToRegTaintPropagation(
}
void AArch64SpeculationHardening::insertRegToSPTaintPropagation(
MachineBasicBlock *MBB, MachineBasicBlock::iterator MBBI,
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
unsigned TmpReg) const {
// If full control flow speculation barriers are used, there will not be
// miss-speculation when returning from this function, and therefore, also
@ -328,19 +389,19 @@ void AArch64SpeculationHardening::insertRegToSPTaintPropagation(
return;
// mov Xtmp, SP === ADD Xtmp, SP, #0
BuildMI(*MBB, MBBI, DebugLoc(), TII->get(AArch64::ADDXri))
BuildMI(MBB, MBBI, DebugLoc(), TII->get(AArch64::ADDXri))
.addDef(TmpReg)
.addUse(AArch64::SP)
.addImm(0)
.addImm(0); // no shift
// and Xtmp, Xtmp, TaintReg === AND Xtmp, Xtmp, TaintReg, #0
BuildMI(*MBB, MBBI, DebugLoc(), TII->get(AArch64::ANDXrs))
BuildMI(MBB, MBBI, DebugLoc(), TII->get(AArch64::ANDXrs))
.addDef(TmpReg, RegState::Renamable)
.addUse(TmpReg, RegState::Kill | RegState::Renamable)
.addUse(MisspeculatingTaintReg, RegState::Kill)
.addImm(0);
// mov SP, Xtmp === ADD SP, Xtmp, #0
BuildMI(*MBB, MBBI, DebugLoc(), TII->get(AArch64::ADDXri))
BuildMI(MBB, MBBI, DebugLoc(), TII->get(AArch64::ADDXri))
.addDef(AArch64::SP)
.addUse(TmpReg, RegState::Kill)
.addImm(0)
@ -484,7 +545,8 @@ bool AArch64SpeculationHardening::slhLoads(MachineBasicBlock &MBB) {
/// \brief If MBBI references a pseudo instruction that should be expanded
/// here, do the expansion and return true. Otherwise return false.
bool AArch64SpeculationHardening::expandSpeculationSafeValue(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) {
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
bool UsesFullSpeculationBarrier) {
MachineInstr &MI = *MBBI;
unsigned Opcode = MI.getOpcode();
bool Is64Bit = true;
@ -499,7 +561,7 @@ bool AArch64SpeculationHardening::expandSpeculationSafeValue(
// Just remove the SpeculationSafe pseudo's if control flow
// miss-speculation isn't happening because we're already inserting barriers
// to guarantee that.
if (!UseControlFlowSpeculationBarrier) {
if (!UseControlFlowSpeculationBarrier && !UsesFullSpeculationBarrier) {
unsigned DstReg = MI.getOperand(0).getReg();
unsigned SrcReg = MI.getOperand(1).getReg();
// Mark this register and all its aliasing registers as needing to be
@ -537,7 +599,7 @@ bool AArch64SpeculationHardening::insertCSDB(MachineBasicBlock &MBB,
}
bool AArch64SpeculationHardening::lowerSpeculationSafeValuePseudos(
MachineBasicBlock &MBB) {
MachineBasicBlock &MBB, bool UsesFullSpeculationBarrier) {
bool Modified = false;
RegsNeedingCSDBBeforeUse.reset();
@ -572,15 +634,16 @@ bool AArch64SpeculationHardening::lowerSpeculationSafeValuePseudos(
break;
}
if (NeedToEmitBarrier)
if (NeedToEmitBarrier && !UsesFullSpeculationBarrier)
Modified |= insertCSDB(MBB, MBBI, DL);
Modified |= expandSpeculationSafeValue(MBB, MBBI);
Modified |=
expandSpeculationSafeValue(MBB, MBBI, UsesFullSpeculationBarrier);
MBBI = NMBBI;
}
if (RegsNeedingCSDBBeforeUse.any())
if (RegsNeedingCSDBBeforeUse.any() && !UsesFullSpeculationBarrier)
Modified |= insertCSDB(MBB, MBBI, DL);
return Modified;
@ -609,7 +672,7 @@ bool AArch64SpeculationHardening::runOnMachineFunction(MachineFunction &MF) {
Modified |= slhLoads(MBB);
}
// 2.a Add instrumentation code to function entry and exits.
// 2. Add instrumentation code to function entry and exits.
LLVM_DEBUG(
dbgs()
<< "***** AArch64SpeculationHardening - track control flow *****\n");
@ -620,17 +683,15 @@ bool AArch64SpeculationHardening::runOnMachineFunction(MachineFunction &MF) {
EntryBlocks.push_back(LPI.LandingPadBlock);
for (auto Entry : EntryBlocks)
insertSPToRegTaintPropagation(
Entry, Entry->SkipPHIsLabelsAndDebug(Entry->begin()));
*Entry, Entry->SkipPHIsLabelsAndDebug(Entry->begin()));
// 2.b Add instrumentation code to every basic block.
for (auto &MBB : MF)
Modified |= instrumentControlFlow(MBB);
LLVM_DEBUG(dbgs() << "***** AArch64SpeculationHardening - Lowering "
"SpeculationSafeValue Pseudos *****\n");
// Step 3: Lower SpeculationSafeValue pseudo instructions.
for (auto &MBB : MF)
Modified |= lowerSpeculationSafeValuePseudos(MBB);
// 3. Add instrumentation code to every basic block.
for (auto &MBB : MF) {
bool UsesFullSpeculationBarrier = false;
Modified |= instrumentControlFlow(MBB, UsesFullSpeculationBarrier);
Modified |=
lowerSpeculationSafeValuePseudos(MBB, UsesFullSpeculationBarrier);
}
return Modified;
}

View File

@ -65,10 +65,7 @@ class MCInstrInfo;
} // end namespace llvm
static cl::opt<bool>
EmitJalrReloc("mips-jalr-reloc", cl::Hidden,
cl::desc("MIPS: Emit R_{MICRO}MIPS_JALR relocation with jalr"),
cl::init(true));
extern cl::opt<bool> EmitJalrReloc;
namespace {

View File

@ -15,6 +15,13 @@
using namespace llvm;
// Note: this option is defined here to be visible from libLLVMMipsAsmParser
// and libLLVMMipsCodeGen
cl::opt<bool>
EmitJalrReloc("mips-jalr-reloc", cl::Hidden,
cl::desc("MIPS: Emit R_{MICRO}MIPS_JALR relocation with jalr"),
cl::init(true));
namespace {
static const MCPhysReg O32IntRegs[4] = {Mips::A0, Mips::A1, Mips::A2, Mips::A3};

View File

@ -89,7 +89,10 @@ namespace MipsII {
MO_GOT_HI16,
MO_GOT_LO16,
MO_CALL_HI16,
MO_CALL_LO16
MO_CALL_LO16,
/// Helper operand used to generate R_MIPS_JALR
MO_JALR
};
enum {

View File

@ -614,8 +614,9 @@ getExprOpValue(const MCExpr *Expr, SmallVectorImpl<MCFixup> &Fixups,
llvm_unreachable("Unhandled fixup kind!");
break;
case MipsMCExpr::MEK_DTPREL:
llvm_unreachable("MEK_DTPREL is used for TLS DIEExpr only");
break;
// MEK_DTPREL is used for marking TLS DIEExpr only
// and contains a regular sub-expression.
return getExprOpValue(MipsExpr->getSubExpr(), Fixups, STI);
case MipsMCExpr::MEK_CALL_HI16:
FixupKind = Mips::fixup_Mips_CALL_HI16;
break;

View File

@ -44,8 +44,10 @@ void MipsMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
llvm_unreachable("MEK_None and MEK_Special are invalid");
break;
case MEK_DTPREL:
llvm_unreachable("MEK_DTPREL is used for TLS DIEExpr only");
break;
// MEK_DTPREL is used for marking TLS DIEExpr only
// and contains a regular sub-expression.
getSubExpr()->print(OS, MAI, true);
return;
case MEK_CALL_HI16:
OS << "%call_hi";
break;
@ -161,7 +163,9 @@ MipsMCExpr::evaluateAsRelocatableImpl(MCValue &Res,
case MEK_Special:
llvm_unreachable("MEK_None and MEK_Special are invalid");
case MEK_DTPREL:
llvm_unreachable("MEK_DTPREL is used for TLS DIEExpr only");
// MEK_DTPREL is used for marking TLS DIEExpr only
// and contains a regular sub-expression.
return getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup);
case MEK_DTPREL_HI:
case MEK_DTPREL_LO:
case MEK_GOT:
@ -249,9 +253,6 @@ void MipsMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {
case MEK_Special:
llvm_unreachable("MEK_None and MEK_Special are invalid");
break;
case MEK_DTPREL:
llvm_unreachable("MEK_DTPREL is used for TLS DIEExpr only");
break;
case MEK_CALL_HI16:
case MEK_CALL_LO16:
case MEK_GOT:
@ -274,6 +275,7 @@ void MipsMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {
if (const MipsMCExpr *E = dyn_cast<const MipsMCExpr>(getSubExpr()))
E->fixELFSymbolsInTLSFixups(Asm);
break;
case MEK_DTPREL:
case MEK_DTPREL_HI:
case MEK_DTPREL_LO:
case MEK_TLSLDM:

View File

@ -460,6 +460,7 @@ class JALRC16_MMR6_DESC_BASE<string opstr, RegisterOperand RO>
let isCall = 1;
let hasDelaySlot = 0;
let Defs = [RA];
let hasPostISelHook = 1;
}
class JALRC16_MMR6_DESC : JALRC16_MMR6_DESC_BASE<"jalr", GPR32Opnd>;

View File

@ -426,6 +426,7 @@ class JumpLinkRegMM16<string opstr, RegisterOperand RO> :
let isCall = 1;
let hasDelaySlot = 1;
let Defs = [RA];
let hasPostISelHook = 1;
}
// 16-bit Jump Reg

View File

@ -1105,7 +1105,7 @@ def : MipsPat<(select i32:$cond, immz, i32:$f),
// Pseudo instructions
let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, hasDelaySlot = 1,
hasExtraSrcRegAllocReq = 1, isCTI = 1, Defs = [AT] in {
hasExtraSrcRegAllocReq = 1, isCTI = 1, Defs = [AT], hasPostISelHook = 1 in {
class TailCallRegR6<Instruction JumpInst, Register RT, RegisterOperand RO> :
PseudoSE<(outs), (ins RO:$rs), [(MipsTailCall RO:$rs)], II_JR>,
PseudoInstExpansion<(JumpInst RT:$rt, RO:$rs)>;

View File

@ -68,6 +68,8 @@ using namespace llvm;
#define DEBUG_TYPE "mips-asm-printer"
extern cl::opt<bool> EmitJalrReloc;
MipsTargetStreamer &MipsAsmPrinter::getTargetStreamer() const {
return static_cast<MipsTargetStreamer &>(*OutStreamer->getTargetStreamer());
}
@ -148,6 +150,40 @@ void MipsAsmPrinter::emitPseudoIndirectBranch(MCStreamer &OutStreamer,
EmitToStreamer(OutStreamer, TmpInst0);
}
// If there is an MO_JALR operand, insert:
//
// .reloc tmplabel, R_{MICRO}MIPS_JALR, symbol
// tmplabel:
//
// This is an optimization hint for the linker which may then replace
// an indirect call with a direct branch.
static void emitDirectiveRelocJalr(const MachineInstr &MI,
MCContext &OutContext,
TargetMachine &TM,
MCStreamer &OutStreamer,
const MipsSubtarget &Subtarget) {
for (unsigned int I = MI.getDesc().getNumOperands(), E = MI.getNumOperands();
I < E; ++I) {
MachineOperand MO = MI.getOperand(I);
if (MO.isMCSymbol() && (MO.getTargetFlags() & MipsII::MO_JALR)) {
MCSymbol *Callee = MO.getMCSymbol();
if (Callee && !Callee->getName().empty()) {
MCSymbol *OffsetLabel = OutContext.createTempSymbol();
const MCExpr *OffsetExpr =
MCSymbolRefExpr::create(OffsetLabel, OutContext);
const MCExpr *CaleeExpr =
MCSymbolRefExpr::create(Callee, OutContext);
OutStreamer.EmitRelocDirective
(*OffsetExpr,
Subtarget.inMicroMipsMode() ? "R_MICROMIPS_JALR" : "R_MIPS_JALR",
CaleeExpr, SMLoc(), *TM.getMCSubtargetInfo());
OutStreamer.EmitLabel(OffsetLabel);
return;
}
}
}
}
void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) {
MipsTargetStreamer &TS = getTargetStreamer();
unsigned Opc = MI->getOpcode();
@ -207,6 +243,11 @@ void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) {
return;
}
if (EmitJalrReloc &&
(MI->isReturn() || MI->isCall() || MI->isIndirectBranch())) {
emitDirectiveRelocJalr(*MI, OutContext, TM, *OutStreamer, *Subtarget);
}
MachineBasicBlock::const_instr_iterator I = MI->getIterator();
MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end();

View File

@ -56,6 +56,7 @@
#include "llvm/IR/Type.h"
#include "llvm/IR/User.h"
#include "llvm/IR/Value.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCInstrDesc.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSymbol.h"
@ -75,6 +76,8 @@
using namespace llvm;
extern cl::opt<bool> EmitJalrReloc;
namespace {
class MipsFastISel final : public FastISel {
@ -1551,6 +1554,16 @@ bool MipsFastISel::fastLowerCall(CallLoweringInfo &CLI) {
CLI.Call = MIB;
if (EmitJalrReloc && !Subtarget->inMips16Mode()) {
// Attach callee address to the instruction, let asm printer emit
// .reloc R_MIPS_JALR.
if (Symbol)
MIB.addSym(Symbol, MipsII::MO_JALR);
else
MIB.addSym(FuncInfo.MF->getContext().getOrCreateSymbol(
Addr.getGlobalValue()->getName()), MipsII::MO_JALR);
}
// Finish off the call including any return values.
return finishCall(CLI, RetVT, NumBytes);
}

View File

@ -57,6 +57,7 @@
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Value.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CodeGen.h"
@ -91,6 +92,8 @@ NoZeroDivCheck("mno-check-zero-division", cl::Hidden,
cl::desc("MIPS: Don't trap on integer division by zero."),
cl::init(false));
extern cl::opt<bool> EmitJalrReloc;
static const MCPhysReg Mips64DPRegs[8] = {
Mips::D12_64, Mips::D13_64, Mips::D14_64, Mips::D15_64,
Mips::D16_64, Mips::D17_64, Mips::D18_64, Mips::D19_64
@ -2879,6 +2882,54 @@ getOpndList(SmallVectorImpl<SDValue> &Ops,
Ops.push_back(InFlag);
}
void MipsTargetLowering::AdjustInstrPostInstrSelection(MachineInstr &MI,
SDNode *Node) const {
switch (MI.getOpcode()) {
default:
return;
case Mips::JALR:
case Mips::JALRPseudo:
case Mips::JALR64:
case Mips::JALR64Pseudo:
case Mips::JALR16_MM:
case Mips::JALRC16_MMR6:
case Mips::TAILCALLREG:
case Mips::TAILCALLREG64:
case Mips::TAILCALLR6REG:
case Mips::TAILCALL64R6REG:
case Mips::TAILCALLREG_MM:
case Mips::TAILCALLREG_MMR6: {
if (!EmitJalrReloc ||
Subtarget.inMips16Mode() ||
!isPositionIndependent() ||
Node->getNumOperands() < 1 ||
Node->getOperand(0).getNumOperands() < 2) {
return;
}
// We are after the callee address, set by LowerCall().
// If added to MI, asm printer will emit .reloc R_MIPS_JALR for the
// symbol.
const SDValue TargetAddr = Node->getOperand(0).getOperand(1);
StringRef Sym;
if (const GlobalAddressSDNode *G =
dyn_cast_or_null<const GlobalAddressSDNode>(TargetAddr)) {
Sym = G->getGlobal()->getName();
}
else if (const ExternalSymbolSDNode *ES =
dyn_cast_or_null<const ExternalSymbolSDNode>(TargetAddr)) {
Sym = ES->getSymbol();
}
if (Sym.empty())
return;
MachineFunction *MF = MI.getParent()->getParent();
MCSymbol *S = MF->getContext().getOrCreateSymbol(Sym);
MI.addOperand(MachineOperand::CreateMCSymbol(S, MipsII::MO_JALR));
}
}
}
/// LowerCall - functions arguments are copied from virtual regs to
/// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted.
SDValue
@ -2930,7 +2981,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
// the maximum out going argument area (including the reserved area), and
// preallocates the stack space on entrance to the caller.
//
// FIXME: We should do the same for efficency and space.
// FIXME: We should do the same for efficiency and space.
// Note: The check on the calling convention below must match
// MipsABIInfo::GetCalleeAllocdArgSizeInBytes().

View File

@ -341,6 +341,9 @@ class TargetRegisterClass;
EmitInstrWithCustomInserter(MachineInstr &MI,
MachineBasicBlock *MBB) const override;
void AdjustInstrPostInstrSelection(MachineInstr &MI,
SDNode *Node) const override;
void HandleByVal(CCState *, unsigned &, unsigned) const override;
unsigned getRegisterByName(const char* RegName, EVT VT,

View File

@ -653,6 +653,16 @@ MipsInstrInfo::genInstrWithNewOpc(unsigned NewOpc,
MIB.addImm(0);
// If I has an MCSymbol operand (used by asm printer, to emit R_MIPS_JALR),
// add it to the new instruction.
for (unsigned J = I->getDesc().getNumOperands(), E = I->getNumOperands();
J < E; ++J) {
const MachineOperand &MO = I->getOperand(J);
if (MO.isMCSymbol() && (MO.getTargetFlags() & MipsII::MO_JALR))
MIB.addSym(MO.getMCSymbol(), MipsII::MO_JALR);
}
} else {
for (unsigned J = 0, E = I->getDesc().getNumOperands(); J < E; ++J) {
if (BranchWithZeroOperand && (unsigned)ZeroOperandPosition == J)
@ -825,7 +835,8 @@ MipsInstrInfo::getSerializableDirectMachineOperandTargetFlags() const {
{MO_GOT_HI16, "mips-got-hi16"},
{MO_GOT_LO16, "mips-got-lo16"},
{MO_CALL_HI16, "mips-call-hi16"},
{MO_CALL_LO16, "mips-call-lo16"}
{MO_CALL_LO16, "mips-call-lo16"},
{MO_JALR, "mips-jalr"}
};
return makeArrayRef(Flags);
}

View File

@ -1623,11 +1623,15 @@ let isCall=1, hasDelaySlot=1, isCTI=1, Defs = [RA] in {
class JumpLinkRegPseudo<RegisterOperand RO, Instruction JALRInst,
Register RetReg, RegisterOperand ResRO = RO>:
PseudoSE<(outs), (ins RO:$rs), [(MipsJmpLink RO:$rs)], II_JALR>,
PseudoInstExpansion<(JALRInst RetReg, ResRO:$rs)>;
PseudoInstExpansion<(JALRInst RetReg, ResRO:$rs)> {
let hasPostISelHook = 1;
}
class JumpLinkReg<string opstr, RegisterOperand RO>:
InstSE<(outs RO:$rd), (ins RO:$rs), !strconcat(opstr, "\t$rd, $rs"),
[], II_JALR, FrmR, opstr>;
[], II_JALR, FrmR, opstr> {
let hasPostISelHook = 1;
}
class BGEZAL_FT<string opstr, DAGOperand opnd,
RegisterOperand RO> :
@ -1646,7 +1650,9 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, hasDelaySlot = 1,
class TailCallReg<Instruction JumpInst, RegisterOperand RO> :
PseudoSE<(outs), (ins RO:$rs), [(MipsTailCall RO:$rs)], II_JR>,
PseudoInstExpansion<(JumpInst RO:$rs)>;
PseudoInstExpansion<(JumpInst RO:$rs)> {
let hasPostISelHook = 1;
}
}
class BAL_BR_Pseudo<Instruction RealInst, DAGOperand opnd> :

View File

@ -117,6 +117,8 @@ MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
case MipsII::MO_CALL_LO16:
TargetKind = MipsMCExpr::MEK_CALL_LO16;
break;
case MipsII::MO_JALR:
return MCOperand();
}
switch (MOTy) {

View File

@ -27,6 +27,14 @@ using namespace llvm;
#define DEBUG_TYPE "x86-discriminate-memops"
static cl::opt<bool> EnableDiscriminateMemops(
DEBUG_TYPE, cl::init(false),
cl::desc("Generate unique debug info for each instruction with a memory "
"operand. Should be enabled for profile-drived cache prefetching, "
"both in the build of the binary being profiled, as well as in "
"the build of the binary consuming the profile."),
cl::Hidden);
namespace {
using Location = std::pair<StringRef, unsigned>;
@ -67,6 +75,9 @@ char X86DiscriminateMemOps::ID = 0;
X86DiscriminateMemOps::X86DiscriminateMemOps() : MachineFunctionPass(ID) {}
bool X86DiscriminateMemOps::runOnMachineFunction(MachineFunction &MF) {
if (!EnableDiscriminateMemops)
return false;
DISubprogram *FDI = MF.getFunction().getSubprogram();
if (!FDI || !FDI->getUnit()->getDebugInfoForProfiling())
return false;

View File

@ -34,7 +34,8 @@ using namespace sampleprof;
static cl::opt<std::string>
PrefetchHintsFile("prefetch-hints-file",
cl::desc("Path to the prefetch hints profile."),
cl::desc("Path to the prefetch hints profile. See also "
"-x86-discriminate-memops"),
cl::Hidden);
namespace {

View File

@ -249,6 +249,8 @@ void FunctionImportGlobalProcessing::processGlobalForThinLTO(GlobalValue &GV) {
bool DoPromote = false;
if (GV.hasLocalLinkage() &&
((DoPromote = shouldPromoteLocalToGlobal(&GV)) || isPerformingImport())) {
// Save the original name string before we rename GV below.
auto Name = GV.getName().str();
// Once we change the name or linkage it is difficult to determine
// again whether we should promote since shouldPromoteLocalToGlobal needs
// to locate the summary (based on GUID from name and linkage). Therefore,
@ -257,6 +259,12 @@ void FunctionImportGlobalProcessing::processGlobalForThinLTO(GlobalValue &GV) {
GV.setLinkage(getLinkage(&GV, DoPromote));
if (!GV.hasLocalLinkage())
GV.setVisibility(GlobalValue::HiddenVisibility);
// If we are renaming a COMDAT leader, ensure that we record the COMDAT
// for later renaming as well. This is required for COFF.
if (const auto *C = GV.getComdat())
if (C->getName() == Name)
RenamedComdats.try_emplace(C, M.getOrInsertComdat(GV.getName()));
} else
GV.setLinkage(getLinkage(&GV, /* DoPromote */ false));
@ -281,6 +289,16 @@ void FunctionImportGlobalProcessing::processGlobalsForThinLTO() {
processGlobalForThinLTO(SF);
for (GlobalAlias &GA : M.aliases())
processGlobalForThinLTO(GA);
// Replace any COMDATS that required renaming (because the COMDAT leader was
// promoted and renamed).
if (!RenamedComdats.empty())
for (auto &GO : M.global_objects())
if (auto *C = GO.getComdat()) {
auto Replacement = RenamedComdats.find(C);
if (Replacement != RenamedComdats.end())
GO.setComdat(Replacement->second);
}
}
bool FunctionImportGlobalProcessing::run() {

View File

@ -217,7 +217,10 @@ static Optional<bool> getOptionalBoolLoopAttribute(const Loop *TheLoop,
// When the value is absent it is interpreted as 'attribute set'.
return true;
case 2:
return mdconst::extract_or_null<ConstantInt>(MD->getOperand(1).get());
if (ConstantInt *IntMD =
mdconst::extract_or_null<ConstantInt>(MD->getOperand(1).get()))
return IntMD->getZExtValue();
return true;
}
llvm_unreachable("unexpected number of options");
}
@ -376,17 +379,17 @@ TransformationMode llvm::hasVectorizeTransformation(Loop *L) {
Optional<int> InterleaveCount =
getOptionalIntLoopAttribute(L, "llvm.loop.interleave.count");
if (Enable == true) {
// 'Forcing' vector width and interleave count to one effectively disables
// this tranformation.
if (VectorizeWidth == 1 && InterleaveCount == 1)
return TM_SuppressedByUser;
return TM_ForcedByUser;
}
// 'Forcing' vector width and interleave count to one effectively disables
// this tranformation.
if (Enable == true && VectorizeWidth == 1 && InterleaveCount == 1)
return TM_SuppressedByUser;
if (getBooleanLoopAttribute(L, "llvm.loop.isvectorized"))
return TM_Disable;
if (Enable == true)
return TM_ForcedByUser;
if (VectorizeWidth == 1 && InterleaveCount == 1)
return TM_Disable;

View File

@ -0,0 +1,441 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=aarch64-- | FileCheck %s
define <2 x i64> @extract0_i32_zext_insert0_i64_undef(<4 x i32> %x) {
; CHECK-LABEL: extract0_i32_zext_insert0_i64_undef:
; CHECK: // %bb.0:
; CHECK-NEXT: movi v1.2d, #0000000000000000
; CHECK-NEXT: zip1 v0.4s, v0.4s, v1.4s
; CHECK-NEXT: ret
%e = extractelement <4 x i32> %x, i32 0
%z = zext i32 %e to i64
%r = insertelement <2 x i64> undef, i64 %z, i32 0
ret <2 x i64> %r
}
define <2 x i64> @extract0_i32_zext_insert0_i64_zero(<4 x i32> %x) {
; CHECK-LABEL: extract0_i32_zext_insert0_i64_zero:
; CHECK: // %bb.0:
; CHECK-NEXT: fmov w8, s0
; CHECK-NEXT: movi v0.2d, #0000000000000000
; CHECK-NEXT: mov v0.d[0], x8
; CHECK-NEXT: ret
%e = extractelement <4 x i32> %x, i32 0
%z = zext i32 %e to i64
%r = insertelement <2 x i64> zeroinitializer, i64 %z, i32 0
ret <2 x i64> %r
}
define <2 x i64> @extract1_i32_zext_insert0_i64_undef(<4 x i32> %x) {
; CHECK-LABEL: extract1_i32_zext_insert0_i64_undef:
; CHECK: // %bb.0:
; CHECK-NEXT: zip1 v0.4s, v0.4s, v0.4s
; CHECK-NEXT: movi v1.2d, #0000000000000000
; CHECK-NEXT: ext v0.16b, v0.16b, v1.16b, #12
; CHECK-NEXT: ret
%e = extractelement <4 x i32> %x, i32 1
%z = zext i32 %e to i64
%r = insertelement <2 x i64> undef, i64 %z, i32 0
ret <2 x i64> %r
}
define <2 x i64> @extract1_i32_zext_insert0_i64_zero(<4 x i32> %x) {
; CHECK-LABEL: extract1_i32_zext_insert0_i64_zero:
; CHECK: // %bb.0:
; CHECK-NEXT: mov w8, v0.s[1]
; CHECK-NEXT: movi v0.2d, #0000000000000000
; CHECK-NEXT: mov v0.d[0], x8
; CHECK-NEXT: ret
%e = extractelement <4 x i32> %x, i32 1
%z = zext i32 %e to i64
%r = insertelement <2 x i64> zeroinitializer, i64 %z, i32 0
ret <2 x i64> %r
}
define <2 x i64> @extract2_i32_zext_insert0_i64_undef(<4 x i32> %x) {
; CHECK-LABEL: extract2_i32_zext_insert0_i64_undef:
; CHECK: // %bb.0:
; CHECK-NEXT: uzp1 v0.4s, v0.4s, v0.4s
; CHECK-NEXT: movi v1.2d, #0000000000000000
; CHECK-NEXT: ext v0.16b, v0.16b, v1.16b, #12
; CHECK-NEXT: ret
%e = extractelement <4 x i32> %x, i32 2
%z = zext i32 %e to i64
%r = insertelement <2 x i64> undef, i64 %z, i32 0
ret <2 x i64> %r
}
define <2 x i64> @extract2_i32_zext_insert0_i64_zero(<4 x i32> %x) {
; CHECK-LABEL: extract2_i32_zext_insert0_i64_zero:
; CHECK: // %bb.0:
; CHECK-NEXT: mov w8, v0.s[2]
; CHECK-NEXT: movi v0.2d, #0000000000000000
; CHECK-NEXT: mov v0.d[0], x8
; CHECK-NEXT: ret
%e = extractelement <4 x i32> %x, i32 2
%z = zext i32 %e to i64
%r = insertelement <2 x i64> zeroinitializer, i64 %z, i32 0
ret <2 x i64> %r
}
define <2 x i64> @extract3_i32_zext_insert0_i64_undef(<4 x i32> %x) {
; CHECK-LABEL: extract3_i32_zext_insert0_i64_undef:
; CHECK: // %bb.0:
; CHECK-NEXT: movi v1.2d, #0000000000000000
; CHECK-NEXT: ext v0.16b, v0.16b, v1.16b, #12
; CHECK-NEXT: ret
%e = extractelement <4 x i32> %x, i32 3
%z = zext i32 %e to i64
%r = insertelement <2 x i64> undef, i64 %z, i32 0
ret <2 x i64> %r
}
define <2 x i64> @extract3_i32_zext_insert0_i64_zero(<4 x i32> %x) {
; CHECK-LABEL: extract3_i32_zext_insert0_i64_zero:
; CHECK: // %bb.0:
; CHECK-NEXT: mov w8, v0.s[3]
; CHECK-NEXT: movi v0.2d, #0000000000000000
; CHECK-NEXT: mov v0.d[0], x8
; CHECK-NEXT: ret
%e = extractelement <4 x i32> %x, i32 3
%z = zext i32 %e to i64
%r = insertelement <2 x i64> zeroinitializer, i64 %z, i32 0
ret <2 x i64> %r
}
define <2 x i64> @extract0_i32_zext_insert1_i64_undef(<4 x i32> %x) {
; CHECK-LABEL: extract0_i32_zext_insert1_i64_undef:
; CHECK: // %bb.0:
; CHECK-NEXT: movi v1.2d, #0000000000000000
; CHECK-NEXT: zip1 v1.4s, v0.4s, v1.4s
; CHECK-NEXT: ext v0.16b, v0.16b, v1.16b, #8
; CHECK-NEXT: ret
%e = extractelement <4 x i32> %x, i32 0
%z = zext i32 %e to i64
%r = insertelement <2 x i64> undef, i64 %z, i32 1
ret <2 x i64> %r
}
define <2 x i64> @extract0_i32_zext_insert1_i64_zero(<4 x i32> %x) {
; CHECK-LABEL: extract0_i32_zext_insert1_i64_zero:
; CHECK: // %bb.0:
; CHECK-NEXT: fmov w8, s0
; CHECK-NEXT: movi v0.2d, #0000000000000000
; CHECK-NEXT: mov v0.d[1], x8
; CHECK-NEXT: ret
%e = extractelement <4 x i32> %x, i32 0
%z = zext i32 %e to i64
%r = insertelement <2 x i64> zeroinitializer, i64 %z, i32 1
ret <2 x i64> %r
}
define <2 x i64> @extract1_i32_zext_insert1_i64_undef(<4 x i32> %x) {
; CHECK-LABEL: extract1_i32_zext_insert1_i64_undef:
; CHECK: // %bb.0:
; CHECK-NEXT: ext v0.16b, v0.16b, v0.16b, #8
; CHECK-NEXT: movi v1.2d, #0000000000000000
; CHECK-NEXT: ext v0.16b, v0.16b, v1.16b, #4
; CHECK-NEXT: ret
%e = extractelement <4 x i32> %x, i32 1
%z = zext i32 %e to i64
%r = insertelement <2 x i64> undef, i64 %z, i32 1
ret <2 x i64> %r
}
define <2 x i64> @extract1_i32_zext_insert1_i64_zero(<4 x i32> %x) {
; CHECK-LABEL: extract1_i32_zext_insert1_i64_zero:
; CHECK: // %bb.0:
; CHECK-NEXT: mov w8, v0.s[1]
; CHECK-NEXT: movi v0.2d, #0000000000000000
; CHECK-NEXT: mov v0.d[1], x8
; CHECK-NEXT: ret
%e = extractelement <4 x i32> %x, i32 1
%z = zext i32 %e to i64
%r = insertelement <2 x i64> zeroinitializer, i64 %z, i32 1
ret <2 x i64> %r
}
define <2 x i64> @extract2_i32_zext_insert1_i64_undef(<4 x i32> %x) {
; CHECK-LABEL: extract2_i32_zext_insert1_i64_undef:
; CHECK: // %bb.0:
; CHECK-NEXT: mov v0.s[3], wzr
; CHECK-NEXT: ret
%e = extractelement <4 x i32> %x, i32 2
%z = zext i32 %e to i64
%r = insertelement <2 x i64> undef, i64 %z, i32 1
ret <2 x i64> %r
}
define <2 x i64> @extract2_i32_zext_insert1_i64_zero(<4 x i32> %x) {
; CHECK-LABEL: extract2_i32_zext_insert1_i64_zero:
; CHECK: // %bb.0:
; CHECK-NEXT: mov w8, v0.s[2]
; CHECK-NEXT: movi v0.2d, #0000000000000000
; CHECK-NEXT: mov v0.d[1], x8
; CHECK-NEXT: ret
%e = extractelement <4 x i32> %x, i32 2
%z = zext i32 %e to i64
%r = insertelement <2 x i64> zeroinitializer, i64 %z, i32 1
ret <2 x i64> %r
}
define <2 x i64> @extract3_i32_zext_insert1_i64_undef(<4 x i32> %x) {
; CHECK-LABEL: extract3_i32_zext_insert1_i64_undef:
; CHECK: // %bb.0:
; CHECK-NEXT: movi v1.2d, #0000000000000000
; CHECK-NEXT: ext v0.16b, v0.16b, v1.16b, #4
; CHECK-NEXT: ret
%e = extractelement <4 x i32> %x, i32 3
%z = zext i32 %e to i64
%r = insertelement <2 x i64> undef, i64 %z, i32 1
ret <2 x i64> %r
}
define <2 x i64> @extract3_i32_zext_insert1_i64_zero(<4 x i32> %x) {
; CHECK-LABEL: extract3_i32_zext_insert1_i64_zero:
; CHECK: // %bb.0:
; CHECK-NEXT: mov w8, v0.s[3]
; CHECK-NEXT: movi v0.2d, #0000000000000000
; CHECK-NEXT: mov v0.d[1], x8
; CHECK-NEXT: ret
%e = extractelement <4 x i32> %x, i32 3
%z = zext i32 %e to i64
%r = insertelement <2 x i64> zeroinitializer, i64 %z, i32 1
ret <2 x i64> %r
}
define <2 x i64> @extract0_i16_zext_insert0_i64_undef(<8 x i16> %x) {
; CHECK-LABEL: extract0_i16_zext_insert0_i64_undef:
; CHECK: // %bb.0:
; CHECK-NEXT: umov w8, v0.h[0]
; CHECK-NEXT: and x8, x8, #0xffff
; CHECK-NEXT: fmov d0, x8
; CHECK-NEXT: ret
%e = extractelement <8 x i16> %x, i32 0
%z = zext i16 %e to i64
%r = insertelement <2 x i64> undef, i64 %z, i32 0
ret <2 x i64> %r
}
define <2 x i64> @extract0_i16_zext_insert0_i64_zero(<8 x i16> %x) {
; CHECK-LABEL: extract0_i16_zext_insert0_i64_zero:
; CHECK: // %bb.0:
; CHECK-NEXT: umov w8, v0.h[0]
; CHECK-NEXT: and x8, x8, #0xffff
; CHECK-NEXT: movi v0.2d, #0000000000000000
; CHECK-NEXT: mov v0.d[0], x8
; CHECK-NEXT: ret
%e = extractelement <8 x i16> %x, i32 0
%z = zext i16 %e to i64
%r = insertelement <2 x i64> zeroinitializer, i64 %z, i32 0
ret <2 x i64> %r
}
define <2 x i64> @extract1_i16_zext_insert0_i64_undef(<8 x i16> %x) {
; CHECK-LABEL: extract1_i16_zext_insert0_i64_undef:
; CHECK: // %bb.0:
; CHECK-NEXT: umov w8, v0.h[1]
; CHECK-NEXT: and x8, x8, #0xffff
; CHECK-NEXT: fmov d0, x8
; CHECK-NEXT: ret
%e = extractelement <8 x i16> %x, i32 1
%z = zext i16 %e to i64
%r = insertelement <2 x i64> undef, i64 %z, i32 0
ret <2 x i64> %r
}
define <2 x i64> @extract1_i16_zext_insert0_i64_zero(<8 x i16> %x) {
; CHECK-LABEL: extract1_i16_zext_insert0_i64_zero:
; CHECK: // %bb.0:
; CHECK-NEXT: umov w8, v0.h[1]
; CHECK-NEXT: and x8, x8, #0xffff
; CHECK-NEXT: movi v0.2d, #0000000000000000
; CHECK-NEXT: mov v0.d[0], x8
; CHECK-NEXT: ret
%e = extractelement <8 x i16> %x, i32 1
%z = zext i16 %e to i64
%r = insertelement <2 x i64> zeroinitializer, i64 %z, i32 0
ret <2 x i64> %r
}
define <2 x i64> @extract2_i16_zext_insert0_i64_undef(<8 x i16> %x) {
; CHECK-LABEL: extract2_i16_zext_insert0_i64_undef:
; CHECK: // %bb.0:
; CHECK-NEXT: umov w8, v0.h[2]
; CHECK-NEXT: and x8, x8, #0xffff
; CHECK-NEXT: fmov d0, x8
; CHECK-NEXT: ret
%e = extractelement <8 x i16> %x, i32 2
%z = zext i16 %e to i64
%r = insertelement <2 x i64> undef, i64 %z, i32 0
ret <2 x i64> %r
}
define <2 x i64> @extract2_i16_zext_insert0_i64_zero(<8 x i16> %x) {
; CHECK-LABEL: extract2_i16_zext_insert0_i64_zero:
; CHECK: // %bb.0:
; CHECK-NEXT: umov w8, v0.h[2]
; CHECK-NEXT: and x8, x8, #0xffff
; CHECK-NEXT: movi v0.2d, #0000000000000000
; CHECK-NEXT: mov v0.d[0], x8
; CHECK-NEXT: ret
%e = extractelement <8 x i16> %x, i32 2
%z = zext i16 %e to i64
%r = insertelement <2 x i64> zeroinitializer, i64 %z, i32 0
ret <2 x i64> %r
}
define <2 x i64> @extract3_i16_zext_insert0_i64_undef(<8 x i16> %x) {
; CHECK-LABEL: extract3_i16_zext_insert0_i64_undef:
; CHECK: // %bb.0:
; CHECK-NEXT: umov w8, v0.h[3]
; CHECK-NEXT: and x8, x8, #0xffff
; CHECK-NEXT: fmov d0, x8
; CHECK-NEXT: ret
%e = extractelement <8 x i16> %x, i32 3
%z = zext i16 %e to i64
%r = insertelement <2 x i64> undef, i64 %z, i32 0
ret <2 x i64> %r
}
define <2 x i64> @extract3_i16_zext_insert0_i64_zero(<8 x i16> %x) {
; CHECK-LABEL: extract3_i16_zext_insert0_i64_zero:
; CHECK: // %bb.0:
; CHECK-NEXT: umov w8, v0.h[3]
; CHECK-NEXT: and x8, x8, #0xffff
; CHECK-NEXT: movi v0.2d, #0000000000000000
; CHECK-NEXT: mov v0.d[0], x8
; CHECK-NEXT: ret
%e = extractelement <8 x i16> %x, i32 3
%z = zext i16 %e to i64
%r = insertelement <2 x i64> zeroinitializer, i64 %z, i32 0
ret <2 x i64> %r
}
define <2 x i64> @extract0_i16_zext_insert1_i64_undef(<8 x i16> %x) {
; CHECK-LABEL: extract0_i16_zext_insert1_i64_undef:
; CHECK: // %bb.0:
; CHECK-NEXT: umov w8, v0.h[0]
; CHECK-NEXT: and x8, x8, #0xffff
; CHECK-NEXT: dup v0.2d, x8
; CHECK-NEXT: ret
%e = extractelement <8 x i16> %x, i32 0
%z = zext i16 %e to i64
%r = insertelement <2 x i64> undef, i64 %z, i32 1
ret <2 x i64> %r
}
define <2 x i64> @extract0_i16_zext_insert1_i64_zero(<8 x i16> %x) {
; CHECK-LABEL: extract0_i16_zext_insert1_i64_zero:
; CHECK: // %bb.0:
; CHECK-NEXT: umov w8, v0.h[0]
; CHECK-NEXT: and x8, x8, #0xffff
; CHECK-NEXT: movi v0.2d, #0000000000000000
; CHECK-NEXT: mov v0.d[1], x8
; CHECK-NEXT: ret
%e = extractelement <8 x i16> %x, i32 0
%z = zext i16 %e to i64
%r = insertelement <2 x i64> zeroinitializer, i64 %z, i32 1
ret <2 x i64> %r
}
define <2 x i64> @extract1_i16_zext_insert1_i64_undef(<8 x i16> %x) {
; CHECK-LABEL: extract1_i16_zext_insert1_i64_undef:
; CHECK: // %bb.0:
; CHECK-NEXT: umov w8, v0.h[1]
; CHECK-NEXT: and x8, x8, #0xffff
; CHECK-NEXT: dup v0.2d, x8
; CHECK-NEXT: ret
%e = extractelement <8 x i16> %x, i32 1
%z = zext i16 %e to i64
%r = insertelement <2 x i64> undef, i64 %z, i32 1
ret <2 x i64> %r
}
define <2 x i64> @extract1_i16_zext_insert1_i64_zero(<8 x i16> %x) {
; CHECK-LABEL: extract1_i16_zext_insert1_i64_zero:
; CHECK: // %bb.0:
; CHECK-NEXT: umov w8, v0.h[1]
; CHECK-NEXT: and x8, x8, #0xffff
; CHECK-NEXT: movi v0.2d, #0000000000000000
; CHECK-NEXT: mov v0.d[1], x8
; CHECK-NEXT: ret
%e = extractelement <8 x i16> %x, i32 1
%z = zext i16 %e to i64
%r = insertelement <2 x i64> zeroinitializer, i64 %z, i32 1
ret <2 x i64> %r
}
define <2 x i64> @extract2_i16_zext_insert1_i64_undef(<8 x i16> %x) {
; CHECK-LABEL: extract2_i16_zext_insert1_i64_undef:
; CHECK: // %bb.0:
; CHECK-NEXT: umov w8, v0.h[2]
; CHECK-NEXT: and x8, x8, #0xffff
; CHECK-NEXT: dup v0.2d, x8
; CHECK-NEXT: ret
%e = extractelement <8 x i16> %x, i32 2
%z = zext i16 %e to i64
%r = insertelement <2 x i64> undef, i64 %z, i32 1
ret <2 x i64> %r
}
define <2 x i64> @extract2_i16_zext_insert1_i64_zero(<8 x i16> %x) {
; CHECK-LABEL: extract2_i16_zext_insert1_i64_zero:
; CHECK: // %bb.0:
; CHECK-NEXT: umov w8, v0.h[2]
; CHECK-NEXT: and x8, x8, #0xffff
; CHECK-NEXT: movi v0.2d, #0000000000000000
; CHECK-NEXT: mov v0.d[1], x8
; CHECK-NEXT: ret
%e = extractelement <8 x i16> %x, i32 2
%z = zext i16 %e to i64
%r = insertelement <2 x i64> zeroinitializer, i64 %z, i32 1
ret <2 x i64> %r
}
define <2 x i64> @extract3_i16_zext_insert1_i64_undef(<8 x i16> %x) {
; CHECK-LABEL: extract3_i16_zext_insert1_i64_undef:
; CHECK: // %bb.0:
; CHECK-NEXT: umov w8, v0.h[3]
; CHECK-NEXT: and x8, x8, #0xffff
; CHECK-NEXT: dup v0.2d, x8
; CHECK-NEXT: ret
%e = extractelement <8 x i16> %x, i32 3
%z = zext i16 %e to i64
%r = insertelement <2 x i64> undef, i64 %z, i32 1
ret <2 x i64> %r
}
define <2 x i64> @extract3_i16_zext_insert1_i64_zero(<8 x i16> %x) {
; CHECK-LABEL: extract3_i16_zext_insert1_i64_zero:
; CHECK: // %bb.0:
; CHECK-NEXT: umov w8, v0.h[3]
; CHECK-NEXT: and x8, x8, #0xffff
; CHECK-NEXT: movi v0.2d, #0000000000000000
; CHECK-NEXT: mov v0.d[1], x8
; CHECK-NEXT: ret
%e = extractelement <8 x i16> %x, i32 3
%z = zext i16 %e to i64
%r = insertelement <2 x i64> zeroinitializer, i64 %z, i32 1
ret <2 x i64> %r
}
; This would crash because we did not expect to create
; a shuffle for a vector where the source operand is
; not the same size as the result.
; TODO: Should we handle this pattern? Ie, is moving to/from
; registers the optimal code?
define <4 x i32> @larger_bv_than_source(<4 x i16> %t0) {
; CHECK-LABEL: larger_bv_than_source:
; CHECK: // %bb.0:
; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0
; CHECK-NEXT: umov w8, v0.h[2]
; CHECK-NEXT: fmov s0, w8
; CHECK-NEXT: ret
%t1 = extractelement <4 x i16> %t0, i32 2
%vgetq_lane = zext i16 %t1 to i32
%t2 = insertelement <4 x i32> undef, i32 %vgetq_lane, i64 0
ret <4 x i32> %t2
}

View File

@ -0,0 +1,11 @@
; RUN: llc -mtriple arm64-windows %s -o - 2>&1 | FileCheck %s
define i8* @foo(i8* %a) {
; CHECK-LABEL: foo
; CHECK-NOT: llvm.x86.seh.recoverfp
%1 = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (i32 ()* @f to i8*), i8* %a)
ret i8* %1
}
declare i8* @llvm.x86.seh.recoverfp(i8*, i8*)
declare i32 @f()

View File

@ -11,10 +11,10 @@ entry:
; CHECK-NEXT: and x8, x8, x16
; CHECK-NEXT: and x1, x1, x16
; CHECK-NEXT: csdb
; CHECK-NEXT: mov x17, sp
; CHECK-NEXT: and x17, x17, x16
; CHECK-NEXT: mov [[TMPREG:x[0-9]+]], sp
; CHECK-NEXT: and [[TMPREG]], [[TMPREG]], x16
; CHECK-NEXT: mov x0, x8
; CHECK-NEXT: mov sp, x17
; CHECK-NEXT: mov sp, [[TMPREG]]
; CHECK-NEXT: ret
}
@ -29,9 +29,9 @@ entry:
; CHECK-NEXT: and x0, x0, x16
; CHECK-NEXT: csdb
; CHECK-NEXT: ldr d0, [x0]
; CHECK-NEXT: mov x17, sp
; CHECK-NEXT: and x17, x17, x16
; CHECK-NEXT: mov sp, x17
; CHECK-NEXT: mov [[TMPREG:x[0-9]+]], sp
; CHECK-NEXT: and [[TMPREG]], [[TMPREG]], x16
; CHECK-NEXT: mov sp, [[TMPREG]]
; CHECK-NEXT: ret
}
@ -51,12 +51,12 @@ entry:
; CHECK-NEXT: and x8, x8, x16
; csdb instruction must occur before the add instruction with w8 as operand.
; CHECK-NEXT: csdb
; CHECK-NEXT: mov x17, sp
; CHECK-NEXT: add w9, w1, w8
; CHECK-NEXT: cmp x8, #0
; CHECK-NEXT: and x17, x17, x16
; CHECK-NEXT: csel w0, w1, w9, eq
; CHECK-NEXT: mov sp, x17
; CHECK-NEXT: mov [[TMPREG:x[0-9]+]], sp
; CHECK-NEXT: and [[TMPREG]], [[TMPREG]], x16
; CHECK-NEXT: mov sp, [[TMPREG]]
; CHECK-NEXT: ret
}
@ -76,12 +76,12 @@ entry:
; CHECK-NEXT: and w8, w8, w16
; csdb instruction must occur before the add instruction with x8 as operand.
; CHECK-NEXT: csdb
; CHECK-NEXT: mov x17, sp
; CHECK-NEXT: add x9, x1, x8
; CHECK-NEXT: cmp w8, #0
; CHECK-NEXT: and x17, x17, x16
; CHECK-NEXT: csel x0, x1, x9, eq
; CHECK-NEXT: mov sp, x17
; CHECK-NEXT: mov [[TMPREG:x[0-9]+]], sp
; CHECK-NEXT: and [[TMPREG]], [[TMPREG]], x16
; CHECK-NEXT: mov sp, [[TMPREG]]
; CHECK-NEXT: ret
}
@ -112,11 +112,11 @@ entry:
; CHECK-NEXT: and x1, x1, x16
; CHECK-NEXT: csdb
; CHECK-NEXT: ldr d0, [x1]
; CHECK-NEXT: mov x17, sp
; CHECK-NEXT: and x17, x17, x16
; CHECK-NEXT: mov v0.d[1], v0.d[0]
; CHECK-NEXT: str q0, [x0]
; CHECK-NEXT: mov sp, x17
; CHECK-NEXT: mov [[TMPREG:x[0-9]+]], sp
; CHECK-NEXT: and [[TMPREG]], [[TMPREG]], x16
; CHECK-NEXT: mov sp, [[TMPREG]]
; CHECK-NEXT: ret
}
@ -129,9 +129,9 @@ entry:
; CHECK-NEXT: and x1, x1, x16
; CHECK-NEXT: csdb
; CHECK-NEXT: ld1 { v0.d }[0], [x1]
; CHECK-NEXT: mov x17, sp
; CHECK-NEXT: and x17, x17, x16
; CHECK-NEXT: mov sp, x17
; CHECK-NEXT: mov [[TMPREG:x[0-9]+]], sp
; CHECK-NEXT: and [[TMPREG]], [[TMPREG]], x16
; CHECK-NEXT: mov sp, [[TMPREG]]
; CHECK-NEXT: ret
%0 = load double, double* %b, align 16
%vld1_lane = insertelement <2 x double> <double undef, double 0.000000e+00>, double %0, i32 0
@ -147,9 +147,9 @@ entry:
; CHECK-NEXT: .cfi_def_cfa_offset 16
; CHECK-NEXT: ldr w8, [sp, #12]
; CHECK-NEXT: add sp, sp, #16
; CHECK-NEXT: mov x17, sp
; CHECK-NEXT: and x17, x17, x16
; CHECK-NEXT: mov sp, x17
; CHECK-NEXT: mov [[TMPREG:x[0-9]+]], sp
; CHECK-NEXT: and [[TMPREG]], [[TMPREG]], x16
; CHECK-NEXT: mov sp, [[TMPREG]]
; CHECK-NEXT: ret
%a = alloca i32, align 4
%val = load volatile i32, i32* %a, align 4

View File

@ -1,9 +1,9 @@
; RUN: sed -e 's/SLHATTR/speculative_load_hardening/' %s | llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu | FileCheck %s --check-prefixes=CHECK,SLH --dump-input-on-failure
; RUN: sed -e 's/SLHATTR//' %s | llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu | FileCheck %s --check-prefixes=CHECK,NOSLH --dump-input-on-failure
; RUN: sed -e 's/SLHATTR/speculative_load_hardening/' %s | llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu -global-isel | FileCheck %s --check-prefixes=CHECK,SLH --dump-input-on-failure
; RUN sed -e 's/SLHATTR//' %s | llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu -global-isel | FileCheck %s --check-prefixes=CHECK,NOSLH --dump-input-on-failure
; RUN: sed -e 's/SLHATTR/speculative_load_hardening/' %s | llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu -fast-isel | FileCheck %s --check-prefixes=CHECK,SLH --dump-input-on-failure
; RUN: sed -e 's/SLHATTR//' %s | llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu -fast-isel | FileCheck %s --check-prefixes=CHECK,NOSLH --dump-input-on-failure
; RUN: sed -e 's/SLHATTR/speculative_load_hardening/' %s | llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu | FileCheck %s --check-prefixes=CHECK,SLH,NOGISELSLH --dump-input-on-failure
; RUN: sed -e 's/SLHATTR//' %s | llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu | FileCheck %s --check-prefixes=CHECK,NOSLH,NOGISELNOSLH --dump-input-on-failure
; RUN: sed -e 's/SLHATTR/speculative_load_hardening/' %s | llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu -global-isel | FileCheck %s --check-prefixes=CHECK,SLH,GISELSLH --dump-input-on-failure
; RUN sed -e 's/SLHATTR//' %s | llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu -global-isel | FileCheck %s --check-prefixes=CHECK,NOSLH,GISELNOSLH --dump-input-on-failure
; RUN: sed -e 's/SLHATTR/speculative_load_hardening/' %s | llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu -fast-isel | FileCheck %s --check-prefixes=CHECK,SLH,NOGISELSLH --dump-input-on-failure
; RUN: sed -e 's/SLHATTR//' %s | llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu -fast-isel | FileCheck %s --check-prefixes=CHECK,NOSLH,NOGISELNOSLH --dump-input-on-failure
define i32 @f(i8* nocapture readonly %p, i32 %i, i32 %N) local_unnamed_addr SLHATTR {
; CHECK-LABEL: f
@ -13,12 +13,12 @@ entry:
; NOSLH-NOT: cmp sp, #0
; NOSLH-NOT: csetm x16, ne
; SLH: mov x17, sp
; SLH: and x17, x17, x16
; SLH: mov sp, x17
; NOSLH-NOT: mov x17, sp
; NOSLH-NOT: and x17, x17, x16
; NOSLH-NOT: mov sp, x17
; SLH: mov [[TMPREG:x[0-9]+]], sp
; SLH: and [[TMPREG]], [[TMPREG]], x16
; SLH: mov sp, [[TMPREG]]
; NOSLH-NOT: mov [[TMPREG:x[0-9]+]], sp
; NOSLH-NOT: and [[TMPREG]], [[TMPREG]], x16
; NOSLH-NOT: mov sp, [[TMPREG]]
%call = tail call i32 @tail_callee(i32 %i)
; SLH: cmp sp, #0
; SLH: csetm x16, ne
@ -43,29 +43,37 @@ if.then: ; preds = %entry
; NOSLH-NOT: csel x16, x16, xzr, [[COND]]
return: ; preds = %entry, %if.then
%retval.0 = phi i32 [ %conv, %if.then ], [ 0, %entry ]
; SLH: mov x17, sp
; SLH: and x17, x17, x16
; SLH: mov sp, x17
; NOSLH-NOT: mov x17, sp
; NOSLH-NOT: and x17, x17, x16
; NOSLH-NOT: mov sp, x17
; SLH: mov [[TMPREG:x[0-9]+]], sp
; SLH: and [[TMPREG]], [[TMPREG]], x16
; SLH: mov sp, [[TMPREG]]
; NOSLH-NOT: mov [[TMPREG:x[0-9]+]], sp
; NOSLH-NOT: and [[TMPREG]], [[TMPREG]], x16
; NOSLH-NOT: mov sp, [[TMPREG]]
ret i32 %retval.0
}
; Make sure that for a tail call, taint doesn't get put into SP twice.
define i32 @tail_caller(i32 %a) local_unnamed_addr SLHATTR {
; CHECK-LABEL: tail_caller:
; SLH: mov x17, sp
; SLH: and x17, x17, x16
; SLH: mov sp, x17
; NOSLH-NOT: mov x17, sp
; NOSLH-NOT: and x17, x17, x16
; NOSLH-NOT: mov sp, x17
; NOGISELSLH: mov [[TMPREG:x[0-9]+]], sp
; NOGISELSLH: and [[TMPREG]], [[TMPREG]], x16
; NOGISELSLH: mov sp, [[TMPREG]]
; NOGISELNOSLH-NOT: mov [[TMPREG:x[0-9]+]], sp
; NOGISELNOSLH-NOT: and [[TMPREG]], [[TMPREG]], x16
; NOGISELNOSLH-NOT: mov sp, [[TMPREG]]
; GISELSLH: mov [[TMPREG:x[0-9]+]], sp
; GISELSLH: and [[TMPREG]], [[TMPREG]], x16
; GISELSLH: mov sp, [[TMPREG]]
; GISELNOSLH-NOT: mov [[TMPREG:x[0-9]+]], sp
; GISELNOSLH-NOT: and [[TMPREG]], [[TMPREG]], x16
; GISELNOSLH-NOT: mov sp, [[TMPREG]]
; GlobalISel doesn't optimize tail calls (yet?), so only check that
; cross-call taint register setup code is missing if a tail call was
; actually produced.
; SLH: {{(bl tail_callee[[:space:]] cmp sp, #0)|(b tail_callee)}}
; SLH-NOT: cmp sp, #0
; NOGISELSLH: b tail_callee
; GISELSLH: bl tail_callee
; GISELSLH: cmp sp, #0
; SLH-NOT: cmp sp, #0
%call = tail call i32 @tail_callee(i32 %a)
ret i32 %call
}

View File

@ -25,6 +25,22 @@
define void @indirectbranch(i32 %a, i32 %b) speculative_load_hardening {
ret void
}
; Also check that a non-default temporary register gets picked correctly to
; transfer the SP to to and it with the taint register when the default
; temporary isn't available.
define void @indirect_call_x17(i32 %a, i32 %b) speculative_load_hardening {
ret void
}
@g = common dso_local local_unnamed_addr global i64 (...)* null, align 8
define void @indirect_tailcall_x17(i32 %a, i32 %b) speculative_load_hardening {
ret void
}
define void @indirect_call_lr(i32 %a, i32 %b) speculative_load_hardening {
ret void
}
define void @RS_cannot_find_available_regs() speculative_load_hardening {
ret void
}
...
---
name: nobranch_fallthrough
@ -115,3 +131,72 @@ body: |
; CHECK-NOT: csel
RET undef $lr, implicit $x0
...
---
name: indirect_call_x17
tracksRegLiveness: true
body: |
bb.0:
liveins: $x17
; CHECK-LABEL: indirect_call_x17
; CHECK: mov x0, sp
; CHECK: and x0, x0, x16
; CHECK: mov sp, x0
; CHECK: blr x17
BLR killed renamable $x17, implicit-def dead $lr, implicit $sp
RET undef $lr, implicit undef $w0
...
---
name: indirect_tailcall_x17
tracksRegLiveness: true
body: |
bb.0:
liveins: $x0
; CHECK-LABEL: indirect_tailcall_x17
; CHECK: mov x1, sp
; CHECK: and x1, x1, x16
; CHECK: mov sp, x1
; CHECK: br x17
$x8 = ADRP target-flags(aarch64-page) @g
$x17 = LDRXui killed $x8, target-flags(aarch64-pageoff, aarch64-nc) @g
TCRETURNri killed $x17, 0, implicit $sp, implicit $x0
...
---
name: indirect_call_lr
tracksRegLiveness: true
body: |
bb.0:
; CHECK-LABEL: indirect_call_lr
; CHECK: mov x1, sp
; CHECK-NEXT: and x1, x1, x16
; CHECK-NEXT: mov sp, x1
; CHECK-NEXT: blr x30
liveins: $x0, $lr
BLR killed renamable $lr, implicit-def dead $lr, implicit $sp, implicit-def $sp, implicit-def $w0
$w0 = nsw ADDWri killed $w0, 1, 0
RET undef $lr, implicit $w0
...
---
name: RS_cannot_find_available_regs
tracksRegLiveness: true
body: |
bb.0:
; In the rare case when no free temporary register is available for the
; propagate taint-to-sp operation, just put in a full speculation barrier
; (isb+dsb sy) at the start of the basic block. And don't put masks on
; instructions for the rest of the basic block, since speculation in that
; basic block was already done, so no need to do masking.
; CHECK-LABEL: RS_cannot_find_available_regs
; CHECK: dsb sy
; CHECK-NEXT: isb
; CHECK-NEXT: ldr x0, [x0]
; The following 2 instructions come from propagating the taint encoded in
; sp at function entry to x16. It turns out the taint info in x16 is not
; used in this function, so those instructions could be optimized away. An
; optimization for later if it turns out this situation occurs often enough.
; CHECK-NEXT: cmp sp, #0
; CHECK-NEXT: csetm x16, ne
; CHECK-NEXT: ret
liveins: $x0, $x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12, $x13, $x14, $x15, $x17, $x18, $x19, $x20, $x21, $x22, $x23, $x24, $x25, $x26, $x27, $x28, $fp, $lr
$x0 = LDRXui killed $x0, 0
RET undef $lr, implicit $x0
...

View File

@ -1,12 +1,12 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=mips-unknown-linux-gnu -mcpu=mips32 -disable-mips-delay-filler | FileCheck %s --check-prefixes=ALL,MIPS32,MIPS32EB
; RUN: llc < %s -mtriple=mips64-unknown-linux-gnu -relocation-model=pic -mcpu=mips64 -disable-mips-delay-filler | FileCheck %s --check-prefixes=ALL,MIPS64,MIPS64EB
; RUN: llc < %s -mtriple=mips64-unknown-linux-gnu -relocation-model=pic -mcpu=mips64 -disable-mips-delay-filler -mips-jalr-reloc=false | FileCheck %s --check-prefixes=ALL,MIPS64,MIPS64EB
; RUN: llc < %s -mtriple=mips-unknown-linux-gnu -mcpu=mips32r5 -mattr=+fp64,+msa -disable-mips-delay-filler | FileCheck %s --check-prefixes=ALL,MIPS32R5,MIPS32R5EB
; RUN: llc < %s -mtriple=mips64-unknown-linux-gnu -relocation-model=pic -mcpu=mips64r5 -mattr=+fp64,+msa -disable-mips-delay-filler | FileCheck %s --check-prefixes=ALL,MIPS64R5,MIPS64R5EB
; RUN: llc < %s -mtriple=mips64-unknown-linux-gnu -relocation-model=pic -mcpu=mips64r5 -mattr=+fp64,+msa -disable-mips-delay-filler -mips-jalr-reloc=false | FileCheck %s --check-prefixes=ALL,MIPS64R5,MIPS64R5EB
; RUN: llc < %s -mtriple=mipsel-unknown-linux-gnu -mcpu=mips32 -disable-mips-delay-filler | FileCheck %s --check-prefixes=ALL,MIPS32,MIPS32EL
; RUN: llc < %s -mtriple=mips64el-unknown-linux-gnu -relocation-model=pic -mcpu=mips64 -disable-mips-delay-filler | FileCheck %s --check-prefixes=ALL,MIPS64,MIPS64EL
; RUN: llc < %s -mtriple=mips64el-unknown-linux-gnu -relocation-model=pic -mcpu=mips64 -disable-mips-delay-filler -mips-jalr-reloc=false | FileCheck %s --check-prefixes=ALL,MIPS64,MIPS64EL
; RUN: llc < %s -mtriple=mipsel-unknown-linux-gnu -mcpu=mips32r5 -mattr=+fp64,+msa -disable-mips-delay-filler | FileCheck %s --check-prefixes=ALL,MIPS32R5,MIPS32R5EL
; RUN: llc < %s -mtriple=mips64el-unknown-linux-gnu -relocation-model=pic -mcpu=mips64r5 -mattr=+fp64,+msa -disable-mips-delay-filler | FileCheck %s --check-prefixes=ALL,MIPS64R5,MIPS64R5EL
; RUN: llc < %s -mtriple=mips64el-unknown-linux-gnu -relocation-model=pic -mcpu=mips64r5 -mattr=+fp64,+msa -disable-mips-delay-filler -mips-jalr-reloc=false | FileCheck %s --check-prefixes=ALL,MIPS64R5,MIPS64R5EL
; Test that vector types are passed through the integer register set whether or
; not MSA is enabled. This is a ABI requirement for MIPS. For GCC compatibility

View File

@ -1,10 +1,10 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=mips-mti-linux-gnu < %s -relocation-model=pic | FileCheck %s --check-prefix=O32
; RUN: llc -mtriple=mips64-mti-linux-gnu < %s -relocation-model=pic | FileCheck %s --check-prefix=N64
; RUN: llc -mtriple=mips64-mti-linux-gnu < %s -relocation-model=pic -target-abi n32 | FileCheck %s --check-prefix=N32
; RUN: llc -mtriple=mips-mti-linux-gnu < %s -relocation-model=pic -O3 | FileCheck %s --check-prefix=O3O32
; RUN: llc -mtriple=mips64-mti-linux-gnu < %s -relocation-model=pic -O3 | FileCheck %s --check-prefix=O3N64
; RUN: llc -mtriple=mips64-mti-linux-gnu < %s -relocation-model=pic -target-abi n32 -O3 | FileCheck %s --check-prefix=O3N32
; RUN: llc -mtriple=mips-mti-linux-gnu < %s -relocation-model=pic -mips-jalr-reloc=false | FileCheck %s --check-prefix=O32
; RUN: llc -mtriple=mips64-mti-linux-gnu < %s -relocation-model=pic -mips-jalr-reloc=false | FileCheck %s --check-prefix=N64
; RUN: llc -mtriple=mips64-mti-linux-gnu < %s -relocation-model=pic -target-abi n32 -mips-jalr-reloc=false | FileCheck %s --check-prefix=N32
; RUN: llc -mtriple=mips-mti-linux-gnu < %s -relocation-model=pic -O3 -mips-jalr-reloc=false | FileCheck %s --check-prefix=O3O32
; RUN: llc -mtriple=mips64-mti-linux-gnu < %s -relocation-model=pic -O3 -mips-jalr-reloc=false | FileCheck %s --check-prefix=O3N64
; RUN: llc -mtriple=mips64-mti-linux-gnu < %s -relocation-model=pic -target-abi n32 -O3 -mips-jalr-reloc=false | FileCheck %s --check-prefix=O3N32
; Test that PIC calls use the $25 register. This is an ABI requirement.

View File

@ -1,36 +1,38 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=mips -mcpu=mips2 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP32,GP32R0R2
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R0R2
; RUN: llc < %s -mtriple=mips -mcpu=mips32 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP32,GP32R0R2
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R0R2
; RUN: llc < %s -mtriple=mips -mcpu=mips32r2 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP32,GP32R2R5
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R2R5
; RUN: llc < %s -mtriple=mips -mcpu=mips32r3 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP32,GP32R2R5
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R2R5
; RUN: llc < %s -mtriple=mips -mcpu=mips32r5 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP32,GP32R2R5
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R2R5
; RUN: llc < %s -mtriple=mips -mcpu=mips32r6 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefix=GP32R6
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefix=GP32R6
; RUN: llc < %s -mtriple=mips64 -mcpu=mips3 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP64,GP64R0R1
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R0R1
; RUN: llc < %s -mtriple=mips64 -mcpu=mips4 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP64,GP64R0R1
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R0R1
; RUN: llc < %s -mtriple=mips64 -mcpu=mips64 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP64,GP64R0R1
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R0R1
; RUN: llc < %s -mtriple=mips64 -mcpu=mips64r2 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP64,GP64R2R5
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R2R5
; RUN: llc < %s -mtriple=mips64 -mcpu=mips64r3 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP64,GP64R2R5
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R2R5
; RUN: llc < %s -mtriple=mips64 -mcpu=mips64r5 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP64,GP64R2R5
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R2R5
; RUN: llc < %s -mtriple=mips64 -mcpu=mips64r6 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefix=GP64R6
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefix=GP64R6
; RUN: llc < %s -mtriple=mips -mcpu=mips32r3 -mattr=+micromips -relocation-model=pic \
; RUN: | FileCheck %s -check-prefix=MMR3
; RUN: llc < %s -mtriple=mips -mcpu=mips32r6 -mattr=+micromips -relocation-model=pic \
; RUN: | FileCheck %s -check-prefix=MMR6
; RUN: llc < %s -mtriple=mips -mcpu=mips32r3 -mattr=+micromips \
; RUN: -relocation-model=pic -mips-jalr-reloc=false | \
; RUN: FileCheck %s -check-prefix=MMR3
; RUN: llc < %s -mtriple=mips -mcpu=mips32r6 -mattr=+micromips \
; RUN: -relocation-model=pic -mips-jalr-reloc=false | \
; RUN: FileCheck %s -check-prefix=MMR6
define signext i1 @sdiv_i1(i1 signext %a, i1 signext %b) {
; GP32-LABEL: sdiv_i1:

View File

@ -1,36 +1,38 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=mips -mcpu=mips2 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP32,GP32R0R2
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R0R2
; RUN: llc < %s -mtriple=mips -mcpu=mips32 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP32,GP32R0R2
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R0R2
; RUN: llc < %s -mtriple=mips -mcpu=mips32r2 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP32,GP32R2R5
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R2R5
; RUN: llc < %s -mtriple=mips -mcpu=mips32r3 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP32,GP32R2R5
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R2R5
; RUN: llc < %s -mtriple=mips -mcpu=mips32r5 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP32,GP32R2R5
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R2R5
; RUN: llc < %s -mtriple=mips -mcpu=mips32r6 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefix=GP32R6
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefix=GP32R6
; RUN: llc < %s -mtriple=mips64 -mcpu=mips3 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP64,GP64R0R1
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R0R1
; RUN: llc < %s -mtriple=mips64 -mcpu=mips4 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP64,GP64R0R1
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R0R1
; RUN: llc < %s -mtriple=mips64 -mcpu=mips64 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP64,GP64R0R1
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R0R1
; RUN: llc < %s -mtriple=mips64 -mcpu=mips64r2 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP64,GP64R2R5
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R2R5
; RUN: llc < %s -mtriple=mips64 -mcpu=mips64r3 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP64,GP64R2R5
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R2R5
; RUN: llc < %s -mtriple=mips64 -mcpu=mips64r5 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP64,GP64R2R5
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R2R5
; RUN: llc < %s -mtriple=mips64 -mcpu=mips64r6 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefix=GP64R6
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefix=GP64R6
; RUN: llc < %s -mtriple=mips -mcpu=mips32r3 -mattr=+micromips -relocation-model=pic \
; RUN: | FileCheck %s -check-prefix=MMR3
; RUN: llc < %s -mtriple=mips -mcpu=mips32r6 -mattr=+micromips -relocation-model=pic \
; RUN: | FileCheck %s -check-prefix=MMR6
; RUN: llc < %s -mtriple=mips -mcpu=mips32r3 -mattr=+micromips \
; RUN: -relocation-model=pic -mips-jalr-reloc=false | \
; RUN: FileCheck %s -check-prefix=MMR3
; RUN: llc < %s -mtriple=mips -mcpu=mips32r6 -mattr=+micromips \
; RUN: -relocation-model=pic -mips-jalr-reloc=false | \
; RUN: FileCheck %s -check-prefix=MMR6
define signext i1 @srem_i1(i1 signext %a, i1 signext %b) {
; GP32-LABEL: srem_i1:

View File

@ -1,36 +1,38 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=mips -mcpu=mips2 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP32,GP32R0R1
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R0R1
; RUN: llc < %s -mtriple=mips -mcpu=mips32 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP32,GP32R0R1
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R0R1
; RUN: llc < %s -mtriple=mips -mcpu=mips32r2 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP32,GP32R2R5
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R2R5
; RUN: llc < %s -mtriple=mips -mcpu=mips32r3 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP32,GP32R2R5
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R2R5
; RUN: llc < %s -mtriple=mips -mcpu=mips32r5 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP32,GP32R2R5
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R2R5
; RUN: llc < %s -mtriple=mips -mcpu=mips32r6 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefix=GP32R6
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefix=GP32R6
; RUN: llc < %s -mtriple=mips64 -mcpu=mips3 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP64,GP64R0R1
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R0R1
; RUN: llc < %s -mtriple=mips64 -mcpu=mips4 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP64,GP64R0R1
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R0R1
; RUN: llc < %s -mtriple=mips64 -mcpu=mips64 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP64,GP64R0R2
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R0R2
; RUN: llc < %s -mtriple=mips64 -mcpu=mips64r2 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP64,GP64R2R5
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R2R5
; RUN: llc < %s -mtriple=mips64 -mcpu=mips64r3 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP64,GP64R2R5
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R2R5
; RUN: llc < %s -mtriple=mips64 -mcpu=mips64r5 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP64,GP64R2R5
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R2R5
; RUN: llc < %s -mtriple=mips64 -mcpu=mips64r6 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefix=GP64R6
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefix=GP64R6
; RUN: llc < %s -mtriple=mips -mcpu=mips32r3 -mattr=+micromips -relocation-model=pic \
; RUN: | FileCheck %s -check-prefix=MMR3
; RUN: llc < %s -mtriple=mips -mcpu=mips32r6 -mattr=+micromips -relocation-model=pic \
; RUN: | FileCheck %s -check-prefix=MMR6
; RUN: llc < %s -mtriple=mips -mcpu=mips32r3 -mattr=+micromips \
; RUN: -relocation-model=pic -mips-jalr-reloc=false | \
; RUN: FileCheck %s -check-prefix=MMR3
; RUN: llc < %s -mtriple=mips -mcpu=mips32r6 -mattr=+micromips \
; RUN: -relocation-model=pic -mips-jalr-reloc=false | \
; RUN: FileCheck %s -check-prefix=MMR6
define zeroext i1 @udiv_i1(i1 zeroext %a, i1 zeroext %b) {
; GP32-LABEL: udiv_i1:

View File

@ -1,36 +1,38 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=mips -mcpu=mips2 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP32,GP32R0R2
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R0R2
; RUN: llc < %s -mtriple=mips -mcpu=mips32 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP32,GP32R0R2
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R0R2
; RUN: llc < %s -mtriple=mips -mcpu=mips32r2 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP32,GP32R2R5
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R2R5
; RUN: llc < %s -mtriple=mips -mcpu=mips32r3 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP32,GP32R2R5
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R2R5
; RUN: llc < %s -mtriple=mips -mcpu=mips32r5 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP32,GP32R2R5
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R2R5
; RUN: llc < %s -mtriple=mips -mcpu=mips32r6 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefix=GP32R6
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefix=GP32R6
; RUN: llc < %s -mtriple=mips64 -mcpu=mips3 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP64,GP64R0R1
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R0R1
; RUN: llc < %s -mtriple=mips64 -mcpu=mips4 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP64,GP64R0R1
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R0R1
; RUN: llc < %s -mtriple=mips64 -mcpu=mips64 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP64,GP64R0R1
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R0R1
; RUN: llc < %s -mtriple=mips64 -mcpu=mips64r2 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP64,GP64R2R5
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R2R5
; RUN: llc < %s -mtriple=mips64 -mcpu=mips64r3 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP64,GP64R2R5
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R2R5
; RUN: llc < %s -mtriple=mips64 -mcpu=mips64r5 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefixes=GP64,GP64R2R5
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R2R5
; RUN: llc < %s -mtriple=mips64 -mcpu=mips64r6 -relocation-model=pic \
; RUN: | FileCheck %s -check-prefix=GP64R6
; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefix=GP64R6
; RUN: llc < %s -mtriple=mips -mcpu=mips32r3 -mattr=+micromips -relocation-model=pic \
; RUN: | FileCheck %s -check-prefix=MMR3
; RUN: llc < %s -mtriple=mips -mcpu=mips32r6 -mattr=+micromips -relocation-model=pic \
; RUN: | FileCheck %s -check-prefix=MMR6
; RUN: llc < %s -mtriple=mips -mcpu=mips32r3 -mattr=+micromips \
; RUN: -relocation-model=pic -mips-jalr-reloc=false | \
; RUN: FileCheck %s -check-prefix=MMR3
; RUN: llc < %s -mtriple=mips -mcpu=mips32r6 -mattr=+micromips \
; RUN: -relocation-model=pic -mips-jalr-reloc=false | \
; RUN: FileCheck %s -check-prefix=MMR6
define signext i1 @urem_i1(i1 signext %a, i1 signext %b) {
; GP32-LABEL: urem_i1:

View File

@ -1,11 +1,11 @@
; RUN: llc -march=mips -target-abi o32 --mattr=+long-calls,+noabicalls < %s \
; RUN: | FileCheck -check-prefix=O32 %s
; RUN: -mips-jalr-reloc=false | FileCheck -check-prefix=O32 %s
; RUN: llc -march=mips -target-abi o32 --mattr=-long-calls,+noabicalls < %s \
; RUN: | FileCheck -check-prefix=O32 %s
; RUN: -mips-jalr-reloc=false | FileCheck -check-prefix=O32 %s
; RUN: llc -march=mips64 -target-abi n64 --mattr=+long-calls,+noabicalls < %s \
; RUN: | FileCheck -check-prefix=N64 %s
; RUN: -mips-jalr-reloc=false | FileCheck -check-prefix=N64 %s
; RUN: llc -march=mips64 -target-abi n64 --mattr=-long-calls,+noabicalls < %s \
; RUN: | FileCheck -check-prefix=N64 %s
; RUN: -mips-jalr-reloc=false | FileCheck -check-prefix=N64 %s
declare void @far() #0

View File

@ -1,8 +1,8 @@
; Check call to mcount in case of long/short call options.
; RUN: llc -march=mips -target-abi o32 --mattr=+long-calls,+noabicalls < %s \
; RUN: | FileCheck -check-prefixes=CHECK,LONG %s
; RUN: -mips-jalr-reloc=false | FileCheck -check-prefixes=CHECK,LONG %s
; RUN: llc -march=mips -target-abi o32 --mattr=-long-calls,+noabicalls < %s \
; RUN: | FileCheck -check-prefixes=CHECK,SHORT %s
; RUN: -mips-jalr-reloc=false | FileCheck -check-prefixes=CHECK,SHORT %s
; Function Attrs: noinline nounwind optnone
define void @foo() #0 {

View File

@ -1,22 +1,22 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -relocation-model=pic -mtriple=mipsel-- -mcpu=mips32r5 \
; RUN: -mattr=+fp64,+msa -verify-machineinstrs < %s | FileCheck %s \
; RUN: -mattr=+fp64,+msa -verify-machineinstrs -mips-jalr-reloc=false < %s | FileCheck %s \
; RUN: --check-prefixes=ALL,MIPS32,MIPSR5,MIPS32-O32,MIPS32R5-O32
; RUN: llc -relocation-model=pic -mtriple=mips64el-- -mcpu=mips64r5 \
; RUN: -mattr=+fp64,+msa -verify-machineinstrs -target-abi n32 < %s | FileCheck %s \
; RUN: -mattr=+fp64,+msa -verify-machineinstrs -target-abi n32 -mips-jalr-reloc=false < %s | FileCheck %s \
; RUN: --check-prefixes=ALL,MIPS64,MIPSR5,MIPS64-N32,MIPS64R5-N32
; RUN: llc -relocation-model=pic -mtriple=mips64el-- -mcpu=mips64r5 \
; RUN: -mattr=+fp64,+msa -verify-machineinstrs -target-abi n64 < %s | FileCheck %s \
; RUN: -mattr=+fp64,+msa -verify-machineinstrs -target-abi n64 -mips-jalr-reloc=false < %s | FileCheck %s \
; RUN: --check-prefixes=ALL,MIPS64,MIPSR5,MIPS64-N64,MIPS64R5-N64
; RUN: llc -relocation-model=pic -mtriple=mipsel-- -mcpu=mips32r6 \
; RUN: -mattr=+fp64,+msa -verify-machineinstrs < %s | FileCheck %s \
; RUN: -mattr=+fp64,+msa -verify-machineinstrs -mips-jalr-reloc=false < %s | FileCheck %s \
; RUN: --check-prefixes=ALL,MIPS32,MIPSR6,MIPSR6-O32
; RUN: llc -relocation-model=pic -mtriple=mips64el-- -mcpu=mips64r6 \
; RUN: -mattr=+fp64,+msa -verify-machineinstrs -target-abi n32 < %s | FileCheck %s \
; RUN: -mattr=+fp64,+msa -verify-machineinstrs -target-abi n32 -mips-jalr-reloc=false < %s | FileCheck %s \
; RUN: --check-prefixes=ALL,MIPS64,MIPSR6,MIPS64-N32,MIPSR6-N32
; RUN: llc -relocation-model=pic -mtriple=mips64el-- -mcpu=mips64r6 \
; RUN: -mattr=+fp64,+msa -verify-machineinstrs -target-abi n64 < %s | FileCheck %s \
; RUN: -mattr=+fp64,+msa -verify-machineinstrs -target-abi n64 -mips-jalr-reloc=false < %s | FileCheck %s \
; RUN: --check-prefixes=ALL,MIPS64,MIPSR6,MIPS64-N64,MIPSR6-N64

View File

@ -1,5 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=mipsel-unknown-linux-gnu -relocation-model=pic < %s | FileCheck %s
; RUN: llc -mtriple=mipsel-unknown-linux-gnu -relocation-model=pic \
; RUN: -mips-jalr-reloc=false < %s | FileCheck %s
%0 = type { i8, i16, i32, i64, double, i32, [4 x i8] }
%struct.S1 = type { i8, i16, i32, i64, double, i32 }

View File

@ -0,0 +1,154 @@
; RUN: llc -mtriple=mips-linux-gnu -relocation-model=pic -mips-tail-calls=1 \
; RUN: -O2 < %s | \
; RUN: FileCheck %s -check-prefixes=ALL,JALR-32R2,TAILCALL-32R2
; RUN: llc -mtriple=mips64-linux-gnu -relocation-model=pic -mips-tail-calls=1 \
; RUN: -O2 < %s | \
; RUN: FileCheck %s -check-prefixes=ALL,JALR-64R2,TAILCALL-64R2
; RUN: llc -mtriple=mips-linux-gnu -relocation-model=pic -mips-tail-calls=1 \
; RUN: -O2 -mcpu=mips32r6 -mips-compact-branches=always < %s | \
; RUN: FileCheck %s -check-prefixes=ALL,JALR-32R6,TAILCALL-32R6
; RUN: llc -mtriple=mips64-linux-gnu -relocation-model=pic -mips-tail-calls=1 \
; RUN: -O2 -mcpu=mips64r6 -mips-compact-branches=always < %s | \
; RUN: FileCheck %s -check-prefixes=ALL,JALR-64R6,TAILCALL-64R6
; RUN: llc -mtriple=mips-linux-gnu -relocation-model=pic -mips-tail-calls=1 \
; RUN: -O2 -mcpu=mips32r6 -mips-compact-branches=never < %s | \
; RUN: FileCheck %s -check-prefixes=ALL,JALR-32R2,TAILCALL-32R2
; RUN: llc -mtriple=mips64-linux-gnu -relocation-model=pic -mips-tail-calls=1 \
; RUN: -O2 -mcpu=mips64r6 -mips-compact-branches=never < %s | \
; RUN: FileCheck %s -check-prefixes=ALL,JALR-64R2,TAILCALL-64R2
; RUN: llc -mtriple=mips-linux-gnu -relocation-model=pic -mips-tail-calls=1 \
; RUN: -O2 -mattr=+micromips -mcpu=mips32r2 < %s | \
; RUN: FileCheck %s -check-prefixes=ALL,JALR-MM,TAILCALL-MM
; RUN: llc -mtriple=mips-linux-gnu -relocation-model=pic -mips-tail-calls=1 \
; RUN: -O2 -mattr=+micromips -mcpu=mips32r6 < %s | \
; RUN: FileCheck %s -check-prefixes=ALL,JALR-MM
; RUN: llc -mtriple=mips-linux-gnu -relocation-model=pic \
; RUN: -O0 < %s | FileCheck %s -check-prefixes=ALL,JALR-32R2
; RUN: llc -mtriple=mips64-linux-gnu -relocation-model=pic \
; RUN: -O0 < %s | FileCheck %s -check-prefixes=ALL,JALR-64R2
; RUN: llc -mtriple=mips-linux-gnu -relocation-model=pic \
; RUN: -O0 -mcpu=mips32r6 -mips-compact-branches=always < %s | \
; RUN: FileCheck %s -check-prefixes=ALL,JALR-32R6
; RUN: llc -mtriple=mips64-linux-gnu -relocation-model=pic \
; RUN: -O0 -mcpu=mips64r6 -mips-compact-branches=always < %s | \
; RUN: FileCheck %s -check-prefixes=ALL,JALR-64R6
; RUN: llc -mtriple=mips-linux-gnu -relocation-model=pic \
; RUN: -O0 -mcpu=mips32r6 -mips-compact-branches=never < %s | \
; RUN: FileCheck %s -check-prefixes=ALL,JALR-32R2
; RUN: llc -mtriple=mips64-linux-gnu -relocation-model=pic \
; RUN: -O0 -mcpu=mips64r6 -mips-compact-branches=never < %s | \
; RUN: FileCheck %s -check-prefixes=ALL,JALR-64R2
; RUN: llc -mtriple=mips-linux-gnu -relocation-model=pic \
; RUN: -O0 -mattr=+micromips -mcpu=mips32r2 < %s | \
; RUN: FileCheck %s -check-prefixes=ALL,JALR-MM
; RUN: llc -mtriple=mips-linux-gnu -relocation-model=pic \
; RUN: -O0 -mattr=+micromips -mcpu=mips32r6 < %s | \
; RUN: FileCheck %s -check-prefixes=ALL,JALR-MM
; RUN: llc -mtriple=mips-linux-gnu -relocation-model=pic -mips-tail-calls=1 \
; RUN: -O2 -mips-jalr-reloc=false < %s | \
; RUN: FileCheck %s -check-prefixes=ALL,NORELOC
; RUN: llc -mtriple=mips-linux-gnu -relocation-model=static -mips-tail-calls=1 \
; RUN: -O2 < %s | \
; RUN: FileCheck %s -check-prefixes=ALL,NORELOC
; RUN: llc -mtriple=mips-linux-gnu -relocation-model=pic -mips-tail-calls=1 \
; RUN: -O0 -mips-jalr-reloc=false < %s | \
; RUN: FileCheck %s -check-prefixes=ALL,NORELOC
; RUN: llc -mtriple=mips-linux-gnu -relocation-model=static -mips-tail-calls=1 \
; RUN: -O0 < %s | \
; RUN: FileCheck %s -check-prefixes=ALL,NORELOC
; RUN: llc -mtriple=mips64-linux-gnu -relocation-model=pic -mips-tail-calls=1 \
; RUN: -O2 -mips-jalr-reloc=false < %s | \
; RUN: FileCheck %s -check-prefixes=ALL,NORELOC
; RUN: llc -mtriple=mips64-linux-gnu -mips-tail-calls=1 \
; RUN: -O2 -relocation-model=static < %s | \
; RUN: FileCheck %s -check-prefixes=ALL,NORELOC
; RUN: llc -mtriple=mips64-linux-gnu -relocation-model=pic \
; RUN: -O0 -mips-jalr-reloc=false < %s | \
; RUN: FileCheck %s -check-prefixes=ALL,NORELOC
; RUN: llc -mtriple=mips64-linux-gnu -relocation-model=static \
; RUN: -O0 < %s | \
; RUN: FileCheck %s -check-prefixes=ALL,NORELOC
define internal void @foo() noinline {
entry:
ret void
}
define void @checkCall() {
entry:
; ALL-LABEL: checkCall:
call void @foo()
; JALR-32R2: .reloc ([[TMPLABEL:.*]]), R_MIPS_JALR, foo
; JALR-32R2-NEXT: [[TMPLABEL]]:
; JALR-32R2-NEXT: jalr $25
; JALR-64R2: .reloc [[TMPLABEL:.*]], R_MIPS_JALR, foo
; JALR-64R2-NEXT: [[TMPLABEL]]:
; JALR-64R2-NEXT: jalr $25
; JALR-MM: .reloc ([[TMPLABEL:.*]]), R_MICROMIPS_JALR, foo
; JALR-MM-NEXT: [[TMPLABEL]]:
; JALR-MM-NEXT: jalr $25
; JALR-32R6: .reloc ([[TMPLABEL:.*]]), R_MIPS_JALR, foo
; JALR-32R6-NEXT: [[TMPLABEL]]:
; JALR-32R6-NEXT: jalrc $25
; JALR-64R6: .reloc [[TMPLABEL:.*]], R_MIPS_JALR, foo
; JALR-64R6-NEXT: [[TMPLABEL]]:
; JALR-64R6-NEXT: jalrc $25
; NORELOC-NOT: R_MIPS_JALR
ret void
}
define void @checkTailCall() {
entry:
; ALL-LABEL: checkTailCall:
tail call void @foo()
; TAILCALL-32R2: .reloc ([[TMPLABEL:.*]]), R_MIPS_JALR, foo
; TAILCALL-32R2-NEXT: [[TMPLABEL]]:
; TAILCALL-32R2-NEXT: jr $25
; TAILCALL-64R2: .reloc [[TMPLABEL:.*]], R_MIPS_JALR, foo
; TAILCALL-64R2-NEXT: [[TMPLABEL]]:
; TAILCALL-64R2-NEXT: jr $25
; TAILCALL-MM: .reloc ([[TMPLABEL:.*]]), R_MICROMIPS_JALR, foo
; TAILCALL-MM-NEXT: [[TMPLABEL]]:
; TAILCALL-MM-NEXT: jrc $25
; TAILCALL-32R6: .reloc ([[TMPLABEL:.*]]), R_MIPS_JALR, foo
; TAILCALL-32R6-NEXT: [[TMPLABEL]]:
; TAILCALL-32R6-NEXT: jrc $25
; TAILCALL-64R6: .reloc [[TMPLABEL:.*]], R_MIPS_JALR, foo
; TAILCALL-64R6-NEXT: [[TMPLABEL]]:
; TAILCALL-64R6-NEXT: jrc $25
; NORELOC-NOT: R_MIPS_JALR
ret void
}

View File

@ -9,11 +9,11 @@
; RUN: FileCheck %s -check-prefix=NO-SHRINK-WRAP-STATIC
; RUN: llc -mtriple=mips-unknown-linux-gnu -enable-shrink-wrap=true \
; RUN: -relocation-model=pic < %s | \
; RUN: -relocation-model=pic -mips-jalr-reloc=false < %s | \
; RUN: FileCheck %s -check-prefix=SHRINK-WRAP-PIC
; RUN: llc -mtriple=mips-unknown-linux-gnu -enable-shrink-wrap=false \
; RUN: -relocation-model=pic < %s | \
; RUN: -relocation-model=pic -mips-jalr-reloc=false < %s | \
; RUN: FileCheck %s -check-prefix=NO-SHRINK-WRAP-PIC
; RUN: llc -mtriple=mips64-unknown-linux-gnu -enable-shrink-wrap=true \
@ -25,11 +25,11 @@
; RUN: FileCheck %s -check-prefix=NO-SHRINK-WRAP-64-STATIC
; RUN: llc -mtriple=mips64-unknown-linux-gnu -enable-shrink-wrap=true \
; RUN: -relocation-model=pic < %s | \
; RUN: -relocation-model=pic -mips-jalr-reloc=false < %s | \
; RUN: FileCheck %s -check-prefix=SHRINK-WRAP-64-PIC
; RUN: llc -mtriple=mips64-unknown-linux-gnu -enable-shrink-wrap=false \
; RUN: -relocation-model=pic < %s | \
; RUN: -relocation-model=pic -mips-jalr-reloc=false < %s | \
; RUN: FileCheck %s -check-prefix=NO-SHRINK-WRAP-64-PIC
declare void @f(i32 signext)

View File

@ -11,7 +11,7 @@
; CHECK-NEXT: DW_AT_type [DW_FORM_ref4] (cu + 0x0040 => {0x00000040} "A")
; CHECK: .debug_loclists contents:
; CHECK-NEXT: 0x00000000: locations list header: length = 0x00000017, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
; CHECK-NEXT: 0x00000000: locations list header: length = 0x00000015, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
; CHECK-NEXT: 0x00000000:
; CHECK-NEXT: [0x0000000000000000, 0x0000000000000004): DW_OP_breg5 RDI+0
; CHECK-NEXT: [0x0000000000000004, 0x0000000000000012): DW_OP_breg3 RBX+0
@ -32,13 +32,13 @@
; ASM-NEXT: .byte 4 # DW_LLE_offset_pair
; ASM-NEXT: .uleb128 .Lfunc_begin0-.Lfunc_begin0 # starting offset
; ASM-NEXT: .uleb128 .Ltmp0-.Lfunc_begin0 # ending offset
; ASM-NEXT: .short 2 # Loc expr size
; ASM-NEXT: .byte 2 # Loc expr size
; ASM-NEXT: .byte 117 # DW_OP_breg5
; ASM-NEXT: .byte 0 # 0
; ASM-NEXT: .byte 4 # DW_LLE_offset_pair
; ASM-NEXT: .uleb128 .Ltmp0-.Lfunc_begin0 # starting offset
; ASM-NEXT: .uleb128 .Ltmp1-.Lfunc_begin0 # ending offset
; ASM-NEXT: .short 2 # Loc expr size
; ASM-NEXT: .byte 2 # Loc expr size
; ASM-NEXT: .byte 115 # DW_OP_breg3
; ASM-NEXT: .byte 0 # 0
; ASM-NEXT: .byte 0 # DW_LLE_end_of_list

View File

@ -1,4 +1,4 @@
; RUN: llc < %s | FileCheck %s
; RUN: llc -x86-discriminate-memops < %s | FileCheck %s
;
; original source, compiled with -O3 -gmlt -fdebug-info-for-profiling:
; int sum(int* arr, int pos1, int pos2) {

View File

@ -1,4 +1,4 @@
; RUN: llc < %s -prefetch-hints-file=%S/insert-prefetch-inline.afdo | FileCheck %s
; RUN: llc < %s -x86-discriminate-memops -prefetch-hints-file=%S/insert-prefetch-inline.afdo | FileCheck %s
;
; Verify we can insert prefetch instructions in code belonging to inlined
; functions.

View File

@ -1,4 +1,4 @@
; RUN: llc < %s -prefetch-hints-file=%S/insert-prefetch-invalid-instr.afdo | FileCheck %s
; RUN: llc < %s -x86-discriminate-memops -prefetch-hints-file=%S/insert-prefetch-invalid-instr.afdo | FileCheck %s
; ModuleID = 'prefetch.cc'
source_filename = "prefetch.cc"
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"

View File

@ -1,5 +1,5 @@
; RUN: llc < %s -prefetch-hints-file=%S/insert-prefetch.afdo | FileCheck %s
; RUN: llc < %s -prefetch-hints-file=%S/insert-prefetch-other.afdo | FileCheck %s -check-prefix=OTHERS
; RUN: llc < %s -x86-discriminate-memops -prefetch-hints-file=%S/insert-prefetch.afdo | FileCheck %s
; RUN: llc < %s -x86-discriminate-memops -prefetch-hints-file=%S/insert-prefetch-other.afdo | FileCheck %s -check-prefix=OTHERS
;
; original source, compiled with -O3 -gmlt -fdebug-info-for-profiling:
; int sum(int* arr, int pos1, int pos2) {

View File

@ -0,0 +1,72 @@
; RUN: llc < %s -filetype=obj | llvm-readobj - -codeview | FileCheck %s
; ModuleID = 'foo.3a1fbbbh-cgu.0'
source_filename = "foo.3a1fbbbh-cgu.0"
target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-windows-msvc"
; Rust source to regenerate:
; $ cat foo.rs
; pub struct Foo;
; impl Foo {
; pub fn foo() {}
; }
; $ rustc foo.rs --crate-type lib -Cdebuginfo=1 --emit=llvm-ir
; CHECK: CodeViewTypes [
; CHECK: MemberFunction (0x1006) {
; CHECK-NEXT: TypeLeafKind: LF_MFUNCTION (0x1009)
; CHECK-NEXT: ReturnType: void (0x3)
; CHECK-NEXT: ClassType: foo::Foo (0x1000)
; CHECK-NEXT: ThisType: 0x0
; CHECK-NEXT: CallingConvention: NearC (0x0)
; CHECK-NEXT: FunctionOptions [ (0x0)
; CHECK-NEXT: ]
; CHECK-NEXT: NumParameters: 0
; CHECK-NEXT: ArgListType: () (0x1005)
; CHECK-NEXT: ThisAdjustment: 0
; CHECK-NEXT: }
; CHECK-NEXT: MemberFuncId (0x1007) {
; CHECK-NEXT: TypeLeafKind: LF_MFUNC_ID (0x1602)
; CHECK-NEXT: ClassType: foo::Foo (0x1000)
; CHECK-NEXT: FunctionType: void foo::Foo::() (0x1006)
; CHECK-NEXT: Name: foo
; CHECK-NEXT: }
; CHECK: CodeViewDebugInfo [
; CHECK: FunctionLineTable [
; CHECK-NEXT: LinkageName: _ZN3foo3Foo3foo17hc557c2121772885bE
; CHECK-NEXT: Flags: 0x0
; CHECK-NEXT: CodeSize: 0x1
; CHECK-NEXT: FilenameSegment [
; CHECK-NEXT: Filename: D:\rust\foo.rs (0x0)
; CHECK-NEXT: +0x0 [
; CHECK-NEXT: LineNumberStart: 3
; CHECK-NEXT: LineNumberEndDelta: 0
; CHECK-NEXT: IsStatement: No
; CHECK-NEXT: ]
; CHECK-NEXT: ]
; CHECK-NEXT: ]
; foo::Foo::foo
; Function Attrs: uwtable
define void @_ZN3foo3Foo3foo17hc557c2121772885bE() unnamed_addr #0 !dbg !5 {
start:
ret void, !dbg !10
}
attributes #0 = { uwtable "target-cpu"="x86-64" }
!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!3, !4}
!0 = distinct !DICompileUnit(language: DW_LANG_Rust, file: !1, producer: "clang LLVM (rustc version 1.33.0-nightly (8b0f0156e 2019-01-22))", isOptimized: false, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: !2)
!1 = !DIFile(filename: "foo.rs", directory: "D:\5Crust")
!2 = !{}
!3 = !{i32 2, !"CodeView", i32 1}
!4 = !{i32 2, !"Debug Info Version", i32 3}
!5 = distinct !DISubprogram(name: "foo", linkageName: "_ZN3foo3Foo3foo17hc557c2121772885bE", scope: !6, file: !1, line: 3, type: !9, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, templateParams: !2, retainedNodes: !2)
!6 = !DICompositeType(tag: DW_TAG_structure_type, name: "Foo", scope: !8, file: !7, align: 8, elements: !2, templateParams: !2, identifier: "5105d9fe1a2a3c68518268151b672274")
!7 = !DIFile(filename: "<unknown>", directory: "")
!8 = !DINamespace(name: "foo", scope: null)
!9 = !DISubroutineType(types: !2)
!10 = !DILocation(line: 3, scope: !5)

View File

@ -1,12 +1,34 @@
; RUN: llc -O0 -march=mips -mcpu=mips32r2 -filetype=obj -o=%t-32.o < %s
; RUN: llc -O0 -march=mips -mcpu=mips32r2 -filetype=obj \
; RUN: -split-dwarf-file=foo.dwo -o=%t-32.o < %s
; RUN: llvm-dwarfdump %t-32.o 2>&1 | FileCheck %s
; RUN: llc -O0 -march=mips64 -mcpu=mips64r2 -filetype=obj -o=%t-64.o < %s
; RUN: llc -O0 -march=mips64 -mcpu=mips64r2 -filetype=obj \
; RUN: -split-dwarf-file=foo.dwo -o=%t-64.o < %s
; RUN: llvm-dwarfdump %t-64.o 2>&1 | FileCheck %s
; RUN: llc -O0 -march=mips -mcpu=mips32r2 -filetype=asm \
; RUN: -split-dwarf-file=foo.dwo < %s | FileCheck -check-prefix=ASM32 %s
; RUN: llc -O0 -march=mips64 -mcpu=mips64r2 -filetype=asm \
; RUN: -split-dwarf-file=foo.dwo < %s | FileCheck -check-prefix=ASM64 %s
@x = thread_local global i32 5, align 4, !dbg !0
; CHECK-NOT: error: failed to compute relocation: R_MIPS_TLS_DTPREL
; CHECK: DW_AT_name ("x")
; CHECK-NEXT: DW_AT_type (0x00000025 "int")
; CHECK-NEXT: DW_AT_external (true)
; CHECK-NEXT: DW_AT_decl_file (0x01)
; CHECK-NEXT: DW_AT_decl_line (1)
; CHECK-NEXT: DW_AT_location (DW_OP_GNU_const_index 0x0, {{DW_OP_GNU_push_tls_address|DW_OP_form_tls_address}})
; ASM32: .section .debug_addr
; ASM32-NEXT: $addr_table_base0:
; ASM32-NEXT: .4byte x+32768
; ASM64: .section .debug_addr
; ASM64-NEXT: .Laddr_table_base0:
; ASM64-NEXT: .8byte x+32768
!llvm.dbg.cu = !{!2}
!llvm.module.flags = !{!7, !8}

View File

@ -9,7 +9,7 @@
# CHECK-NEXT: [0x0000000000000700, 0x0000000000000710): DW_OP_breg5 RDI+0
# CHECK: .debug_loclists contents:
# CHECK-NEXT: 0x00000000: locations list header: length = 0x0000002f, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
# CHECK-NEXT: 0x00000000: locations list header: length = 0x0000002c, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
# CHECK-NEXT: 0x00000000:
# CHECK-NEXT: [0x0000000000000000, 0x0000000000000010): DW_OP_breg5 RDI+0
# CHECK-NEXT: [0x0000000000000530, 0x0000000000000540): DW_OP_breg6 RBP-8, DW_OP_deref
@ -37,7 +37,7 @@
.byte 4 # DW_LLE_offset_pair
.uleb128 0x0 # starting offset
.uleb128 0x10 # ending offset
.short 2 # Loc expr size
.byte 2 # Loc expr size
.byte 117 # DW_OP_breg5
.byte 0 # 0
@ -47,7 +47,7 @@
.byte 4 # DW_LLE_offset_pair
.uleb128 0x30 # starting offset
.uleb128 0x40 # ending offset
.short 3 # Loc expr size
.byte 3 # Loc expr size
.byte 118 # DW_OP_breg6
.byte 120 # -8
.byte 6 # DW_OP_deref
@ -55,7 +55,7 @@
.byte 8 # DW_LLE_start_length
.quad 0x700 # Some address
.uleb128 0x10 # length
.short 2 # Loc expr size
.byte 2 # Loc expr size
.byte 117 # DW_OP_breg5
.byte 0 # 0

View File

@ -0,0 +1,10 @@
target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-windows-msvc19.0.24215"
define void @main() {
entry:
call i8* @lwt_fun()
ret void
}
declare i8* @lwt_fun()

View File

@ -0,0 +1,32 @@
; Test to ensure that comdat is renamed consistently when comdat leader is
; promoted and renamed due to an import. Required by COFF.
; REQUIRES: x86-registered-target
; RUN: opt -thinlto-bc -o %t1.bc %s
; RUN: opt -thinlto-bc -o %t2.bc %S/Inputs/comdat.ll
; RUN: llvm-lto2 run -save-temps -o %t3 %t1.bc %t2.bc \
; RUN: -r %t1.bc,lwt_fun,plx \
; RUN: -r %t2.bc,main,plx \
; RUN: -r %t2.bc,lwt_fun,
; RUN: llvm-dis -o - %t3.1.3.import.bc | FileCheck %s
target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-windows-msvc19.0.24215"
; CHECK: $lwt.llvm.[[HASH:[0-9]+]] = comdat any
$lwt = comdat any
; CHECK: @lwt_aliasee = private unnamed_addr global {{.*}}, comdat($lwt.llvm.[[HASH]])
@lwt_aliasee = private unnamed_addr global [1 x i8*] [i8* null], comdat($lwt)
; CHECK: @lwt.llvm.[[HASH]] = hidden unnamed_addr alias
@lwt = internal unnamed_addr alias [1 x i8*], [1 x i8*]* @lwt_aliasee
; Below function should get imported into other module, resulting in @lwt being
; promoted and renamed.
define i8* @lwt_fun() {
%1 = getelementptr inbounds [1 x i8*], [1 x i8*]* @lwt, i32 0, i32 0
%2 = load i8*, i8** %1
ret i8* %2
}

View File

@ -0,0 +1,33 @@
; RUN: opt -transform-warning -disable-output < %s 2>&1 | FileCheck -allow-empty %s
;
; llvm.org/PR40546
; Do not warn about about leftover llvm.loop.vectorize.enable for already
; vectorized loops.
target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
define void @test(i32 %n) {
entry:
%cmp = icmp eq i32 %n, 0
br i1 %cmp, label %simd.if.end, label %omp.inner.for.body.preheader
omp.inner.for.body.preheader:
%wide.trip.count = zext i32 %n to i64
br label %omp.inner.for.body
omp.inner.for.body:
%indvars.iv = phi i64 [ 0, %omp.inner.for.body.preheader ], [ %indvars.iv.next, %omp.inner.for.body ]
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
%exitcond = icmp eq i64 %indvars.iv.next, %wide.trip.count
br i1 %exitcond, label %simd.if.end, label %omp.inner.for.body, !llvm.loop !0
simd.if.end:
ret void
}
!0 = distinct !{!0, !1, !2}
!1 = !{!"llvm.loop.vectorize.enable", i1 true}
!2 = !{!"llvm.loop.isvectorized"}
; CHECK-NOT: loop not vectorized

View File

@ -0,0 +1,95 @@
; RUN: opt < %s -loop-vectorize -force-vector-width=4 -transform-warning -S 2>&1 | FileCheck %s
; RUN: opt < %s -loop-vectorize -force-vector-width=1 -transform-warning -S 2>&1 | FileCheck %s -check-prefix=NOANALYSIS
; RUN: opt < %s -loop-vectorize -force-vector-width=4 -transform-warning -pass-remarks-missed='loop-vectorize' -S 2>&1 | FileCheck %s -check-prefix=MOREINFO
; This test is a copy of no_switch.ll, with the "llvm.loop.vectorize.enable" metadata set to false.
; It tests that vectorization is explicitly disabled and no warnings are emitted.
; CHECK-NOT: remark: source.cpp:4:5: loop not vectorized: loop contains a switch statement
; CHECK-NOT: warning: source.cpp:4:5: loop not vectorized: the optimizer was unable to perform the requested transformation; the transformation might be disabled or specified as part of an unsupported transformation ordering
; NOANALYSIS-NOT: remark: {{.*}}
; NOANALYSIS-NOT: warning: source.cpp:4:5: loop not vectorized: the optimizer was unable to perform the requested transformation; the transformation might be disabled or specified as part of an unsupported transformation ordering
; MOREINFO: remark: source.cpp:4:5: loop not vectorized: vectorization is explicitly disabled
; MOREINFO-NOT: warning: source.cpp:4:5: loop not vectorized: the optimizer was unable to perform the requested transformation; the transformation might be disabled or specified as part of an unsupported transformation ordering
; CHECK: _Z11test_switchPii
; CHECK-NOT: x i32>
; CHECK: ret
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
; Function Attrs: nounwind optsize ssp uwtable
define void @_Z11test_switchPii(i32* nocapture %A, i32 %Length) #0 !dbg !4 {
entry:
%cmp18 = icmp sgt i32 %Length, 0, !dbg !10
br i1 %cmp18, label %for.body.preheader, label %for.end, !dbg !10, !llvm.loop !12
for.body.preheader: ; preds = %entry
br label %for.body, !dbg !14
for.body: ; preds = %for.body.preheader, %for.inc
%indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %for.body.preheader ]
%arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv, !dbg !14
%0 = load i32, i32* %arrayidx, align 4, !dbg !14, !tbaa !16
switch i32 %0, label %for.inc [
i32 0, label %sw.bb
i32 1, label %sw.bb3
], !dbg !14
sw.bb: ; preds = %for.body
%1 = trunc i64 %indvars.iv to i32, !dbg !20
%mul = shl nsw i32 %1, 1, !dbg !20
br label %for.inc, !dbg !22
sw.bb3: ; preds = %for.body
%2 = trunc i64 %indvars.iv to i32, !dbg !23
store i32 %2, i32* %arrayidx, align 4, !dbg !23, !tbaa !16
br label %for.inc, !dbg !23
for.inc: ; preds = %sw.bb3, %for.body, %sw.bb
%storemerge = phi i32 [ %mul, %sw.bb ], [ 0, %for.body ], [ 0, %sw.bb3 ]
store i32 %storemerge, i32* %arrayidx, align 4, !dbg !20, !tbaa !16
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1, !dbg !10
%lftr.wideiv = trunc i64 %indvars.iv.next to i32, !dbg !10
%exitcond = icmp eq i32 %lftr.wideiv, %Length, !dbg !10
br i1 %exitcond, label %for.end.loopexit, label %for.body, !dbg !10, !llvm.loop !12
for.end.loopexit: ; preds = %for.inc
br label %for.end
for.end: ; preds = %for.end.loopexit, %entry
ret void, !dbg !24
}
attributes #0 = { nounwind }
!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!7, !8}
!llvm.ident = !{!9}
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.5.0", isOptimized: true, runtimeVersion: 6, emissionKind: LineTablesOnly, file: !1, enums: !2, retainedTypes: !2, globals: !2, imports: !2)
!1 = !DIFile(filename: "source.cpp", directory: ".")
!2 = !{}
!4 = distinct !DISubprogram(name: "test_switch", line: 1, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: true, unit: !0, scopeLine: 1, file: !1, scope: !5, type: !6, retainedNodes: !2)
!5 = !DIFile(filename: "source.cpp", directory: ".")
!6 = !DISubroutineType(types: !2)
!7 = !{i32 2, !"Dwarf Version", i32 2}
!8 = !{i32 2, !"Debug Info Version", i32 3}
!9 = !{!"clang version 3.5.0"}
!10 = !DILocation(line: 3, column: 8, scope: !11)
!11 = distinct !DILexicalBlock(line: 3, column: 3, file: !1, scope: !4)
!12 = !{!12, !13, !13}
!13 = !{!"llvm.loop.vectorize.enable", i1 false}
!14 = !DILocation(line: 4, column: 5, scope: !15)
!15 = distinct !DILexicalBlock(line: 3, column: 36, file: !1, scope: !11)
!16 = !{!17, !17, i64 0}
!17 = !{!"int", !18, i64 0}
!18 = !{!"omnipotent char", !19, i64 0}
!19 = !{!"Simple C/C++ TBAA"}
!20 = !DILocation(line: 6, column: 7, scope: !21)
!21 = distinct !DILexicalBlock(line: 4, column: 18, file: !1, scope: !15)
!22 = !DILocation(line: 7, column: 5, scope: !21)
!23 = !DILocation(line: 9, column: 7, scope: !21)
!24 = !DILocation(line: 14, column: 1, scope: !4)

View File

@ -6,7 +6,7 @@
# the final version which uses ULEB128 and not the U32.
# CHECK: .debug_loclists contents:
# CHECK-NEXT: 0x00000000: locations list header: length = 0x0000000f, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
# CHECK-NEXT: 0x00000000: locations list header: length = 0x0000000e, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
# CHECK-NEXT: 0x00000000:
# CHECK-NEXT: Addr idx 1 (w/ length 16): DW_OP_reg5 RDI
@ -21,7 +21,7 @@
.byte 3 # DW_LLE_startx_length
.byte 0x01 # Index
.uleb128 0x10 # Length
.short 1 # Loc expr size
.byte 1 # Loc expr size
.byte 85 # DW_OP_reg5
.byte 0 # DW_LLE_end_of_list
.Ldebug_loclist_table_end0: