mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 11:42:57 +01:00
[X86][GlobalISel] Initial implementation , select G_ADD gpr, gpr
Summary: Initial implementation for X86InstructionSelector. Handle selection COPY and G_ADD/G_SUB gpr, gpr . Reviewers: qcolombet, rovka, zvi, ab Reviewed By: rovka Subscribers: mgorny, dberris, kristof.beyls, llvm-commits Differential Revision: https://reviews.llvm.org/D29816 llvm-svn: 295824
This commit is contained in:
parent
70004e62ed
commit
1280381d89
@ -55,6 +55,13 @@ bool InstructionSelector::constrainSelectedInstRegOperands(
|
||||
// constrainOperandRegClass does that for us.
|
||||
MO.setReg(constrainOperandRegClass(MF, TRI, MRI, TII, RBI, I, I.getDesc(),
|
||||
Reg, OpI));
|
||||
|
||||
// Tie uses to defs as indicated in MCInstrDesc.
|
||||
if (MO.isUse()) {
|
||||
int DefIdx = I.getDesc().getOperandConstraint(OpI, MCOI::TIED_TO);
|
||||
if (DefIdx != -1)
|
||||
I.tieOperands(DefIdx, OpI);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ tablegen(LLVM X86GenCallingConv.inc -gen-callingconv)
|
||||
tablegen(LLVM X86GenSubtargetInfo.inc -gen-subtarget)
|
||||
if(LLVM_BUILD_GLOBAL_ISEL)
|
||||
tablegen(LLVM X86GenRegisterBank.inc -gen-register-bank)
|
||||
tablegen(LLVM X86GenGlobalISel.inc -gen-global-isel)
|
||||
endif()
|
||||
|
||||
add_public_tablegen_target(X86CommonTableGen)
|
||||
@ -21,6 +22,7 @@ set(GLOBAL_ISEL_FILES
|
||||
X86CallLowering.cpp
|
||||
X86LegalizerInfo.cpp
|
||||
X86RegisterBankInfo.cpp
|
||||
X86InstructionSelector.cpp
|
||||
)
|
||||
|
||||
if(LLVM_BUILD_GLOBAL_ISEL)
|
||||
|
133
lib/Target/X86/X86InstructionSelector.cpp
Normal file
133
lib/Target/X86/X86InstructionSelector.cpp
Normal file
@ -0,0 +1,133 @@
|
||||
//===- X86InstructionSelector.cpp ----------------------------*- C++ -*-==//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// \file
|
||||
/// This file implements the targeting of the InstructionSelector class for
|
||||
/// X86.
|
||||
/// \todo This should be generated by TableGen.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "X86InstructionSelector.h"
|
||||
#include "X86InstrInfo.h"
|
||||
#include "X86RegisterBankInfo.h"
|
||||
#include "X86RegisterInfo.h"
|
||||
#include "X86Subtarget.h"
|
||||
#include "X86TargetMachine.h"
|
||||
#include "llvm/CodeGen/MachineBasicBlock.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
#include "llvm/CodeGen/MachineInstr.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/IR/Type.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
#define DEBUG_TYPE "X86-isel"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
#ifndef LLVM_BUILD_GLOBAL_ISEL
|
||||
#error "You shouldn't build this"
|
||||
#endif
|
||||
|
||||
#include "X86GenGlobalISel.inc"
|
||||
|
||||
X86InstructionSelector::X86InstructionSelector(const X86TargetMachine &TM,
|
||||
const X86Subtarget &STI,
|
||||
const X86RegisterBankInfo &RBI)
|
||||
: InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()),
|
||||
TRI(*STI.getRegisterInfo()), RBI(RBI) {}
|
||||
|
||||
// FIXME: This should be target-independent, inferred from the types declared
|
||||
// for each class in the bank.
|
||||
static const TargetRegisterClass *
|
||||
getRegClassForTypeOnBank(LLT Ty, const RegisterBank &RB) {
|
||||
if (RB.getID() == X86::GPRRegBankID) {
|
||||
if (Ty.getSizeInBits() <= 32)
|
||||
return &X86::GR32RegClass;
|
||||
if (Ty.getSizeInBits() == 64)
|
||||
return &X86::GR64RegClass;
|
||||
}
|
||||
|
||||
llvm_unreachable("Unknown RegBank!");
|
||||
}
|
||||
|
||||
// Set X86 Opcode and constrain DestReg.
|
||||
static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
|
||||
MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
|
||||
const RegisterBankInfo &RBI) {
|
||||
|
||||
unsigned DstReg = I.getOperand(0).getReg();
|
||||
if (TargetRegisterInfo::isPhysicalRegister(DstReg)) {
|
||||
assert(I.isCopy() && "Generic operators do not allow physical registers");
|
||||
return true;
|
||||
}
|
||||
|
||||
const RegisterBank &RegBank = *RBI.getRegBank(DstReg, MRI, TRI);
|
||||
const unsigned DstSize = MRI.getType(DstReg).getSizeInBits();
|
||||
unsigned SrcReg = I.getOperand(1).getReg();
|
||||
const unsigned SrcSize = RBI.getSizeInBits(SrcReg, MRI, TRI);
|
||||
(void)SrcSize;
|
||||
assert((!TargetRegisterInfo::isPhysicalRegister(SrcReg) || I.isCopy()) &&
|
||||
"No phys reg on generic operators");
|
||||
assert((DstSize == SrcSize ||
|
||||
// Copies are a mean to setup initial types, the number of
|
||||
// bits may not exactly match.
|
||||
(TargetRegisterInfo::isPhysicalRegister(SrcReg) &&
|
||||
DstSize <= RBI.getSizeInBits(SrcReg, MRI, TRI))) &&
|
||||
"Copy with different width?!");
|
||||
|
||||
const TargetRegisterClass *RC = nullptr;
|
||||
|
||||
switch (RegBank.getID()) {
|
||||
case X86::GPRRegBankID:
|
||||
assert((DstSize <= 64) && "GPRs cannot get more than 64-bit width values.");
|
||||
RC = getRegClassForTypeOnBank(MRI.getType(DstReg), RegBank);
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("Unknown RegBank!");
|
||||
}
|
||||
|
||||
// No need to constrain SrcReg. It will get constrained when
|
||||
// we hit another of its use or its defs.
|
||||
// Copies do not have constraints.
|
||||
if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
|
||||
DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
|
||||
<< " operand\n");
|
||||
return false;
|
||||
}
|
||||
I.setDesc(TII.get(X86::COPY));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool X86InstructionSelector::select(MachineInstr &I) const {
|
||||
assert(I.getParent() && "Instruction should be in a basic block!");
|
||||
assert(I.getParent()->getParent() && "Instruction should be in a function!");
|
||||
|
||||
MachineBasicBlock &MBB = *I.getParent();
|
||||
MachineFunction &MF = *MBB.getParent();
|
||||
MachineRegisterInfo &MRI = MF.getRegInfo();
|
||||
|
||||
unsigned Opcode = I.getOpcode();
|
||||
if (!isPreISelGenericOpcode(Opcode)) {
|
||||
// Certain non-generic instructions also need some special handling.
|
||||
|
||||
if (I.isCopy())
|
||||
return selectCopy(I, TII, MRI, TRI, RBI);
|
||||
|
||||
// TODO: handle more cases - LOAD_STACK_GUARD, PHI
|
||||
return true;
|
||||
}
|
||||
|
||||
if (I.getNumOperands() != I.getNumExplicitOperands()) {
|
||||
assert("Generic instruction has unexpected implicit operands\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return selectImpl(I);
|
||||
}
|
47
lib/Target/X86/X86InstructionSelector.h
Normal file
47
lib/Target/X86/X86InstructionSelector.h
Normal file
@ -0,0 +1,47 @@
|
||||
//===- X86InstructionSelector --------------------------------*- C++ -*-==//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// \file
|
||||
/// This file declares the targeting of the InstructionSelector class for X86.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_X86_X86INSTRUCTIONSELECTOR_H
|
||||
#define LLVM_LIB_TARGET_X86_X86INSTRUCTIONSELECTOR_H
|
||||
|
||||
#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class X86InstrInfo;
|
||||
class X86RegisterBankInfo;
|
||||
class X86RegisterInfo;
|
||||
class X86Subtarget;
|
||||
class X86TargetMachine;
|
||||
|
||||
class X86InstructionSelector : public InstructionSelector {
|
||||
public:
|
||||
X86InstructionSelector(const X86TargetMachine &TM, const X86Subtarget &STI,
|
||||
const X86RegisterBankInfo &RBI);
|
||||
|
||||
bool select(MachineInstr &I) const override;
|
||||
|
||||
private:
|
||||
/// tblgen-erated 'select' implementation, used as the initial selector for
|
||||
/// the patterns that don't require complex C++.
|
||||
bool selectImpl(MachineInstr &I) const;
|
||||
|
||||
const X86TargetMachine &TM;
|
||||
const X86Subtarget &STI;
|
||||
const X86InstrInfo &TII;
|
||||
const X86RegisterInfo &TRI;
|
||||
const X86RegisterBankInfo &RBI;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_LIB_TARGET_X86_X86INSTRUCTIONSELECTOR_H
|
@ -38,12 +38,13 @@ void X86LegalizerInfo::setLegalizerInfo32bit() {
|
||||
const LLT s16 = LLT::scalar(16);
|
||||
const LLT s32 = LLT::scalar(32);
|
||||
|
||||
for (auto Ty : {s8, s16, s32})
|
||||
for (auto Ty : {s8, s16, s32}) {
|
||||
setAction({TargetOpcode::G_ADD, Ty}, Legal);
|
||||
setAction({TargetOpcode::G_SUB, Ty}, Legal);
|
||||
}
|
||||
}
|
||||
void
|
||||
|
||||
X86LegalizerInfo::setLegalizerInfo64bit() {
|
||||
void X86LegalizerInfo::setLegalizerInfo64bit() {
|
||||
|
||||
if (!Subtarget.is64Bit())
|
||||
return;
|
||||
@ -51,4 +52,5 @@ X86LegalizerInfo::setLegalizerInfo64bit() {
|
||||
const LLT s64 = LLT::scalar(64);
|
||||
|
||||
setAction({TargetOpcode::G_ADD, s64}, Legal);
|
||||
setAction({TargetOpcode::G_SUB, s64}, Legal);
|
||||
}
|
||||
|
@ -111,6 +111,7 @@ X86RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
|
||||
|
||||
switch (Opc) {
|
||||
case TargetOpcode::G_ADD:
|
||||
case TargetOpcode::G_SUB:
|
||||
return getOperandsMapping(MI, false);
|
||||
break;
|
||||
default:
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "X86.h"
|
||||
#include "X86CallLowering.h"
|
||||
#include "X86LegalizerInfo.h"
|
||||
#include "X86InstructionSelector.h"
|
||||
#ifdef LLVM_BUILD_GLOBAL_ISEL
|
||||
#include "X86RegisterBankInfo.h"
|
||||
#endif
|
||||
@ -34,6 +35,7 @@
|
||||
#include "llvm/CodeGen/GlobalISel/IRTranslator.h"
|
||||
#include "llvm/CodeGen/GlobalISel/Legalizer.h"
|
||||
#include "llvm/CodeGen/GlobalISel/RegBankSelect.h"
|
||||
#include "llvm/CodeGen/GlobalISel/InstructionSelect.h"
|
||||
#include "llvm/CodeGen/MachineScheduler.h"
|
||||
#include "llvm/CodeGen/Passes.h"
|
||||
#include "llvm/CodeGen/TargetPassConfig.h"
|
||||
@ -211,14 +213,14 @@ struct X86GISelActualAccessor : public GISelAccessor {
|
||||
std::unique_ptr<CallLowering> CallLoweringInfo;
|
||||
std::unique_ptr<LegalizerInfo> Legalizer;
|
||||
std::unique_ptr<RegisterBankInfo> RegBankInfo;
|
||||
std::unique_ptr<InstructionSelector> InstSelector;
|
||||
|
||||
const CallLowering *getCallLowering() const override {
|
||||
return CallLoweringInfo.get();
|
||||
}
|
||||
|
||||
const InstructionSelector *getInstructionSelector() const override {
|
||||
//TODO: Implement
|
||||
return nullptr;
|
||||
return InstSelector.get();
|
||||
}
|
||||
|
||||
const LegalizerInfo *getLegalizerInfo() const override {
|
||||
@ -282,6 +284,7 @@ X86TargetMachine::getSubtargetImpl(const Function &F) const {
|
||||
|
||||
auto *RBI = new X86RegisterBankInfo(*I->getRegisterInfo());
|
||||
GISel->RegBankInfo.reset(RBI);
|
||||
GISel->InstSelector.reset(new X86InstructionSelector(*this, *I, *RBI));
|
||||
|
||||
#endif
|
||||
I->setGISelAccessor(*GISel);
|
||||
@ -391,7 +394,7 @@ bool X86PassConfig::addRegBankSelect() {
|
||||
}
|
||||
|
||||
bool X86PassConfig::addGlobalInstructionSelect() {
|
||||
//TODO: Implement
|
||||
addPass(new InstructionSelect());
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
42
test/CodeGen/X86/GlobalISel/binop-isel.ll
Executable file
42
test/CodeGen/X86/GlobalISel/binop-isel.ll
Executable file
@ -0,0 +1,42 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
||||
; RUN: llc -mtriple=x86_64-linux-gnu -global-isel < %s -o - | FileCheck %s
|
||||
|
||||
define i64 @test_add_i64(i64 %arg1, i64 %arg2) {
|
||||
; CHECK-LABEL: test_add_i64:
|
||||
; CHECK: # BB#0:
|
||||
; CHECK-NEXT: leaq (%rsi,%rdi), %rax
|
||||
; CHECK-NEXT: retq
|
||||
%ret = add i64 %arg1, %arg2
|
||||
ret i64 %ret
|
||||
}
|
||||
|
||||
define i32 @test_add_i32(i32 %arg1, i32 %arg2) {
|
||||
; CHECK-LABEL: test_add_i32:
|
||||
; CHECK: # BB#0:
|
||||
; CHECK-NEXT: # kill: %EDI<def> %EDI<kill> %RDI<def>
|
||||
; CHECK-NEXT: # kill: %ESI<def> %ESI<kill> %RSI<def>
|
||||
; CHECK-NEXT: leal (%rsi,%rdi), %eax
|
||||
; CHECK-NEXT: retq
|
||||
%ret = add i32 %arg1, %arg2
|
||||
ret i32 %ret
|
||||
}
|
||||
|
||||
define i64 @test_sub_i64(i64 %arg1, i64 %arg2) {
|
||||
; CHECK-LABEL: test_sub_i64:
|
||||
; CHECK: # BB#0:
|
||||
; CHECK-NEXT: subq %rsi, %rdi
|
||||
; CHECK-NEXT: movq %rdi, %rax
|
||||
; CHECK-NEXT: retq
|
||||
%ret = sub i64 %arg1, %arg2
|
||||
ret i64 %ret
|
||||
}
|
||||
|
||||
define i32 @test_sub_i32(i32 %arg1, i32 %arg2) {
|
||||
; CHECK-LABEL: test_sub_i32:
|
||||
; CHECK: # BB#0:
|
||||
; CHECK-NEXT: subl %esi, %edi
|
||||
; CHECK-NEXT: movl %edi, %eax
|
||||
; CHECK-NEXT: retq
|
||||
%ret = sub i32 %arg1, %arg2
|
||||
ret i32 %ret
|
||||
}
|
40
test/CodeGen/X86/GlobalISel/legalize-sub.mir
Normal file
40
test/CodeGen/X86/GlobalISel/legalize-sub.mir
Normal file
@ -0,0 +1,40 @@
|
||||
# RUN: llc -mtriple=x86_64-linux-gnu -global-isel -run-pass=legalizer %s -o - | FileCheck %s
|
||||
|
||||
--- |
|
||||
; ModuleID = '<stdin>'
|
||||
source_filename = "<stdin>"
|
||||
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64--linux-gnu"
|
||||
|
||||
define i32 @test_sub_i32(i32 %arg1, i32 %arg2) {
|
||||
%ret = sub i32 %arg1, %arg2
|
||||
ret i32 %ret
|
||||
}
|
||||
|
||||
...
|
||||
---
|
||||
name: test_sub_i32
|
||||
alignment: 4
|
||||
legalized: false
|
||||
regBankSelected: false
|
||||
selected: false
|
||||
tracksRegLiveness: true
|
||||
registers:
|
||||
- { id: 0, class: _ }
|
||||
- { id: 1, class: _ }
|
||||
- { id: 2, class: _ }
|
||||
body: |
|
||||
bb.1 (%ir-block.0):
|
||||
liveins: %edi, %esi
|
||||
; CHECK-LABEL: name: test_sub_i32
|
||||
; CHECK: [[VAL1:%.*]](s32) = COPY %edi
|
||||
; CHECK: [[VAL2:%.*]](s32) = COPY %esi
|
||||
; CHECK: [[RES:%.*]](s32) = G_SUB [[VAL1:%.*]], [[VAL2:%.*]]
|
||||
|
||||
%0(s32) = COPY %edi
|
||||
%1(s32) = COPY %esi
|
||||
%2(s32) = G_SUB %0, %1
|
||||
%eax = COPY %2(s32)
|
||||
RET 0, implicit %eax
|
||||
|
||||
...
|
124
test/CodeGen/X86/GlobalISel/x86_64-instructionselect.mir
Normal file
124
test/CodeGen/X86/GlobalISel/x86_64-instructionselect.mir
Normal file
@ -0,0 +1,124 @@
|
||||
# RUN: llc -mtriple=x86_64-linux-gnu -global-isel -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s
|
||||
|
||||
--- |
|
||||
define i64 @test_add_i64(i64 %arg1, i64 %arg2) {
|
||||
%ret = add i64 %arg1, %arg2
|
||||
ret i64 %ret
|
||||
}
|
||||
|
||||
define i32 @test_add_i32(i32 %arg1, i32 %arg2) {
|
||||
%ret = add i32 %arg1, %arg2
|
||||
ret i32 %ret
|
||||
}
|
||||
|
||||
define i64 @test_sub_i64(i64 %arg1, i64 %arg2) {
|
||||
%ret = sub i64 %arg1, %arg2
|
||||
ret i64 %ret
|
||||
}
|
||||
|
||||
define i32 @test_sub_i32(i32 %arg1, i32 %arg2) {
|
||||
%ret = sub i32 %arg1, %arg2
|
||||
ret i32 %ret
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
---
|
||||
name: test_add_i64
|
||||
legalized: true
|
||||
regBankSelected: true
|
||||
# CHECK: registers:
|
||||
# CHECK-NEXT: - { id: 0, class: gr64 }
|
||||
# CHECK-NEXT: - { id: 1, class: gr64 }
|
||||
# CHECK-NEXT: - { id: 2, class: gr64 }
|
||||
registers:
|
||||
- { id: 0, class: gpr }
|
||||
- { id: 1, class: gpr }
|
||||
- { id: 2, class: gpr }
|
||||
# CHECK: %0 = COPY %rdi
|
||||
# CHECK-NEXT: %1 = COPY %rsi
|
||||
# CHECK-NEXT: %2 = ADD64rr %0, %1
|
||||
body: |
|
||||
bb.1 (%ir-block.0):
|
||||
liveins: %edi, %esi
|
||||
|
||||
%0(s64) = COPY %rdi
|
||||
%1(s64) = COPY %rsi
|
||||
%2(s64) = G_ADD %0, %1
|
||||
|
||||
...
|
||||
|
||||
---
|
||||
name: test_add_i32
|
||||
legalized: true
|
||||
regBankSelected: true
|
||||
# CHECK: registers:
|
||||
# CHECK-NEXT: - { id: 0, class: gr32 }
|
||||
# CHECK-NEXT: - { id: 1, class: gr32 }
|
||||
# CHECK-NEXT: - { id: 2, class: gr32 }
|
||||
registers:
|
||||
- { id: 0, class: gpr }
|
||||
- { id: 1, class: gpr }
|
||||
- { id: 2, class: gpr }
|
||||
# CHECK: %0 = COPY %edi
|
||||
# CHECK-NEXT: %1 = COPY %esi
|
||||
# CHECK-NEXT: %2 = ADD32rr %0, %1
|
||||
body: |
|
||||
bb.1 (%ir-block.0):
|
||||
liveins: %edi, %esi
|
||||
|
||||
%0(s32) = COPY %edi
|
||||
%1(s32) = COPY %esi
|
||||
%2(s32) = G_ADD %0, %1
|
||||
|
||||
...
|
||||
|
||||
---
|
||||
name: test_sub_i64
|
||||
legalized: true
|
||||
regBankSelected: true
|
||||
# CHECK: registers:
|
||||
# CHECK-NEXT: - { id: 0, class: gr64 }
|
||||
# CHECK-NEXT: - { id: 1, class: gr64 }
|
||||
# CHECK-NEXT: - { id: 2, class: gr64 }
|
||||
registers:
|
||||
- { id: 0, class: gpr }
|
||||
- { id: 1, class: gpr }
|
||||
- { id: 2, class: gpr }
|
||||
# CHECK: %0 = COPY %rdi
|
||||
# CHECK-NEXT: %1 = COPY %rsi
|
||||
# CHECK-NEXT: %2 = SUB64rr %0, %1
|
||||
body: |
|
||||
bb.1 (%ir-block.0):
|
||||
liveins: %edi, %esi
|
||||
|
||||
%0(s64) = COPY %rdi
|
||||
%1(s64) = COPY %rsi
|
||||
%2(s64) = G_SUB %0, %1
|
||||
|
||||
...
|
||||
|
||||
---
|
||||
name: test_sub_i32
|
||||
legalized: true
|
||||
regBankSelected: true
|
||||
# CHECK: registers:
|
||||
# CHECK-NEXT: - { id: 0, class: gr32 }
|
||||
# CHECK-NEXT: - { id: 1, class: gr32 }
|
||||
# CHECK-NEXT: - { id: 2, class: gr32 }
|
||||
registers:
|
||||
- { id: 0, class: gpr }
|
||||
- { id: 1, class: gpr }
|
||||
- { id: 2, class: gpr }
|
||||
# CHECK: %0 = COPY %edi
|
||||
# CHECK-NEXT: %1 = COPY %esi
|
||||
# CHECK-NEXT: %2 = SUB32rr %0, %1
|
||||
body: |
|
||||
bb.1 (%ir-block.0):
|
||||
liveins: %edi, %esi
|
||||
|
||||
%0(s32) = COPY %edi
|
||||
%1(s32) = COPY %esi
|
||||
%2(s32) = G_SUB %0, %1
|
||||
|
||||
...
|
Loading…
Reference in New Issue
Block a user