mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-25 20:59:51 +00:00
Thumb2 pre/post indexed loads.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@74696 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
d0265aa00e
commit
e88d5cee9d
@ -102,6 +102,8 @@ public:
|
||||
SDValue &OffImm);
|
||||
bool SelectT2AddrModeImm8(SDValue Op, SDValue N, SDValue &Base,
|
||||
SDValue &OffImm);
|
||||
bool SelectT2AddrModeImm8Offset(SDValue Op, SDValue N,
|
||||
SDValue &OffImm);
|
||||
bool SelectT2AddrModeImm8s4(SDValue Op, SDValue N, SDValue &Base,
|
||||
SDValue &OffImm);
|
||||
bool SelectT2AddrModeSoReg(SDValue Op, SDValue N, SDValue &Base,
|
||||
@ -111,7 +113,11 @@ public:
|
||||
#include "ARMGenDAGISel.inc"
|
||||
|
||||
private:
|
||||
/// SelectARMIndexedLoad - Indexed (pre/post inc/dec) load matching code for
|
||||
/// ARM.
|
||||
SDNode *SelectARMIndexedLoad(SDValue Op);
|
||||
SDNode *SelectT2IndexedLoad(SDValue Op);
|
||||
|
||||
|
||||
/// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
|
||||
/// inline asm expressions.
|
||||
@ -628,6 +634,25 @@ bool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDValue Op, SDValue N,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ARMDAGToDAGISel::SelectT2AddrModeImm8Offset(SDValue Op, SDValue N,
|
||||
SDValue &OffImm){
|
||||
unsigned Opcode = Op.getOpcode();
|
||||
ISD::MemIndexedMode AM = (Opcode == ISD::LOAD)
|
||||
? cast<LoadSDNode>(Op)->getAddressingMode()
|
||||
: cast<StoreSDNode>(Op)->getAddressingMode();
|
||||
if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N)) {
|
||||
int RHSC = (int)RHS->getZExtValue();
|
||||
if (RHSC >= 0 && RHSC < 0x100) { // 8 bits.
|
||||
OffImm = (AM == ISD::PRE_INC)
|
||||
? CurDAG->getTargetConstant(RHSC, MVT::i32)
|
||||
: CurDAG->getTargetConstant(-RHSC, MVT::i32);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ARMDAGToDAGISel::SelectT2AddrModeImm8s4(SDValue Op, SDValue N,
|
||||
SDValue &Base, SDValue &OffImm) {
|
||||
if (N.getOpcode() == ISD::ADD) {
|
||||
@ -762,6 +787,46 @@ SDNode *ARMDAGToDAGISel::SelectARMIndexedLoad(SDValue Op) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SDNode *ARMDAGToDAGISel::SelectT2IndexedLoad(SDValue Op) {
|
||||
LoadSDNode *LD = cast<LoadSDNode>(Op);
|
||||
ISD::MemIndexedMode AM = LD->getAddressingMode();
|
||||
if (AM == ISD::UNINDEXED)
|
||||
return NULL;
|
||||
|
||||
MVT LoadedVT = LD->getMemoryVT();
|
||||
SDValue Offset;
|
||||
bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC);
|
||||
unsigned Opcode = 0;
|
||||
bool Match = false;
|
||||
if (SelectT2AddrModeImm8Offset(Op, LD->getOffset(), Offset)) {
|
||||
switch (LoadedVT.getSimpleVT()) {
|
||||
case MVT::i32:
|
||||
Opcode = isPre ? ARM::t2LDR_PRE : ARM::t2LDR_POST;
|
||||
break;
|
||||
case MVT::i16:
|
||||
Opcode = isPre ? ARM::t2LDRH_PRE : ARM::t2LDRH_POST;
|
||||
break;
|
||||
case MVT::i8:
|
||||
Opcode = isPre ? ARM::t2LDRB_PRE : ARM::t2LDRB_POST;
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
Match = true;
|
||||
}
|
||||
|
||||
if (Match) {
|
||||
SDValue Chain = LD->getChain();
|
||||
SDValue Base = LD->getBasePtr();
|
||||
SDValue Ops[]= { Base, Offset, getAL(CurDAG),
|
||||
CurDAG->getRegister(0, MVT::i32), Chain };
|
||||
return CurDAG->getTargetNode(Opcode, Op.getDebugLoc(), MVT::i32, MVT::i32,
|
||||
MVT::Other, Ops, 5);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
SDNode *ARMDAGToDAGISel::Select(SDValue Op) {
|
||||
SDNode *N = Op.getNode();
|
||||
@ -892,7 +957,11 @@ SDNode *ARMDAGToDAGISel::Select(SDValue Op) {
|
||||
return CurDAG->getTargetNode(ARM::SMULL, dl, MVT::i32, MVT::i32, Ops, 5);
|
||||
}
|
||||
case ISD::LOAD: {
|
||||
SDNode *ResNode = SelectARMIndexedLoad(Op);
|
||||
SDNode *ResNode = 0;
|
||||
if (Subtarget->isThumb2())
|
||||
ResNode = SelectT2IndexedLoad(Op);
|
||||
else
|
||||
ResNode = SelectARMIndexedLoad(Op);
|
||||
if (ResNode)
|
||||
return ResNode;
|
||||
// Other cases are autogenerated.
|
||||
|
@ -231,16 +231,18 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM)
|
||||
setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote);
|
||||
|
||||
// ARM supports all 4 flavors of integer indexed load / store.
|
||||
for (unsigned im = (unsigned)ISD::PRE_INC;
|
||||
im != (unsigned)ISD::LAST_INDEXED_MODE; ++im) {
|
||||
setIndexedLoadAction(im, MVT::i1, Legal);
|
||||
setIndexedLoadAction(im, MVT::i8, Legal);
|
||||
setIndexedLoadAction(im, MVT::i16, Legal);
|
||||
setIndexedLoadAction(im, MVT::i32, Legal);
|
||||
setIndexedStoreAction(im, MVT::i1, Legal);
|
||||
setIndexedStoreAction(im, MVT::i8, Legal);
|
||||
setIndexedStoreAction(im, MVT::i16, Legal);
|
||||
setIndexedStoreAction(im, MVT::i32, Legal);
|
||||
if (!Subtarget->isThumb1Only()) {
|
||||
for (unsigned im = (unsigned)ISD::PRE_INC;
|
||||
im != (unsigned)ISD::LAST_INDEXED_MODE; ++im) {
|
||||
setIndexedLoadAction(im, MVT::i1, Legal);
|
||||
setIndexedLoadAction(im, MVT::i8, Legal);
|
||||
setIndexedLoadAction(im, MVT::i16, Legal);
|
||||
setIndexedLoadAction(im, MVT::i32, Legal);
|
||||
setIndexedStoreAction(im, MVT::i1, Legal);
|
||||
setIndexedStoreAction(im, MVT::i8, Legal);
|
||||
setIndexedStoreAction(im, MVT::i16, Legal);
|
||||
setIndexedStoreAction(im, MVT::i32, Legal);
|
||||
}
|
||||
}
|
||||
|
||||
// i64 operation support.
|
||||
@ -2923,10 +2925,10 @@ bool ARMTargetLowering::isLegalAddressingMode(const AddrMode &AM,
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool getIndexedAddressParts(SDNode *Ptr, MVT VT,
|
||||
bool isSEXTLoad, SDValue &Base,
|
||||
SDValue &Offset, bool &isInc,
|
||||
SelectionDAG &DAG) {
|
||||
static bool getARMIndexedAddressParts(SDNode *Ptr, MVT VT,
|
||||
bool isSEXTLoad, SDValue &Base,
|
||||
SDValue &Offset, bool &isInc,
|
||||
SelectionDAG &DAG) {
|
||||
if (Ptr->getOpcode() != ISD::ADD && Ptr->getOpcode() != ISD::SUB)
|
||||
return false;
|
||||
|
||||
@ -2936,6 +2938,7 @@ static bool getIndexedAddressParts(SDNode *Ptr, MVT VT,
|
||||
if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(Ptr->getOperand(1))) {
|
||||
int RHSC = (int)RHS->getZExtValue();
|
||||
if (RHSC < 0 && RHSC > -256) {
|
||||
assert(Ptr->getOpcode() == ISD::ADD);
|
||||
isInc = false;
|
||||
Offset = DAG.getConstant(-RHSC, RHS->getValueType(0));
|
||||
return true;
|
||||
@ -2949,6 +2952,7 @@ static bool getIndexedAddressParts(SDNode *Ptr, MVT VT,
|
||||
if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(Ptr->getOperand(1))) {
|
||||
int RHSC = (int)RHS->getZExtValue();
|
||||
if (RHSC < 0 && RHSC > -0x1000) {
|
||||
assert(Ptr->getOpcode() == ISD::ADD);
|
||||
isInc = false;
|
||||
Offset = DAG.getConstant(-RHSC, RHS->getValueType(0));
|
||||
Base = Ptr->getOperand(0);
|
||||
@ -2979,6 +2983,31 @@ static bool getIndexedAddressParts(SDNode *Ptr, MVT VT,
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool getT2IndexedAddressParts(SDNode *Ptr, MVT VT,
|
||||
bool isSEXTLoad, SDValue &Base,
|
||||
SDValue &Offset, bool &isInc,
|
||||
SelectionDAG &DAG) {
|
||||
if (Ptr->getOpcode() != ISD::ADD && Ptr->getOpcode() != ISD::SUB)
|
||||
return false;
|
||||
|
||||
Base = Ptr->getOperand(0);
|
||||
if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(Ptr->getOperand(1))) {
|
||||
int RHSC = (int)RHS->getZExtValue();
|
||||
if (RHSC < 0 && RHSC > -0x100) { // 8 bits.
|
||||
assert(Ptr->getOpcode() == ISD::ADD);
|
||||
isInc = false;
|
||||
Offset = DAG.getConstant(-RHSC, RHS->getValueType(0));
|
||||
return true;
|
||||
} else if (RHSC > 0 && RHSC < 0x100) { // 8 bit, no zero.
|
||||
isInc = Ptr->getOpcode() == ISD::ADD;
|
||||
Offset = DAG.getConstant(RHSC, RHS->getValueType(0));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// getPreIndexedAddressParts - returns true by value, base pointer and
|
||||
/// offset pointer and addressing mode by reference if the node's address
|
||||
/// can be legally represented as pre-indexed load / store address.
|
||||
@ -2987,7 +3016,7 @@ ARMTargetLowering::getPreIndexedAddressParts(SDNode *N, SDValue &Base,
|
||||
SDValue &Offset,
|
||||
ISD::MemIndexedMode &AM,
|
||||
SelectionDAG &DAG) const {
|
||||
if (Subtarget->isThumb())
|
||||
if (Subtarget->isThumb1Only())
|
||||
return false;
|
||||
|
||||
MVT VT;
|
||||
@ -3004,13 +3033,18 @@ ARMTargetLowering::getPreIndexedAddressParts(SDNode *N, SDValue &Base,
|
||||
return false;
|
||||
|
||||
bool isInc;
|
||||
bool isLegal = getIndexedAddressParts(Ptr.getNode(), VT, isSEXTLoad, Base,
|
||||
bool isLegal = false;
|
||||
if (Subtarget->isThumb2())
|
||||
isLegal = getT2IndexedAddressParts(Ptr.getNode(), VT, isSEXTLoad, Base,
|
||||
Offset, isInc, DAG);
|
||||
else
|
||||
isLegal = getARMIndexedAddressParts(Ptr.getNode(), VT, isSEXTLoad, Base,
|
||||
Offset, isInc, DAG);
|
||||
if (isLegal) {
|
||||
AM = isInc ? ISD::PRE_INC : ISD::PRE_DEC;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
if (!isLegal)
|
||||
return false;
|
||||
|
||||
AM = isInc ? ISD::PRE_INC : ISD::PRE_DEC;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// getPostIndexedAddressParts - returns true by value, base pointer and
|
||||
@ -3021,7 +3055,7 @@ bool ARMTargetLowering::getPostIndexedAddressParts(SDNode *N, SDNode *Op,
|
||||
SDValue &Offset,
|
||||
ISD::MemIndexedMode &AM,
|
||||
SelectionDAG &DAG) const {
|
||||
if (Subtarget->isThumb())
|
||||
if (Subtarget->isThumb1Only())
|
||||
return false;
|
||||
|
||||
MVT VT;
|
||||
@ -3036,13 +3070,18 @@ bool ARMTargetLowering::getPostIndexedAddressParts(SDNode *N, SDNode *Op,
|
||||
return false;
|
||||
|
||||
bool isInc;
|
||||
bool isLegal = getIndexedAddressParts(Op, VT, isSEXTLoad, Base, Offset,
|
||||
bool isLegal = false;
|
||||
if (Subtarget->isThumb2())
|
||||
isLegal = getT2IndexedAddressParts(Op, VT, isSEXTLoad, Base, Offset,
|
||||
isInc, DAG);
|
||||
if (isLegal) {
|
||||
AM = isInc ? ISD::POST_INC : ISD::POST_DEC;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
else
|
||||
isLegal = getARMIndexedAddressParts(Op, VT, isSEXTLoad, Base, Offset,
|
||||
isInc, DAG);
|
||||
if (!isLegal)
|
||||
return false;
|
||||
|
||||
AM = isInc ? ISD::POST_INC : ISD::POST_DEC;
|
||||
return true;
|
||||
}
|
||||
|
||||
void ARMTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
|
||||
|
@ -873,6 +873,18 @@ class T2XI<dag oops, dag iops, string asm, list<dag> pattern>
|
||||
class T2JTI<dag oops, dag iops, string asm, list<dag> pattern>
|
||||
: Thumb2XI<oops, iops, AddrModeNone, SizeSpecial, asm, "", pattern>;
|
||||
|
||||
// T2Iidxldst - Thumb2 indexed load / store instructions.
|
||||
class T2Iidxldst<dag oops, dag iops, AddrMode am, IndexMode im,
|
||||
string opc, string asm, string cstr, list<dag> pattern>
|
||||
: InstARM<am, Size4Bytes, im, ThumbFrm, cstr> {
|
||||
let OutOperandList = oops;
|
||||
let InOperandList = !con(iops, (ops pred:$p));
|
||||
let AsmString = !strconcat(opc, !strconcat("${p}", asm));
|
||||
let Pattern = pattern;
|
||||
list<Predicate> Predicates = [IsThumb2];
|
||||
}
|
||||
|
||||
|
||||
// T2Pat - Same as Pat<>, but requires that the compiler be in Thumb2 mode.
|
||||
class T2Pat<dag pattern, dag result> : Pat<pattern, result> {
|
||||
list<Predicate> Predicates = [IsThumb2];
|
||||
|
@ -89,7 +89,6 @@ def imm0_65535 : PatLeaf<(i32 imm), [{
|
||||
return (uint32_t)N->getZExtValue() < 65536;
|
||||
}]>;
|
||||
|
||||
|
||||
/// bf_inv_mask_imm predicate - An AND mask to clear an arbitrary width bitfield
|
||||
/// e.g., 0xf000ffff
|
||||
def bf_inv_mask_imm : Operand<i32>,
|
||||
@ -136,13 +135,17 @@ def t2addrmode_imm12 : Operand<i32>,
|
||||
let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
|
||||
}
|
||||
|
||||
// t2addrmode_imm8 := reg - imm8 (also reg + imm8 for some instructions)
|
||||
// t2addrmode_imm8 := reg - imm8
|
||||
def t2addrmode_imm8 : Operand<i32>,
|
||||
ComplexPattern<i32, 2, "SelectT2AddrModeImm8", []> {
|
||||
let PrintMethod = "printT2AddrModeImm8Operand";
|
||||
let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
|
||||
}
|
||||
|
||||
def t2am_imm8_offset : Operand<i32> {
|
||||
let PrintMethod = "printT2AddrModeImm8OffsetOperand";
|
||||
}
|
||||
|
||||
// t2addrmode_imm8s4 := reg + (imm8 << 2)
|
||||
def t2addrmode_imm8s4 : Operand<i32>,
|
||||
ComplexPattern<i32, 2, "SelectT2AddrModeImm8s4", []> {
|
||||
@ -541,10 +544,45 @@ def : T2Pat<(extloadi16 t2addrmode_so_reg:$addr),
|
||||
def : T2Pat<(extloadi16 (ARMWrapper tconstpool:$addr)),
|
||||
(t2LDRHpci tconstpool:$addr)>;
|
||||
|
||||
// Indexed loads
|
||||
def t2LDR_PRE : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb),
|
||||
(ins t2addrmode_imm8:$addr),
|
||||
AddrModeT2_i8, IndexModePre,
|
||||
"ldr", " $dst, $addr!", "$addr.base = $base_wb",
|
||||
[]>;
|
||||
|
||||
def t2LDR_POST : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb),
|
||||
(ins GPR:$base, t2am_imm8_offset:$offset),
|
||||
AddrModeT2_i8, IndexModePost,
|
||||
"ldr", " $dst, [$base], $offset", "$base = $base_wb",
|
||||
[]>;
|
||||
|
||||
def t2LDRB_PRE : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb),
|
||||
(ins t2addrmode_imm8:$addr),
|
||||
AddrModeT2_i8, IndexModePre,
|
||||
"ldrb", " $dst, $addr!", "$addr.base = $base_wb",
|
||||
[]>;
|
||||
def t2LDRB_POST : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb),
|
||||
(ins GPR:$base, t2am_imm8_offset:$offset),
|
||||
AddrModeT2_i8, IndexModePost,
|
||||
"ldrb", " $dst, [$base], $offset", "$base = $base_wb",
|
||||
[]>;
|
||||
|
||||
def t2LDRH_PRE : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb),
|
||||
(ins t2addrmode_imm8:$addr),
|
||||
AddrModeT2_i8, IndexModePre,
|
||||
"ldrh", " $dst, $addr!", "$addr.base = $base_wb",
|
||||
[]>;
|
||||
def t2LDRH_POST : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb),
|
||||
(ins GPR:$base, t2am_imm8_offset:$offset),
|
||||
AddrModeT2_i8, IndexModePost,
|
||||
"ldrh", " $dst, [$base], $offset", "$base = $base_wb",
|
||||
[]>;
|
||||
|
||||
// Store
|
||||
defm t2STR : T2I_st<"str", BinOpFrag<(store node:$LHS, node:$RHS)>>;
|
||||
defm t2STRB : T2I_st<"strb", BinOpFrag<(truncstorei8 node:$LHS, node:$RHS)>>;
|
||||
defm t2STRH : T2I_st<"strh", BinOpFrag<(truncstorei16 node:$LHS, node:$RHS)>>;
|
||||
defm t2STR : T2I_st<"str", BinOpFrag<(store node:$LHS, node:$RHS)>>;
|
||||
defm t2STRB : T2I_st<"strb", BinOpFrag<(truncstorei8 node:$LHS, node:$RHS)>>;
|
||||
defm t2STRH : T2I_st<"strh", BinOpFrag<(truncstorei16 node:$LHS, node:$RHS)>>;
|
||||
|
||||
// Store doubleword
|
||||
let mayLoad = 1 in
|
||||
|
@ -122,6 +122,7 @@ namespace {
|
||||
void printT2SOOperand(const MachineInstr *MI, int OpNum);
|
||||
void printT2AddrModeImm12Operand(const MachineInstr *MI, int OpNum);
|
||||
void printT2AddrModeImm8Operand(const MachineInstr *MI, int OpNum);
|
||||
void printT2AddrModeImm8OffsetOperand(const MachineInstr *MI, int OpNum);
|
||||
void printT2AddrModeSoRegOperand(const MachineInstr *MI, int OpNum);
|
||||
|
||||
void printPredicateOperand(const MachineInstr *MI, int OpNum);
|
||||
@ -747,6 +748,17 @@ void ARMAsmPrinter::printT2AddrModeImm8Operand(const MachineInstr *MI,
|
||||
O << "]";
|
||||
}
|
||||
|
||||
void ARMAsmPrinter::printT2AddrModeImm8OffsetOperand(const MachineInstr *MI,
|
||||
int OpNum) {
|
||||
const MachineOperand &MO1 = MI->getOperand(OpNum);
|
||||
int32_t OffImm = (int32_t)MO1.getImm();
|
||||
// Don't print +0.
|
||||
if (OffImm < 0)
|
||||
O << "#-" << -OffImm;
|
||||
else if (OffImm > 0)
|
||||
O << "#+" << OffImm;
|
||||
}
|
||||
|
||||
void ARMAsmPrinter::printT2AddrModeSoRegOperand(const MachineInstr *MI,
|
||||
int OpNum) {
|
||||
const MachineOperand &MO1 = MI->getOperand(OpNum);
|
||||
|
12
test/CodeGen/Thumb2/thumb2-ldr_post.ll
Normal file
12
test/CodeGen/Thumb2/thumb2-ldr_post.ll
Normal file
@ -0,0 +1,12 @@
|
||||
; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | \
|
||||
; RUN: grep {ldr.*\\\[.*\],} | count 1
|
||||
|
||||
define i32 @test(i32 %a, i32 %b, i32 %c) {
|
||||
%tmp1 = mul i32 %a, %b ; <i32> [#uses=2]
|
||||
%tmp2 = inttoptr i32 %tmp1 to i32* ; <i32*> [#uses=1]
|
||||
%tmp3 = load i32* %tmp2 ; <i32> [#uses=1]
|
||||
%tmp4 = sub i32 %tmp1, 8 ; <i32> [#uses=1]
|
||||
%tmp5 = mul i32 %tmp4, %tmp3 ; <i32> [#uses=1]
|
||||
ret i32 %tmp5
|
||||
}
|
||||
|
19
test/CodeGen/Thumb2/thumb2-ldr_pre.ll
Normal file
19
test/CodeGen/Thumb2/thumb2-ldr_pre.ll
Normal file
@ -0,0 +1,19 @@
|
||||
; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | \
|
||||
; RUN: grep {ldr.*\\!} | count 2
|
||||
|
||||
define i32* @test1(i32* %X, i32* %dest) {
|
||||
%Y = getelementptr i32* %X, i32 4 ; <i32*> [#uses=2]
|
||||
%A = load i32* %Y ; <i32> [#uses=1]
|
||||
store i32 %A, i32* %dest
|
||||
ret i32* %Y
|
||||
}
|
||||
|
||||
define i32 @test2(i32 %a, i32 %b) {
|
||||
%tmp1 = sub i32 %a, 64 ; <i32> [#uses=2]
|
||||
%tmp2 = inttoptr i32 %tmp1 to i32* ; <i32*> [#uses=1]
|
||||
%tmp3 = load i32* %tmp2 ; <i32> [#uses=1]
|
||||
%tmp4 = sub i32 %tmp1, %b ; <i32> [#uses=1]
|
||||
%tmp5 = add i32 %tmp4, %tmp3 ; <i32> [#uses=1]
|
||||
ret i32 %tmp5
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user