aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Target/Hexagon/HexagonISelDAGToDAG.cpp40
-rw-r--r--lib/Target/Hexagon/HexagonInstrInfo.cpp117
-rw-r--r--lib/Target/Hexagon/HexagonInstrInfoV4.td737
-rw-r--r--lib/Target/Hexagon/HexagonRegisterInfo.cpp66
-rw-r--r--lib/Target/Hexagon/HexagonSubtarget.cpp17
-rw-r--r--test/CodeGen/Hexagon/memops.ll1369
-rw-r--r--test/CodeGen/Hexagon/memops1.ll33
-rw-r--r--test/CodeGen/Hexagon/memops2.ll32
-rw-r--r--test/CodeGen/Hexagon/memops3.ll31
9 files changed, 1948 insertions, 494 deletions
diff --git a/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp b/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
index 3a1c48bac9..8fc9ba1ee8 100644
--- a/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
+++ b/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
@@ -113,6 +113,46 @@ public:
SDNode *SelectAdd(SDNode *N);
bool isConstExtProfitable(SDNode *N) const;
+// XformMskToBitPosU5Imm - Returns the bit position which
+// the single bit 32 bit mask represents.
+// Used in Clr and Set bit immediate memops.
+SDValue XformMskToBitPosU5Imm(uint32_t Imm) {
+ int32_t bitPos;
+ bitPos = Log2_32(Imm);
+ assert(bitPos >= 0 && bitPos < 32 &&
+ "Constant out of range for 32 BitPos Memops");
+ return CurDAG->getTargetConstant(bitPos, MVT::i32);
+}
+
+// XformMskToBitPosU4Imm - Returns the bit position which the single bit 16 bit
+// mask represents. Used in Clr and Set bit immediate memops.
+SDValue XformMskToBitPosU4Imm(uint16_t Imm) {
+ return XformMskToBitPosU5Imm(Imm);
+}
+
+// XformMskToBitPosU3Imm - Returns the bit position which the single bit 8 bit
+// mask represents. Used in Clr and Set bit immediate memops.
+SDValue XformMskToBitPosU3Imm(uint8_t Imm) {
+ return XformMskToBitPosU5Imm(Imm);
+}
+
+// Return true if there is exactly one bit set in V, i.e., if V is one of the
+// following integers: 2^0, 2^1, ..., 2^31.
+bool ImmIsSingleBit(uint32_t v) const {
+ uint32_t c = CountPopulation_64(v);
+ // Only return true if we counted 1 bit.
+ return c == 1;
+}
+
+// XformM5ToU5Imm - Return a target constant with the specified value, of type
+// i32 where the negative literal is transformed into a positive literal for
+// use in -= memops.
+inline SDValue XformM5ToU5Imm(signed Imm) {
+ assert( (Imm >= -31 && Imm <= -1) && "Constant out of range for Memops");
+ return CurDAG->getTargetConstant( - Imm, MVT::i32);
+}
+
+
// XformU7ToU7M1Imm - Return a target constant decremented by 1, in range
// [1..128], used in cmpb.gtu instructions.
inline SDValue XformU7ToU7M1Imm(signed Imm) {
diff --git a/lib/Target/Hexagon/HexagonInstrInfo.cpp b/lib/Target/Hexagon/HexagonInstrInfo.cpp
index 96a252e1b8..2e59f506be 100644
--- a/lib/Target/Hexagon/HexagonInstrInfo.cpp
+++ b/lib/Target/Hexagon/HexagonInstrInfo.cpp
@@ -1991,46 +1991,28 @@ isValidOffset(const int Opcode, const int Offset) const {
return (Offset >= Hexagon_ADDI_OFFSET_MIN) &&
(Offset <= Hexagon_ADDI_OFFSET_MAX);
- case Hexagon::MEMw_ADDi_indexed_MEM_V4 :
- case Hexagon::MEMw_SUBi_indexed_MEM_V4 :
- case Hexagon::MEMw_ADDr_indexed_MEM_V4 :
- case Hexagon::MEMw_SUBr_indexed_MEM_V4 :
- case Hexagon::MEMw_ANDr_indexed_MEM_V4 :
- case Hexagon::MEMw_ORr_indexed_MEM_V4 :
- case Hexagon::MEMw_ADDi_MEM_V4 :
- case Hexagon::MEMw_SUBi_MEM_V4 :
- case Hexagon::MEMw_ADDr_MEM_V4 :
- case Hexagon::MEMw_SUBr_MEM_V4 :
- case Hexagon::MEMw_ANDr_MEM_V4 :
- case Hexagon::MEMw_ORr_MEM_V4 :
+ case Hexagon::MemOPw_ADDi_V4 :
+ case Hexagon::MemOPw_SUBi_V4 :
+ case Hexagon::MemOPw_ADDr_V4 :
+ case Hexagon::MemOPw_SUBr_V4 :
+ case Hexagon::MemOPw_ANDr_V4 :
+ case Hexagon::MemOPw_ORr_V4 :
return (0 <= Offset && Offset <= 255);
- case Hexagon::MEMh_ADDi_indexed_MEM_V4 :
- case Hexagon::MEMh_SUBi_indexed_MEM_V4 :
- case Hexagon::MEMh_ADDr_indexed_MEM_V4 :
- case Hexagon::MEMh_SUBr_indexed_MEM_V4 :
- case Hexagon::MEMh_ANDr_indexed_MEM_V4 :
- case Hexagon::MEMh_ORr_indexed_MEM_V4 :
- case Hexagon::MEMh_ADDi_MEM_V4 :
- case Hexagon::MEMh_SUBi_MEM_V4 :
- case Hexagon::MEMh_ADDr_MEM_V4 :
- case Hexagon::MEMh_SUBr_MEM_V4 :
- case Hexagon::MEMh_ANDr_MEM_V4 :
- case Hexagon::MEMh_ORr_MEM_V4 :
+ case Hexagon::MemOPh_ADDi_V4 :
+ case Hexagon::MemOPh_SUBi_V4 :
+ case Hexagon::MemOPh_ADDr_V4 :
+ case Hexagon::MemOPh_SUBr_V4 :
+ case Hexagon::MemOPh_ANDr_V4 :
+ case Hexagon::MemOPh_ORr_V4 :
return (0 <= Offset && Offset <= 127);
- case Hexagon::MEMb_ADDi_indexed_MEM_V4 :
- case Hexagon::MEMb_SUBi_indexed_MEM_V4 :
- case Hexagon::MEMb_ADDr_indexed_MEM_V4 :
- case Hexagon::MEMb_SUBr_indexed_MEM_V4 :
- case Hexagon::MEMb_ANDr_indexed_MEM_V4 :
- case Hexagon::MEMb_ORr_indexed_MEM_V4 :
- case Hexagon::MEMb_ADDi_MEM_V4 :
- case Hexagon::MEMb_SUBi_MEM_V4 :
- case Hexagon::MEMb_ADDr_MEM_V4 :
- case Hexagon::MEMb_SUBr_MEM_V4 :
- case Hexagon::MEMb_ANDr_MEM_V4 :
- case Hexagon::MEMb_ORr_MEM_V4 :
+ case Hexagon::MemOPb_ADDi_V4 :
+ case Hexagon::MemOPb_SUBi_V4 :
+ case Hexagon::MemOPb_ADDr_V4 :
+ case Hexagon::MemOPb_SUBr_V4 :
+ case Hexagon::MemOPb_ANDr_V4 :
+ case Hexagon::MemOPb_ORr_V4 :
return (0 <= Offset && Offset <= 63);
// LDri_pred and STriw_pred are pseudo operations, so it has to take offset of
@@ -2086,44 +2068,33 @@ isMemOp(const MachineInstr *MI) const {
switch (MI->getOpcode())
{
default: return false;
- case Hexagon::MEMw_ADDi_indexed_MEM_V4 :
- case Hexagon::MEMw_SUBi_indexed_MEM_V4 :
- case Hexagon::MEMw_ADDr_indexed_MEM_V4 :
- case Hexagon::MEMw_SUBr_indexed_MEM_V4 :
- case Hexagon::MEMw_ANDr_indexed_MEM_V4 :
- case Hexagon::MEMw_ORr_indexed_MEM_V4 :
- case Hexagon::MEMw_ADDi_MEM_V4 :
- case Hexagon::MEMw_SUBi_MEM_V4 :
- case Hexagon::MEMw_ADDr_MEM_V4 :
- case Hexagon::MEMw_SUBr_MEM_V4 :
- case Hexagon::MEMw_ANDr_MEM_V4 :
- case Hexagon::MEMw_ORr_MEM_V4 :
- case Hexagon::MEMh_ADDi_indexed_MEM_V4 :
- case Hexagon::MEMh_SUBi_indexed_MEM_V4 :
- case Hexagon::MEMh_ADDr_indexed_MEM_V4 :
- case Hexagon::MEMh_SUBr_indexed_MEM_V4 :
- case Hexagon::MEMh_ANDr_indexed_MEM_V4 :
- case Hexagon::MEMh_ORr_indexed_MEM_V4 :
- case Hexagon::MEMh_ADDi_MEM_V4 :
- case Hexagon::MEMh_SUBi_MEM_V4 :
- case Hexagon::MEMh_ADDr_MEM_V4 :
- case Hexagon::MEMh_SUBr_MEM_V4 :
- case Hexagon::MEMh_ANDr_MEM_V4 :
- case Hexagon::MEMh_ORr_MEM_V4 :
- case Hexagon::MEMb_ADDi_indexed_MEM_V4 :
- case Hexagon::MEMb_SUBi_indexed_MEM_V4 :
- case Hexagon::MEMb_ADDr_indexed_MEM_V4 :
- case Hexagon::MEMb_SUBr_indexed_MEM_V4 :
- case Hexagon::MEMb_ANDr_indexed_MEM_V4 :
- case Hexagon::MEMb_ORr_indexed_MEM_V4 :
- case Hexagon::MEMb_ADDi_MEM_V4 :
- case Hexagon::MEMb_SUBi_MEM_V4 :
- case Hexagon::MEMb_ADDr_MEM_V4 :
- case Hexagon::MEMb_SUBr_MEM_V4 :
- case Hexagon::MEMb_ANDr_MEM_V4 :
- case Hexagon::MEMb_ORr_MEM_V4 :
- return true;
+ case Hexagon::MemOPw_ADDi_V4 :
+ case Hexagon::MemOPw_SUBi_V4 :
+ case Hexagon::MemOPw_ADDr_V4 :
+ case Hexagon::MemOPw_SUBr_V4 :
+ case Hexagon::MemOPw_ANDr_V4 :
+ case Hexagon::MemOPw_ORr_V4 :
+ case Hexagon::MemOPh_ADDi_V4 :
+ case Hexagon::MemOPh_SUBi_V4 :
+ case Hexagon::MemOPh_ADDr_V4 :
+ case Hexagon::MemOPh_SUBr_V4 :
+ case Hexagon::MemOPh_ANDr_V4 :
+ case Hexagon::MemOPh_ORr_V4 :
+ case Hexagon::MemOPb_ADDi_V4 :
+ case Hexagon::MemOPb_SUBi_V4 :
+ case Hexagon::MemOPb_ADDr_V4 :
+ case Hexagon::MemOPb_SUBr_V4 :
+ case Hexagon::MemOPb_ANDr_V4 :
+ case Hexagon::MemOPb_ORr_V4 :
+ case Hexagon::MemOPb_SETBITi_V4:
+ case Hexagon::MemOPh_SETBITi_V4:
+ case Hexagon::MemOPw_SETBITi_V4:
+ case Hexagon::MemOPb_CLRBITi_V4:
+ case Hexagon::MemOPh_CLRBITi_V4:
+ case Hexagon::MemOPw_CLRBITi_V4:
+ return true;
}
+ return false;
}
diff --git a/lib/Target/Hexagon/HexagonInstrInfoV4.td b/lib/Target/Hexagon/HexagonInstrInfoV4.td
index 1d0643d03b..48b3b2c4cd 100644
--- a/lib/Target/Hexagon/HexagonInstrInfoV4.td
+++ b/lib/Target/Hexagon/HexagonInstrInfoV4.td
@@ -2658,414 +2658,367 @@ def LSRd_rr_xor_V4 : MInst_acc<(outs DoubleRegs:$dst),
// MEMOP: Word, Half, Byte
//===----------------------------------------------------------------------===//
+def MEMOPIMM : SDNodeXForm<imm, [{
+ // Call the transformation function XformM5ToU5Imm to get the negative
+ // immediate's positive counterpart.
+ int32_t imm = N->getSExtValue();
+ return XformM5ToU5Imm(imm);
+}]>;
+
+def MEMOPIMM_HALF : SDNodeXForm<imm, [{
+ // -1 .. -31 represented as 65535..65515
+ // assigning to a short restores our desired signed value.
+ // Call the transformation function XformM5ToU5Imm to get the negative
+ // immediate's positive counterpart.
+ int16_t imm = N->getSExtValue();
+ return XformM5ToU5Imm(imm);
+}]>;
+
+def MEMOPIMM_BYTE : SDNodeXForm<imm, [{
+ // -1 .. -31 represented as 255..235
+ // assigning to a char restores our desired signed value.
+ // Call the transformation function XformM5ToU5Imm to get the negative
+ // immediate's positive counterpart.
+ int8_t imm = N->getSExtValue();
+ return XformM5ToU5Imm(imm);
+}]>;
+
+def SETMEMIMM : SDNodeXForm<imm, [{
+ // Return the bit position we will set [0-31].
+ // As an SDNode.
+ int32_t imm = N->getSExtValue();
+ return XformMskToBitPosU5Imm(imm);
+}]>;
+
+def CLRMEMIMM : SDNodeXForm<imm, [{
+ // Return the bit position we will clear [0-31].
+ // As an SDNode.
+ // we bit negate the value first
+ int32_t imm = ~(N->getSExtValue());
+ return XformMskToBitPosU5Imm(imm);
+}]>;
+
+def SETMEMIMM_SHORT : SDNodeXForm<imm, [{
+ // Return the bit position we will set [0-15].
+ // As an SDNode.
+ int16_t imm = N->getSExtValue();
+ return XformMskToBitPosU4Imm(imm);
+}]>;
+
+def CLRMEMIMM_SHORT : SDNodeXForm<imm, [{
+ // Return the bit position we will clear [0-15].
+ // As an SDNode.
+ // we bit negate the value first
+ int16_t imm = ~(N->getSExtValue());
+ return XformMskToBitPosU4Imm(imm);
+}]>;
+
+def SETMEMIMM_BYTE : SDNodeXForm<imm, [{
+ // Return the bit position we will set [0-7].
+ // As an SDNode.
+ int8_t imm = N->getSExtValue();
+ return XformMskToBitPosU3Imm(imm);
+}]>;
+
+def CLRMEMIMM_BYTE : SDNodeXForm<imm, [{
+ // Return the bit position we will clear [0-7].
+ // As an SDNode.
+ // we bit negate the value first
+ int8_t imm = ~(N->getSExtValue());
+ return XformMskToBitPosU3Imm(imm);
+}]>;
+
//===----------------------------------------------------------------------===//
-// MEMOP: Word
-//
-// Implemented:
-// MEMw_ADDi_indexed_V4 : memw(Rs+#u6:2)+=#U5
-// MEMw_SUBi_indexed_V4 : memw(Rs+#u6:2)-=#U5
-// MEMw_ADDr_indexed_V4 : memw(Rs+#u6:2)+=Rt
-// MEMw_SUBr_indexed_V4 : memw(Rs+#u6:2)-=Rt
-// MEMw_CLRr_indexed_V4 : memw(Rs+#u6:2)&=Rt
-// MEMw_SETr_indexed_V4 : memw(Rs+#u6:2)|=Rt
-// MEMw_ADDi_V4 : memw(Rs+#u6:2)+=#U5
-// MEMw_SUBi_V4 : memw(Rs+#u6:2)-=#U5
-// MEMw_ADDr_V4 : memw(Rs+#u6:2)+=Rt
-// MEMw_SUBr_V4 : memw(Rs+#u6:2)-=Rt
-// MEMw_CLRr_V4 : memw(Rs+#u6:2)&=Rt
-// MEMw_SETr_V4 : memw(Rs+#u6:2)|=Rt
-//
-// Not implemented:
-// MEMw_CLRi_indexed_V4 : memw(Rs+#u6:2)=clrbit(#U5)
-// MEMw_SETi_indexed_V4 : memw(Rs+#u6:2)=setbit(#U5)
-// MEMw_CLRi_V4 : memw(Rs+#u6:2)=clrbit(#U5)
-// MEMw_SETi_V4 : memw(Rs+#u6:2)=setbit(#U5)
+// Template class for MemOp instructions with the register value.
//===----------------------------------------------------------------------===//
+class MemOp_rr_base <string opc, bits<2> opcBits, Operand ImmOp,
+ string memOp, bits<2> memOpBits> :
+ MEMInst_V4<(outs),
+ (ins IntRegs:$base, ImmOp:$offset, IntRegs:$delta),
+ opc#"($base+#$offset)"#memOp#"$delta",
+ []>,
+ Requires<[HasV4T, UseMEMOP]> {
+
+ bits<5> base;
+ bits<5> delta;
+ bits<32> offset;
+ bits<6> offsetBits; // memb - u6:0 , memh - u6:1, memw - u6:2
+
+ let offsetBits = !if (!eq(opcBits, 0b00), offset{5-0},
+ !if (!eq(opcBits, 0b01), offset{6-1},
+ !if (!eq(opcBits, 0b10), offset{7-2},0)));
+
+ let IClass = 0b0011;
+ let Inst{27-24} = 0b1110;
+ let Inst{22-21} = opcBits;
+ let Inst{20-16} = base;
+ let Inst{13} = 0b0;
+ let Inst{12-7} = offsetBits;
+ let Inst{6-5} = memOpBits;
+ let Inst{4-0} = delta;
+}
+//===----------------------------------------------------------------------===//
+// Template class for MemOp instructions with the immediate value.
+//===----------------------------------------------------------------------===//
+class MemOp_ri_base <string opc, bits<2> opcBits, Operand ImmOp,
+ string memOp, bits<2> memOpBits> :
+ MEMInst_V4 <(outs),
+ (ins IntRegs:$base, ImmOp:$offset, u5Imm:$delta),
+ opc#"($base+#$offset)"#memOp#"#$delta"
+ #!if(memOpBits{1},")", ""), // clrbit, setbit - include ')'
+ []>,
+ Requires<[HasV4T, UseMEMOP]> {
+
+ bits<5> base;
+ bits<5> delta;
+ bits<32> offset;
+ bits<6> offsetBits; // memb - u6:0 , memh - u6:1, memw - u6:2
+
+ let offsetBits = !if (!eq(opcBits, 0b00), offset{5-0},
+ !if (!eq(opcBits, 0b01), offset{6-1},
+ !if (!eq(opcBits, 0b10), offset{7-2},0)));
+
+ let IClass = 0b0011;
+ let Inst{27-24} = 0b1111;
+ let Inst{22-21} = opcBits;
+ let Inst{20-16} = base;
+ let Inst{13} = 0b0;
+ let Inst{12-7} = offsetBits;
+ let Inst{6-5} = memOpBits;
+ let Inst{4-0} = delta;
+}
+// multiclass to define MemOp instructions with register operand.
+multiclass MemOp_rr<string opc, bits<2> opcBits, Operand ImmOp> {
+ def _ADD#NAME#_V4 : MemOp_rr_base <opc, opcBits, ImmOp, " += ", 0b00>; // add
+ def _SUB#NAME#_V4 : MemOp_rr_base <opc, opcBits, ImmOp, " -= ", 0b01>; // sub
+ def _AND#NAME#_V4 : MemOp_rr_base <opc, opcBits, ImmOp, " &= ", 0b10>; // and
+ def _OR#NAME#_V4 : MemOp_rr_base <opc, opcBits, ImmOp, " |= ", 0b11>; // or
+}
-// memw(Rs+#u6:2) += #U5
-let AddedComplexity = 30 in
-def MEMw_ADDi_indexed_MEM_V4 : MEMInst_V4<(outs),
- (ins IntRegs:$base, u6_2Imm:$offset, u5Imm:$addend),
- "memw($base+#$offset) += #$addend",
- []>,
- Requires<[HasV4T, UseMEMOP]>;
-
-// memw(Rs+#u6:2) -= #U5
-let AddedComplexity = 30 in
-def MEMw_SUBi_indexed_MEM_V4 : MEMInst_V4<(outs),
- (ins IntRegs:$base, u6_2Imm:$offset, u5Imm:$subend),
- "memw($base+#$offset) -= #$subend",
- []>,
- Requires<[HasV4T, UseMEMOP]>;
-
-// memw(Rs+#u6:2) += Rt
-let AddedComplexity = 30 in
-def MEMw_ADDr_indexed_MEM_V4 : MEMInst_V4<(outs),
- (ins IntRegs:$base, u6_2Imm:$offset, IntRegs:$addend),
- "memw($base+#$offset) += $addend",
- [(store (add (load (add (i32 IntRegs:$base), u6_2ImmPred:$offset)),
- (i32 IntRegs:$addend)),
- (add (i32 IntRegs:$base), u6_2ImmPred:$offset))]>,
- Requires<[HasV4T, UseMEMOP]>;
-
-// memw(Rs+#u6:2) -= Rt
-let AddedComplexity = 30 in
-def MEMw_SUBr_indexed_MEM_V4 : MEMInst_V4<(outs),
- (ins IntRegs:$base, u6_2Imm:$offset, IntRegs:$subend),
- "memw($base+#$offset) -= $subend",
- [(store (sub (load (add (i32 IntRegs:$base), u6_2ImmPred:$offset)),
- (i32 IntRegs:$subend)),
- (add (i32 IntRegs:$base), u6_2ImmPred:$offset))]>,
- Requires<[HasV4T, UseMEMOP]>;
-
-// memw(Rs+#u6:2) &= Rt
-let AddedComplexity = 30 in
-def MEMw_ANDr_indexed_MEM_V4 : MEMInst_V4<(outs),
- (ins IntRegs:$base, u6_2Imm:$offset, IntRegs:$andend),
- "memw($base+#$offset) &= $andend",
- [(store (and (load (add (i32 IntRegs:$base), u6_2ImmPred:$offset)),
- (i32 IntRegs:$andend)),
- (add (i32 IntRegs:$base), u6_2ImmPred:$offset))]>,
- Requires<[HasV4T, UseMEMOP]>;
-
-// memw(Rs+#u6:2) |= Rt
-let AddedComplexity = 30 in
-def MEMw_ORr_indexed_MEM_V4 : MEMInst_V4<(outs),
- (ins IntRegs:$base, u6_2Imm:$offset, IntRegs:$orend),
- "memw($base+#$offset) |= $orend",
- [(store (or (load (add (i32 IntRegs:$base), u6_2ImmPred:$offset)),
- (i32 IntRegs:$orend)),
- (add (i32 IntRegs:$base), u6_2ImmPred:$offset))]>,
- Requires<[HasV4T, UseMEMOP]>;
-
-// memw(Rs+#u6:2) += #U5
-let AddedComplexity = 30 in
-def MEMw_ADDi_MEM_V4 : MEMInst_V4<(outs),
- (ins MEMri:$addr, u5Imm:$addend),
- "memw($addr) += $addend",
- []>,
- Requires<[HasV4T, UseMEMOP]>;
-
-// memw(Rs+#u6:2) -= #U5
-let AddedComplexity = 30 in
-def MEMw_SUBi_MEM_V4 : MEMInst_V4<(outs),
- (ins MEMri:$addr, u5Imm:$subend),
- "memw($addr) -= $subend",
- []>,
- Requires<[HasV4T, UseMEMOP]>;
-
-// memw(Rs+#u6:2) += Rt
-let AddedComplexity = 30 in
-def MEMw_ADDr_MEM_V4 : MEMInst_V4<(outs),
- (ins MEMri:$addr, IntRegs:$addend),
- "memw($addr) += $addend",
- [(store (add (load ADDRriU6_2:$addr), (i32 IntRegs:$addend)),
- ADDRriU6_2:$addr)]>,
- Requires<[HasV4T, UseMEMOP]>;
-
-// memw(Rs+#u6:2) -= Rt
-let AddedComplexity = 30 in
-def MEMw_SUBr_MEM_V4 : MEMInst_V4<(outs),
- (ins MEMri:$addr, IntRegs:$subend),
- "memw($addr) -= $subend",
- [(store (sub (load ADDRriU6_2:$addr), (i32 IntRegs:$subend)),
- ADDRriU6_2:$addr)]>,
- Requires<[HasV4T, UseMEMOP]>;
-
-// memw(Rs+#u6:2) &= Rt
-let AddedComplexity = 30 in
-def MEMw_ANDr_MEM_V4 : MEMInst_V4<(outs),
- (ins MEMri:$addr, IntRegs:$andend),
- "memw($addr) &= $andend",
- [(store (and (load ADDRriU6_2:$addr), (i32 IntRegs:$andend)),
- ADDRriU6_2:$addr)]>,
- Requires<[HasV4T, UseMEMOP]>;
-
-// memw(Rs+#u6:2) |= Rt
-let AddedComplexity = 30 in
-def MEMw_ORr_MEM_V4 : MEMInst_V4<(outs),
- (ins MEMri:$addr, IntRegs:$orend),
- "memw($addr) |= $orend",
- [(store (or (load ADDRriU6_2:$addr), (i32 IntRegs:$orend)),
- ADDRriU6_2:$addr)]>,
- Requires<[HasV4T, UseMEMOP]>;
+// multiclass to define MemOp instructions with immediate Operand.
+multiclass MemOp_ri<string opc, bits<2> opcBits, Operand ImmOp> {
+ def _ADD#NAME#_V4 : MemOp_ri_base <opc, opcBits, ImmOp, " += ", 0b00 >;
+ def _SUB#NAME#_V4 : MemOp_ri_base <opc, opcBits, ImmOp, " -= ", 0b01 >;
+ def _CLRBIT#NAME#_V4 : MemOp_ri_base<opc, opcBits, ImmOp, " =clrbit(", 0b10>;
+ def _SETBIT#NAME#_V4 : MemOp_ri_base<opc, opcBits, ImmOp, " =setbit(", 0b11>;
+}
+
+multiclass MemOp_base <string opc, bits<2> opcBits, Operand ImmOp> {
+ defm r : MemOp_rr <opc, opcBits, ImmOp>;
+ defm i : MemOp_ri <opc, opcBits, ImmOp>;
+}
+
+// Define MemOp instructions.
+let isExtendable = 1, opExtendable = 1, isExtentSigned = 0,
+validSubTargets =HasV4SubT in {
+ let opExtentBits = 6, accessSize = ByteAccess in
+ defm MemOPb : MemOp_base <"memb", 0b00, u6_0Ext>;
+
+ let opExtentBits = 7, accessSize = HalfWordAccess in
+ defm MemOPh : MemOp_base <"memh", 0b01, u6_1Ext>;
+
+ let opExtentBits = 8, accessSize = WordAccess in
+ defm MemOPw : MemOp_base <"memw", 0b10, u6_2Ext>;
+}
//===----------------------------------------------------------------------===//
-// MEMOP: Halfword
-//
-// Implemented:
-// MEMh_ADDi_indexed_V4 : memw(Rs+#u6:2)+=#U5
-// MEMh_SUBi_indexed_V4 : memw(Rs+#u6:2)-=#U5
-// MEMh_ADDr_indexed_V4 : memw(Rs+#u6:2)+=Rt
-// MEMh_SUBr_indexed_V4 : memw(Rs+#u6:2)-=Rt
-// MEMh_CLRr_indexed_V4 : memw(Rs+#u6:2)&=Rt
-// MEMh_SETr_indexed_V4 : memw(Rs+#u6:2)|=Rt
-// MEMh_ADDi_V4 : memw(Rs+#u6:2)+=#U5
-// MEMh_SUBi_V4 : memw(Rs+#u6:2)-=#U5
-// MEMh_ADDr_V4 : memw(Rs+#u6:2)+=Rt
-// MEMh_SUBr_V4 : memw(Rs+#u6:2)-=Rt
-// MEMh_CLRr_V4 : memw(Rs+#u6:2)&=Rt
-// MEMh_SETr_V4 : memw(Rs+#u6:2)|=Rt
-//
-// Not implemented:
-// MEMh_CLRi_indexed_V4 : memw(Rs+#u6:2)=clrbit(#U5)
-// MEMh_SETi_indexed_V4 : memw(Rs+#u6:2)=setbit(#U5)
-// MEMh_CLRi_V4 : memw(Rs+#u6:2)=clrbit(#U5)
-// MEMh_SETi_V4 : memw(Rs+#u6:2)=setbit(#U5)
+// Multiclass to define 'Def Pats' for ALU operations on the memory
+// Here value used for the ALU operation is an immediate value.
+// mem[bh](Rs+#0) += #U5
+// mem[bh](Rs+#u6) += #U5
//===----------------------------------------------------------------------===//
+multiclass MemOpi_u5Pats <PatFrag ldOp, PatFrag stOp, PatLeaf ExtPred,
+ InstHexagon MI, SDNode OpNode> {
+ let AddedComplexity = 180 in
+ def : Pat < (stOp (OpNode (ldOp IntRegs:$addr), u5ImmPred:$addend),
+ IntRegs:$addr),
+ (MI IntRegs:$addr, #0, u5ImmPred:$addend )>;
+
+ let AddedComplexity = 190 in
+ def : Pat <(stOp (OpNode (ldOp (add IntRegs:$base, ExtPred:$offset)),
+ u5ImmPred:$addend),
+ (add IntRegs:$base, ExtPred:$offset)),
+ (MI IntRegs:$base, ExtPred:$offset, u5ImmPred:$addend)>;
+}
-// memh(Rs+#u6:1) += #U5
-let AddedComplexity = 30 in
-def MEMh_ADDi_indexed_MEM_V4 : MEMInst_V4<(outs),
- (ins IntRegs:$base, u6_1Imm:$offset, u5Imm:$addend),
- "memh($base+#$offset) += $addend",
- []>,
- Requires<[HasV4T, UseMEMOP]>;
-
-// memh(Rs+#u6:1) -= #U5
-let AddedComplexity = 30 in
-def MEMh_SUBi_indexed_MEM_V4 : MEMInst_V4<(outs),
- (ins IntRegs:$base, u6_1Imm:$offset, u5Imm:$subend),
- "memh($base+#$offset) -= $subend",
- []>,
- Requires<[HasV4T, UseMEMOP]>;
-
-// memh(Rs+#u6:1) += Rt
-let AddedComplexity = 30 in
-def MEMh_ADDr_indexed_MEM_V4 : MEMInst_V4<(outs),
- (ins IntRegs:$base, u6_1Imm:$offset, IntRegs:$addend),
- "memh($base+#$offset) += $addend",
- [(truncstorei16 (add (sextloadi16 (add (i32 IntRegs:$base),
- u6_1ImmPred:$offset)),
- (i32 IntRegs:$addend)),
- (add (i32 IntRegs:$base), u6_1ImmPred:$offset))]>,
- Requires<[HasV4T, UseMEMOP]>;
-
-// memh(Rs+#u6:1) -= Rt
-let AddedComplexity = 30 in
-def MEMh_SUBr_indexed_MEM_V4 : MEMInst_V4<(outs),
- (ins IntRegs:$base, u6_1Imm:$offset, IntRegs:$subend),
- "memh($base+#$offset) -= $subend",
- [(truncstorei16 (sub (sextloadi16 (add (i32 IntRegs:$base),
- u6_1ImmPred:$offset)),
- (i32 IntRegs:$subend)),
- (add (i32 IntRegs:$base), u6_1ImmPred:$offset))]>,
- Requires<[HasV4T, UseMEMOP]>;
-
-// memh(Rs+#u6:1) &= Rt
-let AddedComplexity = 30 in
-def MEMh_ANDr_indexed_MEM_V4 : MEMInst_V4<(outs),
- (ins IntRegs:$base, u6_1Imm:$offset, IntRegs:$andend),
- "memh($base+#$offset) += $andend",
- [(truncstorei16 (and (sextloadi16 (add (i32 IntRegs:$base),
- u6_1ImmPred:$offset)),
- (i32 IntRegs:$andend)),
- (add (i32 IntRegs:$base), u6_1ImmPred:$offset))]>,
- Requires<[HasV4T, UseMEMOP]>;
-
-// memh(Rs+#u6:1) |= Rt
-let AddedComplexity = 30 in
-def MEMh_ORr_indexed_MEM_V4 : MEMInst_V4<(outs),
- (ins IntRegs:$base, u6_1Imm:$offset, IntRegs:$orend),
- "memh($base+#$offset) |= $orend",
- [(truncstorei16 (or (sextloadi16 (add (i32 IntRegs:$base),
- u6_1ImmPred:$offset)),
- (i32 IntRegs:$orend)),
- (add (i32 IntRegs:$base), u6_1ImmPred:$offset))]>,
- Requires<[HasV4T, UseMEMOP]>;
-
-// memh(Rs+#u6:1) += #U5
-let AddedComplexity = 30 in
-def MEMh_ADDi_MEM_V4 : MEMInst_V4<(outs),
- (ins MEMri:$addr, u5Imm:$addend),
- "memh($addr) += $addend",
- []>,
- Requires<[HasV4T, UseMEMOP]>;
-
-// memh(Rs+#u6:1) -= #U5
-let AddedComplexity = 30 in
-def MEMh_SUBi_MEM_V4 : MEMInst_V4<(outs),
- (ins MEMri:$addr, u5Imm:$subend),
- "memh($addr) -= $subend",
- []>,
- Requires<[HasV4T, UseMEMOP]>;
-
-// memh(Rs+#u6:1) += Rt
-let AddedComplexity = 30 in
-def MEMh_ADDr_MEM_V4 : MEMInst_V4<(outs),
- (ins MEMri:$addr, IntRegs:$addend),
- "memh($addr) += $addend",
- [(truncstorei16 (add (sextloadi16 ADDRriU6_1:$addr),
- (i32 IntRegs:$addend)), ADDRriU6_1:$addr)]>,
- Requires<[HasV4T, UseMEMOP]>;
-
-// memh(Rs+#u6:1) -= Rt
-let AddedComplexity = 30 in
-def MEMh_SUBr_MEM_V4 : MEMInst_V4<(outs),
- (ins MEMri:$addr, IntRegs:$subend),
- "memh($addr) -= $subend",
- [(truncstorei16 (sub (sextloadi16 ADDRriU6_1:$addr),
- (i32 IntRegs:$subend)), ADDRriU6_1:$addr)]>,
- Requires<[HasV4T, UseMEMOP]>;
-
-// memh(Rs+#u6:1) &= Rt
-let AddedComplexity = 30 in
-def MEMh_ANDr_MEM_V4 : MEMInst_V4<(outs),
- (ins MEMri:$addr, IntRegs:$andend),
- "memh($addr) &= $andend",
- [(truncstorei16 (and (sextloadi16 ADDRriU6_1:$addr),
- (i32 IntRegs:$andend)), ADDRriU6_1:$addr)]>,
- Requires<[HasV4T, UseMEMOP]>;
-
-// memh(Rs+#u6:1) |= Rt
-let AddedComplexity = 30 in
-def MEMh_ORr_MEM_V4 : MEMInst_V4<(outs),
- (ins MEMri:$addr, IntRegs:$orend),
- "memh($addr) |= $orend",
- [(truncstorei16 (or (sextloadi16 ADDRriU6_1:$addr),
- (i32 IntRegs:$orend)), ADDRriU6_1:$addr)]>,
- Requires<[HasV4T, UseMEMOP]>;
+multiclass MemOpi_u5ALUOp<PatFrag ldOp, PatFrag stOp, PatLeaf ExtPred,
+ InstHexagon addMI, InstHexagon subMI> {
+ defm : MemOpi_u5Pats<ldOp, stOp, ExtPred, addMI, add>;
+ defm : MemOpi_u5Pats<ldOp, stOp, ExtPred, subMI, sub>;
+}
+multiclass MemOpi_u5ExtType<PatFrag ldOpByte, PatFrag ldOpHalf > {
+ // Half Word
+ defm : MemOpi_u5ALUOp <ldOpHalf, truncstorei16, u6_1ExtPred,
+ MemOPh_ADDi_V4, MemOPh_SUBi_V4>;
+ // Byte
+ defm : MemOpi_u5ALUOp <ldOpByte, truncstorei8, u6ExtPred,
+ MemOPb_ADDi_V4, MemOPb_SUBi_V4>;
+}
+
+let Predicates = [HasV4T, UseMEMOP] in {
+ defm : MemOpi_u5ExtType<zextloadi8, zextloadi16>; // zero extend
+ defm : MemOpi_u5ExtType<sextloadi8, sextloadi16>; // sign extend
+ defm : MemOpi_u5ExtType<extloadi8, extloadi16>; // any extend
+
+ // Word
+ defm : MemOpi_u5ALUOp <load, store, u6_2ExtPred, MemOPw_ADDi_V4,
+ MemOPw_SUBi_V4>;
+}
//===----------------------------------------------------------------------===//
-// MEMOP: Byte
-//
-// Implemented:
-// MEMb_ADDi_indexed_V4 : memb(Rs+#u6:0)+=#U5
-// MEMb_SUBi_indexed_V4 : memb(Rs+#u6:0)-=#U5
-// MEMb_ADDr_indexed_V4 : memb(Rs+#u6:0)+=Rt
-// MEMb_SUBr_indexed_V4 : memb(Rs+#u6:0)-=Rt
-// MEMb_CLRr_indexed_V4 : memb(Rs+#u6:0)&=Rt
-// MEMb_SETr_indexed_V4 : memb(Rs+#u6:0)|=Rt
-// MEMb_ADDi_V4 : memb(Rs+#u6:0)+=#U5
-// MEMb_SUBi_V4 : memb(Rs+#u6:0)-=#U5
-// MEMb_ADDr_V4 : memb(Rs+#u6:0)+=Rt
-// MEMb_SUBr_V4 : memb(Rs+#u6:0)-=Rt
-// MEMb_CLRr_V4 : memb(Rs+#u6:0)&=Rt
-// MEMb_SETr_V4 : memb(Rs+#u6:0)|=Rt
-//
-// Not implemented:
-// MEMb_CLRi_indexed_V4 : memb(Rs+#u6:0)=clrbit(#U5)
-// MEMb_SETi_indexed_V4 : memb(Rs+#u6:0)=setbit(#U5)
-// MEMb_CLRi_V4 : memb(Rs+#u6:0)=clrbit(#U5)
-// MEMb_SETi_V4 : memb(Rs+#u6:0)=setbit(#U5)
+// multiclass to define 'Def Pats' for ALU operations on the memory.
+// Here value used for the ALU operation is a negative value.
+// mem[bh](Rs+#0) += #m5
+// mem[bh](Rs+#u6) += #m5
+//===----------------------------------------------------------------------===//
+
+multiclass MemOpi_m5Pats <PatFrag ldOp, PatFrag stOp, PatLeaf extPred,
+ PatLeaf immPred, ComplexPattern addrPred,
+ SDNodeXForm xformFunc, InstHexagon MI> {
+ let AddedComplexity = 190 in
+ def : Pat <(stOp (add (ldOp IntRegs:$addr), immPred:$subend),
+ IntRegs:$addr),
+ (MI IntRegs:$addr, #0, (xformFunc immPred:$subend) )>;
+
+ let AddedComplexity = 195 in
+ def : Pat<(stOp (add (ldOp (add IntRegs:$base, extPred:$offset)),
+ immPred:$subend),
+ (add IntRegs:$base, extPred:$offset)),
+ (MI IntRegs:$base, extPred:$offset, (xformFunc immPred:$subend))>;
+}
+
+multiclass MemOpi_m5ExtType<PatFrag ldOpByte, PatFrag ldOpHalf > {
+ // Half Word
+ defm : MemOpi_m5Pats <ldOpHalf, truncstorei16, u6_1ExtPred, m5HImmPred,
+ ADDRriU6_1, MEMOPIMM_HALF, MemOPh_SUBi_V4>;
+ // Byte
+ defm : MemOpi_m5Pats <ldOpByte, truncstorei8, u6ExtPred, m5BImmPred,
+ ADDRriU6_0, MEMOPIMM_BYTE, MemOPb_SUBi_V4>;
+}
+
+let Predicates = [HasV4T, UseMEMOP] in {
+ defm : MemOpi_m5ExtType<zextloadi8, zextloadi16>; // zero extend
+ defm : MemOpi_m5ExtType<sextloadi8, sextloadi16>; // sign extend
+ defm : MemOpi_m5ExtType<extloadi8, extloadi16>; // any extend
+
+ // Word
+ defm : MemOpi_m5Pats <load, store, u6_2ExtPred, m5ImmPred,
+ ADDRriU6_2, MEMOPIMM, MemOPw_SUBi_V4>;
+}
+
//===----------------------------------------------------------------------===//
+// Multiclass to define 'def Pats' for bit operations on the memory.
+// mem[bhw](Rs+#0) = [clrbit|setbit](#U5)
+// mem[bhw](Rs+#u6) = [clrbit|setbit](#U5)
+//===----------------------------------------------------------------------===//
+
+multiclass MemOpi_bitPats <PatFrag ldOp, PatFrag stOp, PatLeaf immPred,
+ PatLeaf extPred, ComplexPattern addrPred,
+ SDNodeXForm xformFunc, InstHexagon MI, SDNode OpNode> {
+
+ // mem[bhw](Rs+#u6:[012]) = [clrbit|setbit](#U5)
+ let AddedComplexity = 250 in
+ def : Pat<(stOp (OpNode (ldOp (add IntRegs:$base, extPred:$offset)),
+ immPred:$bitend),
+ (add IntRegs:$base, extPred:$offset)),
+ (MI IntRegs:$base, extPred:$offset, (xformFunc immPred:$bitend))>;
+
+ // mem[bhw](Rs+#0) = [clrbit|setbit](#U5)
+ let AddedComplexity = 225 in
+ def : Pat <(stOp (OpNode (ldOp addrPred:$addr), immPred:$bitend),
+ addrPred:$addr),
+ (MI IntRegs:$addr, #0, (xformFunc immPred:$bitend))>;
+}
+
+multiclass MemOpi_bitExtType<PatFrag ldOpByte, PatFrag ldOpHalf > {
+ // Byte - clrbit
+ defm : MemOpi_bitPats<ldOpByte, truncstorei8, Clr3ImmPred, u6ExtPred,
+ ADDRriU6_0, CLRMEMIMM_BYTE, MemOPb_CLRBITi_V4, and>;
+ // Byte - setbit
+ defm : MemOpi_bitPats<ldOpByte, truncstorei8, Set3ImmPred, u6ExtPred,
+ ADDRriU6_0, SETMEMIMM_BYTE, MemOPb_SETBITi_V4, or>;
+ // Half Word - clrbit
+ defm : MemOpi_bitPats<ldOpHalf, truncstorei16, Clr4ImmPred, u6_1ExtPred,
+ ADDRriU6_1, CLRMEMIMM_SHORT, MemOPh_CLRBITi_V4, and>;
+ // Half Word - setbit
+ defm : MemOpi_bitPats<ldOpHalf, truncstorei16, Set4ImmPred, u6_1ExtPred,
+ ADDRriU6_1, SETMEMIMM_SHORT, MemOPh_SETBITi_V4, or>;
+}
-// memb(Rs+#u6:0) += #U5
-let AddedComplexity = 30 in
-def MEMb_ADDi_indexed_MEM_V4 : MEMInst_V4<(outs),
- (ins IntRegs:$base, u6_0Imm:$offset, u5Imm:$addend),
- "memb($base+#$offset) += $addend",
- []>,
- Requires<[HasV4T, UseMEMOP]>;
-
-// memb(Rs+#u6:0) -= #U5
-let AddedComplexity = 30 in
-def MEMb_SUBi_indexed_MEM_V4 : MEMInst_V4<(outs),
- (ins IntRegs:$base, u6_0Imm:$offset, u5Imm:$subend),
- "memb($base+#$offset) -= $subend",
- []>,
- Requires<[HasV4T, UseMEMOP]>;
-
-// memb(Rs+#u6:0) += Rt
-let AddedComplexity = 30 in
-def MEMb_ADDr_indexed_MEM_V4 : MEMInst_V4<(outs),
- (ins IntRegs:$base, u6_0Imm:$offset, IntRegs:$addend),
- "memb($base+#$offset) += $addend",
- [(truncstorei8 (add (sextloadi8 (add (i32 IntRegs:$base),
- u6_0ImmPred:$offset)),
- (i32 IntRegs:$addend)),
- (add (i32 IntRegs:$base), u6_0ImmPred:$offset))]>,
- Requires<[HasV4T, UseMEMOP]>;
-
-// memb(Rs+#u6:0) -= Rt
-let AddedComplexity = 30 in
-def MEMb_SUBr_indexed_MEM_V4 : MEMInst_V4<(outs),
- (ins IntRegs:$base, u6_0Imm:$offset, IntRegs:$subend),
- "memb($base+#$offset) -= $subend",
- [(truncstorei8 (sub (sextloadi8 (add (i32 IntRegs:$base),
- u6_0ImmPred:$offset)),
- (i32 IntRegs:$subend)),
- (add (i32 IntRegs:$base), u6_0ImmPred:$offset))]>,
- Requires<[HasV4T, UseMEMOP]>;
-
-// memb(Rs+#u6:0) &= Rt
-let AddedComplexity = 30 in
-def MEMb_ANDr_indexed_MEM_V4 : MEMInst_V4<(outs),
- (ins IntRegs:$base, u6_0Imm:$offset, IntRegs:$andend),
- "memb($base+#$offset) += $andend",
- [(truncstorei8 (and (sextloadi8 (add (i32 IntRegs:$base),
- u6_0ImmPred:$offset)),
- (i32 IntRegs:$andend)),
- (add (i32 IntRegs:$base), u6_0ImmPred:$offset))]>,
- Requires<[HasV4T, UseMEMOP]>;
-
-// memb(Rs+#u6:0) |= Rt
-let AddedComplexity = 30 in
-def MEMb_ORr_indexed_MEM_V4 : MEMInst_V4<(outs),
- (ins IntRegs:$base, u6_0Imm:$offset, IntRegs:$orend),
- "memb($base+#$offset) |= $orend",
- [(truncstorei8 (or (sextloadi8 (add (i32 IntRegs:$base),
- u6_0ImmPred:$offset)),
- (i32 IntRegs:$orend)),
- (add (i32 IntRegs:$base), u6_0ImmPred:$offset))]>,
- Requires<[HasV4T, UseMEMOP]>;
-
-// memb(Rs+#u6:0) += #U5
-let AddedComplexity = 30 in
-def MEMb_ADDi_MEM_V4 : MEMInst_V4<(outs),
- (ins MEMri:$addr, u5Imm:$addend),
- "memb($addr) += $addend",
- []>,
- Requires<[HasV4T, UseMEMOP]>;
-
-// memb(Rs+#u6:0) -= #U5
-let AddedComplexity = 30 in
-def MEMb_SUBi_MEM_V4 : MEMInst_V4<(outs),
- (ins MEMri:$addr, u5Imm:$subend),
- "memb($addr) -= $subend",
- []>,
- Requires<[HasV4T, UseMEMOP]>;
-
-// memb(Rs+#u6:0) += Rt
-let AddedComplexity = 30 in
-def MEMb_ADDr_MEM_V4 : MEMInst_V4<(outs),
- (ins MEMri:$addr, IntRegs:$addend),
- "memb($addr) += $addend",
- [(truncstorei8 (add (sextloadi8 ADDRriU6_0:$addr),
- (i32 IntRegs:$addend)), ADDRriU6_0:$addr)]>,
- Requires<[HasV4T, UseMEMOP]>;
-
-// memb(Rs+#u6:0) -= Rt
-let AddedComplexity = 30 in
-def MEMb_SUBr_MEM_V4 : MEMInst_V4<(outs),
- (ins MEMri:$addr, IntRegs:$subend),
- "memb($addr) -= $subend",
- [(truncstorei8 (sub (sextloadi8 ADDRriU6_0:$addr),
- (i32 IntRegs:$subend)), ADDRriU6_0:$addr)]>,
- Requires<[HasV4T, UseMEMOP]>;
-
-// memb(Rs+#u6:0) &= Rt
-let AddedComplexity = 30 in
-def MEMb_ANDr_MEM_V4 : MEMInst_V4<(outs),
- (ins MEMri:$addr, IntRegs:$andend),
- "memb($addr) &= $andend",
- [(truncstorei8 (and (sextloadi8 ADDRriU6_0:$addr),
- (i32 IntRegs:$andend)), ADDRriU6_0:$addr)]>,
- Requires<[HasV4T, UseMEMOP]>;
-
-// memb(Rs+#u6:0) |= Rt
-let AddedComplexity = 30 in
-def MEMb_ORr_MEM_V4 : MEMInst_V4<(outs),
- (ins MEMri:$addr, IntRegs:$orend),
- "memb($addr) |= $orend",
- [(truncstorei8 (or (sextloadi8 ADDRriU6_0:$addr),
- (i32 IntRegs:$orend)), ADDRriU6_0:$addr)]>,
- Requires<[HasV4T, UseMEMOP]>;
+let Predicates = [HasV4T, UseMEMOP] in {
+ // mem[bh](Rs+#0) = [clrbit|setbit](#U5)
+ // mem[bh](Rs+#u6:[01]) = [clrbit|setbit](#U5)
+ defm : MemOpi_bitExtType<zextloadi8, zextloadi16>; // zero extend
+ defm : MemOpi_bitExtType<sextloadi8, sextloadi16>; // sign extend
+ defm : MemOpi_bitExtType<extloadi8, extloadi16>; // any extend
+
+ // memw(Rs+#0) = [clrbit|setbit](#U5)
+ // memw(Rs+#u6:2) = [clrbit|setbit](#U5)
+ defm : MemOpi_bitPats<load, store, Clr5ImmPred, u6_2ExtPred, ADDRriU6_2,
+ CLRMEMIMM, MemOPw_CLRBITi_V4, and>;
+ defm : MemOpi_bitPats<load, store, Set5ImmPred, u6_2ExtPred, ADDRriU6_2,
+ SETMEMIMM, MemOPw_SETBITi_V4, or>;
+}
+
+//===----------------------------------------------------------------------===//
+// Multiclass to define 'def Pats' for ALU operations on the memory
+// where addend is a register.
+// mem[bhw](Rs+#0) [+-&|]= Rt
+// mem[bhw](Rs+#U6:[012]) [+-&|]= Rt
+//===----------------------------------------------------------------------===//
+multiclass MemOpr_Pats <PatFrag ldOp, PatFrag stOp, ComplexPattern addrPred,
+ PatLeaf extPred, InstHexagon MI, SDNode OpNode> {
+ let AddedComplexity = 141 in
+ // mem[bhw](Rs+#0) [+-&|]= Rt
+ def : Pat <(stOp (OpNode (ldOp addrPred:$addr), (i32 IntRegs:$addend)),
+ addrPred:$addr),
+ (MI IntRegs:$addr, #0, (i32 IntRegs:$addend) )>;
+
+ // mem[bhw](Rs+#U6:[012]) [+-&|]= Rt
+ let AddedComplexity = 150 in
+ def : Pat <(stOp (OpNode (ldOp (add IntRegs:$base, extPred:$offset)),
+ (i32 IntRegs:$orend)),
+ (add IntRegs:$base, extPred:$offset)),
+ (MI IntRegs:$base, extPred:$offset, (i32 IntRegs:$orend) )>;
+}
+
+multiclass MemOPr_ALUOp<PatFrag ldOp, PatFrag stOp,
+ ComplexPattern addrPred, PatLeaf extPred,
+ InstHexagon addMI, InstHexagon subMI,
+ InstHexagon andMI, InstHexagon orMI > {
+
+ defm : MemOpr_Pats <ldOp, stOp, addrPred, extPred, addMI, add>;
+ defm : MemOpr_Pats <ldOp, stOp, addrPred, extPred, subMI, sub>;
+ defm : MemOpr_Pats <ldOp, stOp, addrPred, extPred, andMI, and>;
+ defm : MemOpr_Pats <ldOp, stOp, addrPred, extPred, orMI, or>;
+}
+
+multiclass MemOPr_ExtType<PatFrag ldOpByte, PatFrag ldOpHalf > {
+ // Half Word
+ defm : MemOPr_ALUOp <ldOpHalf, truncstorei16, ADDRriU6_1, u6_1ExtPred,
+ MemOPh_ADDr_V4, MemOPh_SUBr_V4,
+ MemOPh_ANDr_V4, MemOPh_ORr_V4>;
+ // Byte
+ defm : MemOPr_ALUOp <ldOpByte, truncstorei8, ADDRriU6_0, u6ExtPred,
+ MemOPb_ADDr_V4, MemOPb_SUBr_V4,
+ MemOPb_ANDr_V4, MemOPb_ORr_V4>;
+}
+
+// Define 'def Pats' for MemOps with register addend.
+let Predicates = [HasV4T, UseMEMOP] in {
+ // Byte, Half Word
+ defm : MemOPr_ExtType<zextloadi8, zextloadi16>; // zero extend
+ defm : MemOPr_ExtType<sextloadi8, sextloadi16>; // sign extend
+ defm : MemOPr_ExtType<extloadi8, extloadi16>; // any extend
+ // Word
+ defm : MemOPr_ALUOp <load, store, ADDRriU6_2, u6_2ExtPred, MemOPw_ADDr_V4,
+ MemOPw_SUBr_V4, MemOPw_ANDr_V4, MemOPw_ORr_V4 >;
+}
//===----------------------------------------------------------------------===//
// XTYPE/PRED +
diff --git a/lib/Target/Hexagon/HexagonRegisterInfo.cpp b/lib/Target/Hexagon/HexagonRegisterInfo.cpp
index f947dfcdf9..d8b4e2fcb3 100644
--- a/lib/Target/Hexagon/HexagonRegisterInfo.cpp
+++ b/lib/Target/Hexagon/HexagonRegisterInfo.cpp
@@ -14,25 +14,26 @@
#include "HexagonRegisterInfo.h"
#include "Hexagon.h"
-#include "HexagonMachineFunctionInfo.h"
#include "HexagonSubtarget.h"
#include "HexagonTargetMachine.h"
+#include "HexagonMachineFunctionInfo.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
-#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/PseudoSourceValue.h"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Type.h"
#include "llvm/MC/MachineLocation.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/ErrorHandling.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ErrorHandling.h"
using namespace llvm;
@@ -215,28 +216,41 @@ void HexagonRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
MI.getOperand(FIOperandNum).ChangeToRegister(resReg, false, false,true);
MI.getOperand(FIOperandNum+1).ChangeToImmediate(0);
} else if (TII.isMemOp(&MI)) {
- unsigned resReg = HEXAGON_RESERVED_REG_1;
- if (!MFI.hasVarSizedObjects() &&
- TII.isValidOffset(MI.getOpcode(), (FrameSize+Offset))) {
- MI.getOperand(FIOperandNum).ChangeToRegister(getStackRegister(),
- false, false, true);
- MI.getOperand(FIOperandNum+1).ChangeToImmediate(FrameSize+Offset);
- } else if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) {
- BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
- TII.get(Hexagon::CONST32_Int_Real), resReg).addImm(Offset);
- BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
- TII.get(Hexagon::ADD_rr),
- resReg).addReg(FrameReg).addReg(resReg);
- MI.getOperand(FIOperandNum).ChangeToRegister(resReg, false, false,
- true);
- MI.getOperand(FIOperandNum+1).ChangeToImmediate(0);
+ // use the constant extender if the instruction provides it
+ // and we are V4TOps.
+ if (Subtarget.hasV4TOps()) {
+ if (TII.isConstExtended(&MI)) {
+ MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false);
+ MI.getOperand(FIOperandNum+1).ChangeToImmediate(Offset);
+ TII.immediateExtend(&MI);
+ } else {
+ llvm_unreachable("Need to implement for memops");
+ }
} else {
- BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
- TII.get(Hexagon::ADD_ri),
- resReg).addReg(FrameReg).addImm(Offset);
- MI.getOperand(FIOperandNum).ChangeToRegister(resReg, false, false,
- true);
- MI.getOperand(FIOperandNum+1).ChangeToImmediate(0);
+ // Only V3 and older instructions here.
+ unsigned ResReg = HEXAGON_RESERVED_REG_1;
+ if (!MFI.hasVarSizedObjects() &&
+ TII.isValidOffset(MI.getOpcode(), (FrameSize+Offset))) {
+ MI.getOperand(FIOperandNum).ChangeToRegister(getStackRegister(),
+ false, false, false);
+ MI.getOperand(FIOperandNum+1).ChangeToImmediate(FrameSize+Offset);
+ } else if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) {
+ BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
+ TII.get(Hexagon::CONST32_Int_Real), ResReg).addImm(Offset);
+ BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
+ TII.get(Hexagon::ADD_rr), ResReg).addReg(FrameReg).
+ addReg(ResReg);
+ MI.getOperand(FIOperandNum).ChangeToRegister(ResReg, false, false,
+ true);
+ MI.getOperand(FIOperandNum+1).ChangeToImmediate(0);
+ } else {
+ BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
+ TII.get(Hexagon::ADD_ri), ResReg).addReg(FrameReg).
+ addImm(Offset);
+ MI.getOperand(FIOperandNum).ChangeToRegister(ResReg, false, false,
+ true);
+ MI.getOperand(FIOperandNum+1).ChangeToImmediate(0);
+ }
}
} else {
unsigned dstReg = MI.getOperand(0).getReg();
diff --git a/lib/Target/Hexagon/HexagonSubtarget.cpp b/lib/Target/Hexagon/HexagonSubtarget.cpp
index 4bacb8fa67..07d5ce1d8a 100644
--- a/lib/Target/Hexagon/HexagonSubtarget.cpp
+++ b/lib/Target/Hexagon/HexagonSubtarget.cpp
@@ -29,8 +29,16 @@ EnableV3("enable-hexagon-v3", cl::Hidden,
static cl::opt<bool>
EnableMemOps(
"enable-hexagon-memops",
- cl::Hidden, cl::ZeroOrMore, cl::ValueDisallowed,
- cl::desc("Generate V4 memop instructions."));
+ cl::Hidden, cl::ZeroOrMore, cl::ValueDisallowed, cl::init(true),
+ cl::desc(
+ "Generate V4 MEMOP in code generation for Hexagon target"));
+
+static cl::opt<bool>
+DisableMemOps(
+ "disable-hexagon-memops",
+ cl::Hidden, cl::ZeroOrMore, cl::ValueDisallowed, cl::init(false),
+ cl::desc(
+ "Do not generate V4 MEMOP in code generation for Hexagon target"));
static cl::opt<bool>
EnableIEEERndNear(
@@ -64,7 +72,10 @@ HexagonSubtarget::HexagonSubtarget(StringRef TT, StringRef CPU, StringRef FS):
// Initialize scheduling itinerary for the specified CPU.
InstrItins = getInstrItineraryForCPU(CPUString);
- if (EnableMemOps)
+ // UseMemOps on by default unless disabled explicitly
+ if (DisableMemOps)
+ UseMemOps = false;
+ else if (EnableMemOps)
UseMemOps = true;
else
UseMemOps = false;
diff --git a/test/CodeGen/Hexagon/memops.ll b/test/CodeGen/Hexagon/memops.ll
new file mode 100644
index 0000000000..5498848d85
--- /dev/null
+++ b/test/CodeGen/Hexagon/memops.ll
@@ -0,0 +1,1369 @@
+; RUN: llc -march=hexagon -mcpu=hexagonv5 < %s | FileCheck %s
+; Generate MemOps for V4 and above.
+
+define void @memop_unsigned_char_add5(i8* nocapture %p) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}+={{ *}}#5
+ %0 = load i8* %p, align 1, !tbaa !0
+ %conv = zext i8 %0 to i32
+ %add = add nsw i32 %conv, 5
+ %conv1 = trunc i32 %add to i8
+ store i8 %conv1, i8* %p, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_unsigned_char_add(i8* nocapture %p, i8 zeroext %x) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}+={{ *}}r{{[0-9]+}}
+ %conv = zext i8 %x to i32
+ %0 = load i8* %p, align 1, !tbaa !0
+ %conv1 = zext i8 %0 to i32
+ %add = add nsw i32 %conv1, %conv
+ %conv2 = trunc i32 %add to i8
+ store i8 %conv2, i8* %p, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_unsigned_char_sub(i8* nocapture %p, i8 zeroext %x) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}-={{ *}}r{{[0-9]+}}
+ %conv = zext i8 %x to i32
+ %0 = load i8* %p, align 1, !tbaa !0
+ %conv1 = zext i8 %0 to i32
+ %sub = sub nsw i32 %conv1, %conv
+ %conv2 = trunc i32 %sub to i8
+ store i8 %conv2, i8* %p, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_unsigned_char_or(i8* nocapture %p, i8 zeroext %x) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}|={{ *}}r{{[0-9]+}}
+ %0 = load i8* %p, align 1, !tbaa !0
+ %or3 = or i8 %0, %x
+ store i8 %or3, i8* %p, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_unsigned_char_and(i8* nocapture %p, i8 zeroext %x) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}&={{ *}}r{{[0-9]+}}
+ %0 = load i8* %p, align 1, !tbaa !0
+ %and3 = and i8 %0, %x
+ store i8 %and3, i8* %p, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_unsigned_char_clrbit(i8* nocapture %p) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}={{ *}}clrbit({{ *}}#5{{ *}})
+ %0 = load i8* %p, align 1, !tbaa !0
+ %conv = zext i8 %0 to i32
+ %and = and i32 %conv, 223
+ %conv1 = trunc i32 %and to i8
+ store i8 %conv1, i8* %p, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_unsigned_char_setbit(i8* nocapture %p) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}={{ *}}setbit({{ *}}#7{{ *}})
+ %0 = load i8* %p, align 1, !tbaa !0
+ %conv = zext i8 %0 to i32
+ %or = or i32 %conv, 128
+ %conv1 = trunc i32 %or to i8
+ store i8 %conv1, i8* %p, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_unsigned_char_add5_index(i8* nocapture %p, i32 %i) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}+={{ *}}#5
+ %add.ptr = getelementptr inbounds i8* %p, i32 %i
+ %0 = load i8* %add.ptr, align 1, !tbaa !0
+ %conv = zext i8 %0 to i32
+ %add = add nsw i32 %conv, 5
+ %conv1 = trunc i32 %add to i8
+ store i8 %conv1, i8* %add.ptr, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_unsigned_char_add_index(i8* nocapture %p, i32 %i, i8 zeroext %x) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}+={{ *}}r{{[0-9]+}}
+ %conv = zext i8 %x to i32
+ %add.ptr = getelementptr inbounds i8* %p, i32 %i
+ %0 = load i8* %add.ptr, align 1, !tbaa !0
+ %conv1 = zext i8 %0 to i32
+ %add = add nsw i32 %conv1, %conv
+ %conv2 = trunc i32 %add to i8
+ store i8 %conv2, i8* %add.ptr, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_unsigned_char_sub_index(i8* nocapture %p, i32 %i, i8 zeroext %x) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}-={{ *}}r{{[0-9]+}}
+ %conv = zext i8 %x to i32
+ %add.ptr = getelementptr inbounds i8* %p, i32 %i
+ %0 = load i8* %add.ptr, align 1, !tbaa !0
+ %conv1 = zext i8 %0 to i32
+ %sub = sub nsw i32 %conv1, %conv
+ %conv2 = trunc i32 %sub to i8
+ store i8 %conv2, i8* %add.ptr, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_unsigned_char_or_index(i8* nocapture %p, i32 %i, i8 zeroext %x) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}|={{ *}}r{{[0-9]+}}
+ %add.ptr = getelementptr inbounds i8* %p, i32 %i
+ %0 = load i8* %add.ptr, align 1, !tbaa !0
+ %or3 = or i8 %0, %x
+ store i8 %or3, i8* %add.ptr, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_unsigned_char_and_index(i8* nocapture %p, i32 %i, i8 zeroext %x) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}&={{ *}}r{{[0-9]+}}
+ %add.ptr = getelementptr inbounds i8* %p, i32 %i
+ %0 = load i8* %add.ptr, align 1, !tbaa !0
+ %and3 = and i8 %0, %x
+ store i8 %and3, i8* %add.ptr, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_unsigned_char_clrbit_index(i8* nocapture %p, i32 %i) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}={{ *}}clrbit({{ *}}#5{{ *}})
+ %add.ptr = getelementptr inbounds i8* %p, i32 %i
+ %0 = load i8* %add.ptr, align 1, !tbaa !0
+ %conv = zext i8 %0 to i32
+ %and = and i32 %conv, 223
+ %conv1 = trunc i32 %and to i8
+ store i8 %conv1, i8* %add.ptr, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_unsigned_char_setbit_index(i8* nocapture %p, i32 %i) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}={{ *}}setbit({{ *}}#7{{ *}})
+ %add.ptr = getelementptr inbounds i8* %p, i32 %i
+ %0 = load i8* %add.ptr, align 1, !tbaa !0
+ %conv = zext i8 %0 to i32
+ %or = or i32 %conv, 128
+ %conv1 = trunc i32 %or to i8
+ store i8 %conv1, i8* %add.ptr, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_unsigned_char_add5_index5(i8* nocapture %p) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#5){{ *}}+={{ *}}#5
+ %add.ptr = getelementptr inbounds i8* %p, i32 5
+ %0 = load i8* %add.ptr, align 1, !tbaa !0
+ %conv = zext i8 %0 to i32
+ %add = add nsw i32 %conv, 5
+ %conv1 = trunc i32 %add to i8
+ store i8 %conv1, i8* %add.ptr, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_unsigned_char_add_index5(i8* nocapture %p, i8 zeroext %x) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#5){{ *}}+={{ *}}r{{[0-9]+}}
+ %conv = zext i8 %x to i32
+ %add.ptr = getelementptr inbounds i8* %p, i32 5
+ %0 = load i8* %add.ptr, align 1, !tbaa !0
+ %conv1 = zext i8 %0 to i32
+ %add = add nsw i32 %conv1, %conv
+ %conv2 = trunc i32 %add to i8
+ store i8 %conv2, i8* %add.ptr, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_unsigned_char_sub_index5(i8* nocapture %p, i8 zeroext %x) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#5){{ *}}-={{ *}}r{{[0-9]+}}
+ %conv = zext i8 %x to i32
+ %add.ptr = getelementptr inbounds i8* %p, i32 5
+ %0 = load i8* %add.ptr, align 1, !tbaa !0
+ %conv1 = zext i8 %0 to i32
+ %sub = sub nsw i32 %conv1, %conv
+ %conv2 = trunc i32 %sub to i8
+ store i8 %conv2, i8* %add.ptr, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_unsigned_char_or_index5(i8* nocapture %p, i8 zeroext %x) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#5){{ *}}|={{ *}}r{{[0-9]+}}
+ %add.ptr = getelementptr inbounds i8* %p, i32 5
+ %0 = load i8* %add.ptr, align 1, !tbaa !0
+ %or3 = or i8 %0, %x
+ store i8 %or3, i8* %add.ptr, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_unsigned_char_and_index5(i8* nocapture %p, i8 zeroext %x) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#5){{ *}}&={{ *}}r{{[0-9]+}}
+ %add.ptr = getelementptr inbounds i8* %p, i32 5
+ %0 = load i8* %add.ptr, align 1, !tbaa !0
+ %and3 = and i8 %0, %x
+ store i8 %and3, i8* %add.ptr, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_unsigned_char_clrbit_index5(i8* nocapture %p) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#5){{ *}}={{ *}}clrbit({{ *}}#5{{ *}})
+ %add.ptr = getelementptr inbounds i8* %p, i32 5
+ %0 = load i8* %add.ptr, align 1, !tbaa !0
+ %conv = zext i8 %0 to i32
+ %and = and i32 %conv, 223
+ %conv1 = trunc i32 %and to i8
+ store i8 %conv1, i8* %add.ptr, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_unsigned_char_setbit_index5(i8* nocapture %p) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#5){{ *}}={{ *}}setbit({{ *}}#7{{ *}})
+ %add.ptr = getelementptr inbounds i8* %p, i32 5
+ %0 = load i8* %add.ptr, align 1, !tbaa !0
+ %conv = zext i8 %0 to i32
+ %or = or i32 %conv, 128
+ %conv1 = trunc i32 %or to i8
+ store i8 %conv1, i8* %add.ptr, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_signed_char_add5(i8* nocapture %p) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}+={{ *}}#5
+ %0 = load i8* %p, align 1, !tbaa !0
+ %conv2 = zext i8 %0 to i32
+ %add = add nsw i32 %conv2, 5
+ %conv1 = trunc i32 %add to i8
+ store i8 %conv1, i8* %p, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_signed_char_add(i8* nocapture %p, i8 signext %x) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}+={{ *}}r{{[0-9]+}}
+ %conv4 = zext i8 %x to i32
+ %0 = load i8* %p, align 1, !tbaa !0
+ %conv13 = zext i8 %0 to i32
+ %add = add nsw i32 %conv13, %conv4
+ %conv2 = trunc i32 %add to i8
+ store i8 %conv2, i8* %p, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_signed_char_sub(i8* nocapture %p, i8 signext %x) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}-={{ *}}r{{[0-9]+}}
+ %conv4 = zext i8 %x to i32
+ %0 = load i8* %p, align 1, !tbaa !0
+ %conv13 = zext i8 %0 to i32
+ %sub = sub nsw i32 %conv13, %conv4
+ %conv2 = trunc i32 %sub to i8
+ store i8 %conv2, i8* %p, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_signed_char_or(i8* nocapture %p, i8 signext %x) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}|={{ *}}r{{[0-9]+}}
+ %0 = load i8* %p, align 1, !tbaa !0
+ %or3 = or i8 %0, %x
+ store i8 %or3, i8* %p, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_signed_char_and(i8* nocapture %p, i8 signext %x) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}&={{ *}}r{{[0-9]+}}
+ %0 = load i8* %p, align 1, !tbaa !0
+ %and3 = and i8 %0, %x
+ store i8 %and3, i8* %p, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_signed_char_clrbit(i8* nocapture %p) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}={{ *}}clrbit({{ *}}#5{{ *}})
+ %0 = load i8* %p, align 1, !tbaa !0
+ %conv2 = zext i8 %0 to i32
+ %and = and i32 %conv2, 223
+ %conv1 = trunc i32 %and to i8
+ store i8 %conv1, i8* %p, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_signed_char_setbit(i8* nocapture %p) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}={{ *}}setbit({{ *}}#7{{ *}})
+ %0 = load i8* %p, align 1, !tbaa !0
+ %conv2 = zext i8 %0 to i32
+ %or = or i32 %conv2, 128
+ %conv1 = trunc i32 %or to i8
+ store i8 %conv1, i8* %p, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_signed_char_add5_index(i8* nocapture %p, i32 %i) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}+={{ *}}#5
+ %add.ptr = getelementptr inbounds i8* %p, i32 %i
+ %0 = load i8* %add.ptr, align 1, !tbaa !0
+ %conv2 = zext i8 %0 to i32
+ %add = add nsw i32 %conv2, 5
+ %conv1 = trunc i32 %add to i8
+ store i8 %conv1, i8* %add.ptr, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_signed_char_add_index(i8* nocapture %p, i32 %i, i8 signext %x) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}+={{ *}}r{{[0-9]+}}
+ %conv4 = zext i8 %x to i32
+ %add.ptr = getelementptr inbounds i8* %p, i32 %i
+ %0 = load i8* %add.ptr, align 1, !tbaa !0
+ %conv13 = zext i8 %0 to i32
+ %add = add nsw i32 %conv13, %conv4
+ %conv2 = trunc i32 %add to i8
+ store i8 %conv2, i8* %add.ptr, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_signed_char_sub_index(i8* nocapture %p, i32 %i, i8 signext %x) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}-={{ *}}r{{[0-9]+}}
+ %conv4 = zext i8 %x to i32
+ %add.ptr = getelementptr inbounds i8* %p, i32 %i
+ %0 = load i8* %add.ptr, align 1, !tbaa !0
+ %conv13 = zext i8 %0 to i32
+ %sub = sub nsw i32 %conv13, %conv4
+ %conv2 = trunc i32 %sub to i8
+ store i8 %conv2, i8* %add.ptr, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_signed_char_or_index(i8* nocapture %p, i32 %i, i8 signext %x) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}|={{ *}}r{{[0-9]+}}
+ %add.ptr = getelementptr inbounds i8* %p, i32 %i
+ %0 = load i8* %add.ptr, align 1, !tbaa !0
+ %or3 = or i8 %0, %x
+ store i8 %or3, i8* %add.ptr, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_signed_char_and_index(i8* nocapture %p, i32 %i, i8 signext %x) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}&={{ *}}r{{[0-9]+}}
+ %add.ptr = getelementptr inbounds i8* %p, i32 %i
+ %0 = load i8* %add.ptr, align 1, !tbaa !0
+ %and3 = and i8 %0, %x
+ store i8 %and3, i8* %add.ptr, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_signed_char_clrbit_index(i8* nocapture %p, i32 %i) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}={{ *}}clrbit({{ *}}#5{{ *}})
+ %add.ptr = getelementptr inbounds i8* %p, i32 %i
+ %0 = load i8* %add.ptr, align 1, !tbaa !0
+ %conv2 = zext i8 %0 to i32
+ %and = and i32 %conv2, 223
+ %conv1 = trunc i32 %and to i8
+ store i8 %conv1, i8* %add.ptr, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_signed_char_setbit_index(i8* nocapture %p, i32 %i) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}={{ *}}setbit({{ *}}#7{{ *}})
+ %add.ptr = getelementptr inbounds i8* %p, i32 %i
+ %0 = load i8* %add.ptr, align 1, !tbaa !0
+ %conv2 = zext i8 %0 to i32
+ %or = or i32 %conv2, 128
+ %conv1 = trunc i32 %or to i8
+ store i8 %conv1, i8* %add.ptr, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_signed_char_add5_index5(i8* nocapture %p) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#5){{ *}}+={{ *}}#5
+ %add.ptr = getelementptr inbounds i8* %p, i32 5
+ %0 = load i8* %add.ptr, align 1, !tbaa !0
+ %conv2 = zext i8 %0 to i32
+ %add = add nsw i32 %conv2, 5
+ %conv1 = trunc i32 %add to i8
+ store i8 %conv1, i8* %add.ptr, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_signed_char_add_index5(i8* nocapture %p, i8 signext %x) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#5){{ *}}+={{ *}}r{{[0-9]+}}
+ %conv4 = zext i8 %x to i32
+ %add.ptr = getelementptr inbounds i8* %p, i32 5
+ %0 = load i8* %add.ptr, align 1, !tbaa !0
+ %conv13 = zext i8 %0 to i32
+ %add = add nsw i32 %conv13, %conv4
+ %conv2 = trunc i32 %add to i8
+ store i8 %conv2, i8* %add.ptr, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_signed_char_sub_index5(i8* nocapture %p, i8 signext %x) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#5){{ *}}-={{ *}}r{{[0-9]+}}
+ %conv4 = zext i8 %x to i32
+ %add.ptr = getelementptr inbounds i8* %p, i32 5
+ %0 = load i8* %add.ptr, align 1, !tbaa !0
+ %conv13 = zext i8 %0 to i32
+ %sub = sub nsw i32 %conv13, %conv4
+ %conv2 = trunc i32 %sub to i8
+ store i8 %conv2, i8* %add.ptr, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_signed_char_or_index5(i8* nocapture %p, i8 signext %x) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#5){{ *}}|={{ *}}r{{[0-9]+}}
+ %add.ptr = getelementptr inbounds i8* %p, i32 5
+ %0 = load i8* %add.ptr, align 1, !tbaa !0
+ %or3 = or i8 %0, %x
+ store i8 %or3, i8* %add.ptr, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_signed_char_and_index5(i8* nocapture %p, i8 signext %x) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#5){{ *}}&={{ *}}r{{[0-9]+}}
+ %add.ptr = getelementptr inbounds i8* %p, i32 5
+ %0 = load i8* %add.ptr, align 1, !tbaa !0
+ %and3 = and i8 %0, %x
+ store i8 %and3, i8* %add.ptr, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_signed_char_clrbit_index5(i8* nocapture %p) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#5){{ *}}={{ *}}clrbit({{ *}}#5{{ *}})
+ %add.ptr = getelementptr inbounds i8* %p, i32 5
+ %0 = load i8* %add.ptr, align 1, !tbaa !0
+ %conv2 = zext i8 %0 to i32
+ %and = and i32 %conv2, 223
+ %conv1 = trunc i32 %and to i8
+ store i8 %conv1, i8* %add.ptr, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_signed_char_setbit_index5(i8* nocapture %p) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#5){{ *}}={{ *}}setbit({{ *}}#7{{ *}})
+ %add.ptr = getelementptr inbounds i8* %p, i32 5
+ %0 = load i8* %add.ptr, align 1, !tbaa !0
+ %conv2 = zext i8 %0 to i32
+ %or = or i32 %conv2, 128
+ %conv1 = trunc i32 %or to i8
+ store i8 %conv1, i8* %add.ptr, align 1, !tbaa !0
+ ret void
+}
+
+define void @memop_unsigned_short_add5(i16* nocapture %p) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}+={{ *}}#5
+ %0 = load i16* %p, align 2, !tbaa !2
+ %conv = zext i16 %0 to i32
+ %add = add nsw i32 %conv, 5
+ %conv1 = trunc i32 %add to i16
+ store i16 %conv1, i16* %p, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_unsigned_short_add(i16* nocapture %p, i16 zeroext %x) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}+={{ *}}r{{[0-9]+}}
+ %conv = zext i16 %x to i32
+ %0 = load i16* %p, align 2, !tbaa !2
+ %conv1 = zext i16 %0 to i32
+ %add = add nsw i32 %conv1, %conv
+ %conv2 = trunc i32 %add to i16
+ store i16 %conv2, i16* %p, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_unsigned_short_sub(i16* nocapture %p, i16 zeroext %x) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}-={{ *}}r{{[0-9]+}}
+ %conv = zext i16 %x to i32
+ %0 = load i16* %p, align 2, !tbaa !2
+ %conv1 = zext i16 %0 to i32
+ %sub = sub nsw i32 %conv1, %conv
+ %conv2 = trunc i32 %sub to i16
+ store i16 %conv2, i16* %p, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_unsigned_short_or(i16* nocapture %p, i16 zeroext %x) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}|={{ *}}r{{[0-9]+}}
+ %0 = load i16* %p, align 2, !tbaa !2
+ %or3 = or i16 %0, %x
+ store i16 %or3, i16* %p, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_unsigned_short_and(i16* nocapture %p, i16 zeroext %x) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}&={{ *}}r{{[0-9]+}}
+ %0 = load i16* %p, align 2, !tbaa !2
+ %and3 = and i16 %0, %x
+ store i16 %and3, i16* %p, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_unsigned_short_clrbit(i16* nocapture %p) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}={{ *}}clrbit({{ *}}#5{{ *}})
+ %0 = load i16* %p, align 2, !tbaa !2
+ %conv = zext i16 %0 to i32
+ %and = and i32 %conv, 65503
+ %conv1 = trunc i32 %and to i16
+ store i16 %conv1, i16* %p, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_unsigned_short_setbit(i16* nocapture %p) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}={{ *}}setbit({{ *}}#7{{ *}})
+ %0 = load i16* %p, align 2, !tbaa !2
+ %conv = zext i16 %0 to i32
+ %or = or i32 %conv, 128
+ %conv1 = trunc i32 %or to i16
+ store i16 %conv1, i16* %p, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_unsigned_short_add5_index(i16* nocapture %p, i32 %i) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}+={{ *}}#5
+ %add.ptr = getelementptr inbounds i16* %p, i32 %i
+ %0 = load i16* %add.ptr, align 2, !tbaa !2
+ %conv = zext i16 %0 to i32
+ %add = add nsw i32 %conv, 5
+ %conv1 = trunc i32 %add to i16
+ store i16 %conv1, i16* %add.ptr, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_unsigned_short_add_index(i16* nocapture %p, i32 %i, i16 zeroext %x) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}+={{ *}}r{{[0-9]+}}
+ %conv = zext i16 %x to i32
+ %add.ptr = getelementptr inbounds i16* %p, i32 %i
+ %0 = load i16* %add.ptr, align 2, !tbaa !2
+ %conv1 = zext i16 %0 to i32
+ %add = add nsw i32 %conv1, %conv
+ %conv2 = trunc i32 %add to i16
+ store i16 %conv2, i16* %add.ptr, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_unsigned_short_sub_index(i16* nocapture %p, i32 %i, i16 zeroext %x) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}-={{ *}}r{{[0-9]+}}
+ %conv = zext i16 %x to i32
+ %add.ptr = getelementptr inbounds i16* %p, i32 %i
+ %0 = load i16* %add.ptr, align 2, !tbaa !2
+ %conv1 = zext i16 %0 to i32
+ %sub = sub nsw i32 %conv1, %conv
+ %conv2 = trunc i32 %sub to i16
+ store i16 %conv2, i16* %add.ptr, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_unsigned_short_or_index(i16* nocapture %p, i32 %i, i16 zeroext %x) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}|={{ *}}r{{[0-9]+}}
+ %add.ptr = getelementptr inbounds i16* %p, i32 %i
+ %0 = load i16* %add.ptr, align 2, !tbaa !2
+ %or3 = or i16 %0, %x
+ store i16 %or3, i16* %add.ptr, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_unsigned_short_and_index(i16* nocapture %p, i32 %i, i16 zeroext %x) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}&={{ *}}r{{[0-9]+}}
+ %add.ptr = getelementptr inbounds i16* %p, i32 %i
+ %0 = load i16* %add.ptr, align 2, !tbaa !2
+ %and3 = and i16 %0, %x
+ store i16 %and3, i16* %add.ptr, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_unsigned_short_clrbit_index(i16* nocapture %p, i32 %i) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}={{ *}}clrbit({{ *}}#5{{ *}})
+ %add.ptr = getelementptr inbounds i16* %p, i32 %i
+ %0 = load i16* %add.ptr, align 2, !tbaa !2
+ %conv = zext i16 %0 to i32
+ %and = and i32 %conv, 65503
+ %conv1 = trunc i32 %and to i16
+ store i16 %conv1, i16* %add.ptr, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_unsigned_short_setbit_index(i16* nocapture %p, i32 %i) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}={{ *}}setbit({{ *}}#7{{ *}})
+ %add.ptr = getelementptr inbounds i16* %p, i32 %i
+ %0 = load i16* %add.ptr, align 2, !tbaa !2
+ %conv = zext i16 %0 to i32
+ %or = or i32 %conv, 128
+ %conv1 = trunc i32 %or to i16
+ store i16 %conv1, i16* %add.ptr, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_unsigned_short_add5_index5(i16* nocapture %p) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#10){{ *}}+={{ *}}#5
+ %add.ptr = getelementptr inbounds i16* %p, i32 5
+ %0 = load i16* %add.ptr, align 2, !tbaa !2
+ %conv = zext i16 %0 to i32
+ %add = add nsw i32 %conv, 5
+ %conv1 = trunc i32 %add to i16
+ store i16 %conv1, i16* %add.ptr, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_unsigned_short_add_index5(i16* nocapture %p, i16 zeroext %x) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#10){{ *}}+={{ *}}r{{[0-9]+}}
+ %conv = zext i16 %x to i32
+ %add.ptr = getelementptr inbounds i16* %p, i32 5
+ %0 = load i16* %add.ptr, align 2, !tbaa !2
+ %conv1 = zext i16 %0 to i32
+ %add = add nsw i32 %conv1, %conv
+ %conv2 = trunc i32 %add to i16
+ store i16 %conv2, i16* %add.ptr, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_unsigned_short_sub_index5(i16* nocapture %p, i16 zeroext %x) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#10){{ *}}-={{ *}}r{{[0-9]+}}
+ %conv = zext i16 %x to i32
+ %add.ptr = getelementptr inbounds i16* %p, i32 5
+ %0 = load i16* %add.ptr, align 2, !tbaa !2
+ %conv1 = zext i16 %0 to i32
+ %sub = sub nsw i32 %conv1, %conv
+ %conv2 = trunc i32 %sub to i16
+ store i16 %conv2, i16* %add.ptr, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_unsigned_short_or_index5(i16* nocapture %p, i16 zeroext %x) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#10){{ *}}|={{ *}}r{{[0-9]+}}
+ %add.ptr = getelementptr inbounds i16* %p, i32 5
+ %0 = load i16* %add.ptr, align 2, !tbaa !2
+ %or3 = or i16 %0, %x
+ store i16 %or3, i16* %add.ptr, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_unsigned_short_and_index5(i16* nocapture %p, i16 zeroext %x) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#10){{ *}}&={{ *}}r{{[0-9]+}}
+ %add.ptr = getelementptr inbounds i16* %p, i32 5
+ %0 = load i16* %add.ptr, align 2, !tbaa !2
+ %and3 = and i16 %0, %x
+ store i16 %and3, i16* %add.ptr, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_unsigned_short_clrbit_index5(i16* nocapture %p) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#10){{ *}}={{ *}}clrbit({{ *}}#5{{ *}})
+ %add.ptr = getelementptr inbounds i16* %p, i32 5
+ %0 = load i16* %add.ptr, align 2, !tbaa !2
+ %conv = zext i16 %0 to i32
+ %and = and i32 %conv, 65503
+ %conv1 = trunc i32 %and to i16
+ store i16 %conv1, i16* %add.ptr, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_unsigned_short_setbit_index5(i16* nocapture %p) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#10){{ *}}={{ *}}setbit({{ *}}#7{{ *}})
+ %add.ptr = getelementptr inbounds i16* %p, i32 5
+ %0 = load i16* %add.ptr, align 2, !tbaa !2
+ %conv = zext i16 %0 to i32
+ %or = or i32 %conv, 128
+ %conv1 = trunc i32 %or to i16
+ store i16 %conv1, i16* %add.ptr, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_signed_short_add5(i16* nocapture %p) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}+={{ *}}#5
+ %0 = load i16* %p, align 2, !tbaa !2
+ %conv2 = zext i16 %0 to i32
+ %add = add nsw i32 %conv2, 5
+ %conv1 = trunc i32 %add to i16
+ store i16 %conv1, i16* %p, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_signed_short_add(i16* nocapture %p, i16 signext %x) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}+={{ *}}r{{[0-9]+}}
+ %conv4 = zext i16 %x to i32
+ %0 = load i16* %p, align 2, !tbaa !2
+ %conv13 = zext i16 %0 to i32
+ %add = add nsw i32 %conv13, %conv4
+ %conv2 = trunc i32 %add to i16
+ store i16 %conv2, i16* %p, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_signed_short_sub(i16* nocapture %p, i16 signext %x) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}-={{ *}}r{{[0-9]+}}
+ %conv4 = zext i16 %x to i32
+ %0 = load i16* %p, align 2, !tbaa !2
+ %conv13 = zext i16 %0 to i32
+ %sub = sub nsw i32 %conv13, %conv4
+ %conv2 = trunc i32 %sub to i16
+ store i16 %conv2, i16* %p, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_signed_short_or(i16* nocapture %p, i16 signext %x) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}|={{ *}}r{{[0-9]+}}
+ %0 = load i16* %p, align 2, !tbaa !2
+ %or3 = or i16 %0, %x
+ store i16 %or3, i16* %p, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_signed_short_and(i16* nocapture %p, i16 signext %x) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}&={{ *}}r{{[0-9]+}}
+ %0 = load i16* %p, align 2, !tbaa !2
+ %and3 = and i16 %0, %x
+ store i16 %and3, i16* %p, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_signed_short_clrbit(i16* nocapture %p) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}={{ *}}clrbit({{ *}}#5{{ *}})
+ %0 = load i16* %p, align 2, !tbaa !2
+ %conv2 = zext i16 %0 to i32
+ %and = and i32 %conv2, 65503
+ %conv1 = trunc i32 %and to i16
+ store i16 %conv1, i16* %p, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_signed_short_setbit(i16* nocapture %p) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}={{ *}}setbit({{ *}}#7{{ *}})
+ %0 = load i16* %p, align 2, !tbaa !2
+ %conv2 = zext i16 %0 to i32
+ %or = or i32 %conv2, 128
+ %conv1 = trunc i32 %or to i16
+ store i16 %conv1, i16* %p, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_signed_short_add5_index(i16* nocapture %p, i32 %i) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}+={{ *}}#5
+ %add.ptr = getelementptr inbounds i16* %p, i32 %i
+ %0 = load i16* %add.ptr, align 2, !tbaa !2
+ %conv2 = zext i16 %0 to i32
+ %add = add nsw i32 %conv2, 5
+ %conv1 = trunc i32 %add to i16
+ store i16 %conv1, i16* %add.ptr, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_signed_short_add_index(i16* nocapture %p, i32 %i, i16 signext %x) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}+={{ *}}r{{[0-9]+}}
+ %conv4 = zext i16 %x to i32
+ %add.ptr = getelementptr inbounds i16* %p, i32 %i
+ %0 = load i16* %add.ptr, align 2, !tbaa !2
+ %conv13 = zext i16 %0 to i32
+ %add = add nsw i32 %conv13, %conv4
+ %conv2 = trunc i32 %add to i16
+ store i16 %conv2, i16* %add.ptr, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_signed_short_sub_index(i16* nocapture %p, i32 %i, i16 signext %x) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}-={{ *}}r{{[0-9]+}}
+ %conv4 = zext i16 %x to i32
+ %add.ptr = getelementptr inbounds i16* %p, i32 %i
+ %0 = load i16* %add.ptr, align 2, !tbaa !2
+ %conv13 = zext i16 %0 to i32
+ %sub = sub nsw i32 %conv13, %conv4
+ %conv2 = trunc i32 %sub to i16
+ store i16 %conv2, i16* %add.ptr, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_signed_short_or_index(i16* nocapture %p, i32 %i, i16 signext %x) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}|={{ *}}r{{[0-9]+}}
+ %add.ptr = getelementptr inbounds i16* %p, i32 %i
+ %0 = load i16* %add.ptr, align 2, !tbaa !2
+ %or3 = or i16 %0, %x
+ store i16 %or3, i16* %add.ptr, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_signed_short_and_index(i16* nocapture %p, i32 %i, i16 signext %x) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}&={{ *}}r{{[0-9]+}}
+ %add.ptr = getelementptr inbounds i16* %p, i32 %i
+ %0 = load i16* %add.ptr, align 2, !tbaa !2
+ %and3 = and i16 %0, %x
+ store i16 %and3, i16* %add.ptr, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_signed_short_clrbit_index(i16* nocapture %p, i32 %i) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}={{ *}}clrbit({{ *}}#5{{ *}})
+ %add.ptr = getelementptr inbounds i16* %p, i32 %i
+ %0 = load i16* %add.ptr, align 2, !tbaa !2
+ %conv2 = zext i16 %0 to i32
+ %and = and i32 %conv2, 65503
+ %conv1 = trunc i32 %and to i16
+ store i16 %conv1, i16* %add.ptr, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_signed_short_setbit_index(i16* nocapture %p, i32 %i) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}={{ *}}setbit({{ *}}#7{{ *}})
+ %add.ptr = getelementptr inbounds i16* %p, i32 %i
+ %0 = load i16* %add.ptr, align 2, !tbaa !2
+ %conv2 = zext i16 %0 to i32
+ %or = or i32 %conv2, 128
+ %conv1 = trunc i32 %or to i16
+ store i16 %conv1, i16* %add.ptr, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_signed_short_add5_index5(i16* nocapture %p) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#10){{ *}}+={{ *}}#5
+ %add.ptr = getelementptr inbounds i16* %p, i32 5
+ %0 = load i16* %add.ptr, align 2, !tbaa !2
+ %conv2 = zext i16 %0 to i32
+ %add = add nsw i32 %conv2, 5
+ %conv1 = trunc i32 %add to i16
+ store i16 %conv1, i16* %add.ptr, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_signed_short_add_index5(i16* nocapture %p, i16 signext %x) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#10){{ *}}+={{ *}}r{{[0-9]+}}
+ %conv4 = zext i16 %x to i32
+ %add.ptr = getelementptr inbounds i16* %p, i32 5
+ %0 = load i16* %add.ptr, align 2, !tbaa !2
+ %conv13 = zext i16 %0 to i32
+ %add = add nsw i32 %conv13, %conv4
+ %conv2 = trunc i32 %add to i16
+ store i16 %conv2, i16* %add.ptr, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_signed_short_sub_index5(i16* nocapture %p, i16 signext %x) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#10){{ *}}-={{ *}}r{{[0-9]+}}
+ %conv4 = zext i16 %x to i32
+ %add.ptr = getelementptr inbounds i16* %p, i32 5
+ %0 = load i16* %add.ptr, align 2, !tbaa !2
+ %conv13 = zext i16 %0 to i32
+ %sub = sub nsw i32 %conv13, %conv4
+ %conv2 = trunc i32 %sub to i16
+ store i16 %conv2, i16* %add.ptr, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_signed_short_or_index5(i16* nocapture %p, i16 signext %x) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#10){{ *}}|={{ *}}r{{[0-9]+}}
+ %add.ptr = getelementptr inbounds i16* %p, i32 5
+ %0 = load i16* %add.ptr, align 2, !tbaa !2
+ %or3 = or i16 %0, %x
+ store i16 %or3, i16* %add.ptr, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_signed_short_and_index5(i16* nocapture %p, i16 signext %x) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#10){{ *}}&={{ *}}r{{[0-9]+}}
+ %add.ptr = getelementptr inbounds i16* %p, i32 5
+ %0 = load i16* %add.ptr, align 2, !tbaa !2
+ %and3 = and i16 %0, %x
+ store i16 %and3, i16* %add.ptr, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_signed_short_clrbit_index5(i16* nocapture %p) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#10){{ *}}={{ *}}clrbit({{ *}}#5{{ *}})
+ %add.ptr = getelementptr inbounds i16* %p, i32 5
+ %0 = load i16* %add.ptr, align 2, !tbaa !2
+ %conv2 = zext i16 %0 to i32
+ %and = and i32 %conv2, 65503
+ %conv1 = trunc i32 %and to i16
+ store i16 %conv1, i16* %add.ptr, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_signed_short_setbit_index5(i16* nocapture %p) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#10){{ *}}={{ *}}setbit({{ *}}#7{{ *}})
+ %add.ptr = getelementptr inbounds i16* %p, i32 5
+ %0 = load i16* %add.ptr, align 2, !tbaa !2
+ %conv2 = zext i16 %0 to i32
+ %or = or i32 %conv2, 128
+ %conv1 = trunc i32 %or to i16
+ store i16 %conv1, i16* %add.ptr, align 2, !tbaa !2
+ ret void
+}
+
+define void @memop_signed_int_add5(i32* nocapture %p) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}+={{ *}}#5
+ %0 = load i32* %p, align 4, !tbaa !3
+ %add = add i32 %0, 5
+ store i32 %add, i32* %p, align 4, !tbaa !3
+ ret void
+}
+
+define void @memop_signed_int_add(i32* nocapture %p, i32 %x) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}+={{ *}}r{{[0-9]+}}
+ %0 = load i32* %p, align 4, !tbaa !3
+ %add = add i32 %0, %x
+ store i32 %add, i32* %p, align 4, !tbaa !3
+ ret void
+}
+
+define void @memop_signed_int_sub(i32* nocapture %p, i32 %x) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}-={{ *}}r{{[0-9]+}}
+ %0 = load i32* %p, align 4, !tbaa !3
+ %sub = sub i32 %0, %x
+ store i32 %sub, i32* %p, align 4, !tbaa !3
+ ret void
+}
+
+define void @memop_signed_int_or(i32* nocapture %p, i32 %x) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}|={{ *}}r{{[0-9]+}}
+ %0 = load i32* %p, align 4, !tbaa !3
+ %or = or i32 %0, %x
+ store i32 %or, i32* %p, align 4, !tbaa !3
+ ret void
+}
+
+define void @memop_signed_int_and(i32* nocapture %p, i32 %x) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}&={{ *}}r{{[0-9]+}}
+ %0 = load i32* %p, align 4, !tbaa !3
+ %and = and i32 %0, %x
+ store i32 %and, i32* %p, align 4, !tbaa !3
+ ret void
+}
+
+define void @memop_signed_int_clrbit(i32* nocapture %p) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}={{ *}}clrbit({{ *}}#5{{ *}})
+ %0 = load i32* %p, align 4, !tbaa !3
+ %and = and i32 %0, -33
+ store i32 %and, i32* %p, align 4, !tbaa !3
+ ret void
+}
+
+define void @memop_signed_int_setbit(i32* nocapture %p) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}={{ *}}setbit({{ *}}#7{{ *}})
+ %0 = load i32* %p, align 4, !tbaa !3
+ %or = or i32 %0, 128
+ store i32 %or, i32* %p, align 4, !tbaa !3
+ ret void
+}
+
+define void @memop_signed_int_add5_index(i32* nocapture %p, i32 %i) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}+={{ *}}#5
+ %add.ptr = getelementptr inbounds i32* %p, i32 %i
+ %0 = load i32* %add.ptr, align 4, !tbaa !3
+ %add = add i32 %0, 5
+ store i32 %add, i32* %add.ptr, align 4, !tbaa !3
+ ret void
+}
+
+define void @memop_signed_int_add_index(i32* nocapture %p, i32 %i, i32 %x) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}+={{ *}}r{{[0-9]+}}
+ %add.ptr = getelementptr inbounds i32* %p, i32 %i
+ %0 = load i32* %add.ptr, align 4, !tbaa !3
+ %add = add i32 %0, %x
+ store i32 %add, i32* %add.ptr, align 4, !tbaa !3
+ ret void
+}
+
+define void @memop_signed_int_sub_index(i32* nocapture %p, i32 %i, i32 %x) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}-={{ *}}r{{[0-9]+}}
+ %add.ptr = getelementptr inbounds i32* %p, i32 %i
+ %0 = load i32* %add.ptr, align 4, !tbaa !3
+ %sub = sub i32 %0, %x
+ store i32 %sub, i32* %add.ptr, align 4, !tbaa !3
+ ret void
+}
+
+define void @memop_signed_int_or_index(i32* nocapture %p, i32 %i, i32 %x) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}|={{ *}}r{{[0-9]+}}
+ %add.ptr = getelementptr inbounds i32* %p, i32 %i
+ %0 = load i32* %add.ptr, align 4, !tbaa !3
+ %or = or i32 %0, %x
+ store i32 %or, i32* %add.ptr, align 4, !tbaa !3
+ ret void
+}
+
+define void @memop_signed_int_and_index(i32* nocapture %p, i32 %i, i32 %x) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}&={{ *}}r{{[0-9]+}}
+ %add.ptr = getelementptr inbounds i32* %p, i32 %i
+ %0 = load i32* %add.ptr, align 4, !tbaa !3
+ %and = and i32 %0, %x
+ store i32 %and, i32* %add.ptr, align 4, !tbaa !3
+ ret void
+}
+
+define void @memop_signed_int_clrbit_index(i32* nocapture %p, i32 %i) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}={{ *}}clrbit({{ *}}#5{{ *}})
+ %add.ptr = getelementptr inbounds i32* %p, i32 %i
+ %0 = load i32* %add.ptr, align 4, !tbaa !3
+ %and = and i32 %0, -33
+ store i32 %and, i32* %add.ptr, align 4, !tbaa !3
+ ret void
+}
+
+define void @memop_signed_int_setbit_index(i32* nocapture %p, i32 %i) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}={{ *}}setbit({{ *}}#7{{ *}})
+ %add.ptr = getelementptr inbounds i32* %p, i32 %i
+ %0 = load i32* %add.ptr, align 4, !tbaa !3
+ %or = or i32 %0, 128
+ store i32 %or, i32* %add.ptr, align 4, !tbaa !3
+ ret void
+}
+
+define void @memop_signed_int_add5_index5(i32* nocapture %p) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#20){{ *}}+={{ *}}#5
+ %add.ptr = getelementptr inbounds i32* %p, i32 5
+ %0 = load i32* %add.ptr, align 4, !tbaa !3
+ %add = add i32 %0, 5
+ store i32 %add, i32* %add.ptr, align 4, !tbaa !3
+ ret void
+}
+
+define void @memop_signed_int_add_index5(i32* nocapture %p, i32 %x) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#20){{ *}}+={{ *}}r{{[0-9]+}}
+ %add.ptr = getelementptr inbounds i32* %p, i32 5
+ %0 = load i32* %add.ptr, align 4, !tbaa !3
+ %add = add i32 %0, %x
+ store i32 %add, i32* %add.ptr, align 4, !tbaa !3
+ ret void
+}
+
+define void @memop_signed_int_sub_index5(i32* nocapture %p, i32 %x) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#20){{ *}}-={{ *}}r{{[0-9]+}}
+ %add.ptr = getelementptr inbounds i32* %p, i32 5
+ %0 = load i32* %add.ptr, align 4, !tbaa !3
+ %sub = sub i32 %0, %x
+ store i32 %sub, i32* %add.ptr, align 4, !tbaa !3
+ ret void
+}
+
+define void @memop_signed_int_or_index5(i32* nocapture %p, i32 %x) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#20){{ *}}|={{ *}}r{{[0-9]+}}
+ %add.ptr = getelementptr inbounds i32* %p, i32 5
+ %0 = load i32* %add.ptr, align 4, !tbaa !3
+ %or = or i32 %0, %x
+ store i32 %or, i32* %add.ptr, align 4, !tbaa !3
+ ret void
+}
+
+define void @memop_signed_int_and_index5(i32* nocapture %p, i32 %x) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#20){{ *}}&={{ *}}r{{[0-9]+}}
+ %add.ptr = getelementptr inbounds i32* %p, i32 5
+ %0 = load i32* %add.ptr, align 4, !tbaa !3
+ %and = and i32 %0, %x
+ store i32 %and, i32* %add.ptr, align 4, !tbaa !3
+ ret void
+}
+
+define void @memop_signed_int_clrbit_index5(i32* nocapture %p) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#20){{ *}}={{ *}}clrbit({{ *}}#5{{ *}})
+ %add.ptr = getelementptr inbounds i32* %p, i32 5
+ %0 = load i32* %add.ptr, align 4, !tbaa !3
+ %and = and i32 %0, -33
+ store i32 %and, i32* %add.ptr, align 4, !tbaa !3
+ ret void
+}
+
+define void @memop_signed_int_setbit_index5(i32* nocapture %p) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#20){{ *}}={{ *}}setbit({{ *}}#7{{ *}})
+ %add.ptr = getelementptr inbounds i32* %p, i32 5
+ %0 = load i32* %add.ptr, align 4, !tbaa !3
+ %or = or i32 %0, 128
+ store i32 %or, i32* %add.ptr, align 4, !tbaa !3
+ ret void
+}
+
+define void @memop_unsigned_int_add5(i32* nocapture %p) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}+={{ *}}#5
+ %0 = load i32* %p, align 4, !tbaa !3
+ %add = add nsw i32 %0, 5
+ store i32 %add, i32* %p, align 4, !tbaa !3
+ ret void
+}
+
+define void @memop_unsigned_int_add(i32* nocapture %p, i32 %x) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}+={{ *}}r{{[0-9]+}}
+ %0 = load i32* %p, align 4, !tbaa !3
+ %add = add nsw i32 %0, %x
+ store i32 %add, i32* %p, align 4, !tbaa !3
+ ret void
+}
+
+define void @memop_unsigned_int_sub(i32* nocapture %p, i32 %x) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}-={{ *}}r{{[0-9]+}}
+ %0 = load i32* %p, align 4, !tbaa !3
+ %sub = sub nsw i32 %0, %x
+ store i32 %sub, i32* %p, align 4, !tbaa !3
+ ret void
+}
+
+define void @memop_unsigned_int_or(i32* nocapture %p, i32 %x) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}|={{ *}}r{{[0-9]+}}
+ %0 = load i32* %p, align 4, !tbaa !3
+ %or = or i32 %0, %x
+ store i32 %or, i32* %p, align 4, !tbaa !3
+ ret void
+}
+
+define void @memop_unsigned_int_and(i32* nocapture %p, i32 %x) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}&={{ *}}r{{[0-9]+}}
+ %0 = load i32* %p, align 4, !tbaa !3
+ %and = and i32 %0, %x
+ store i32 %and, i32* %p, align 4, !tbaa !3
+ ret void
+}
+
+define void @memop_unsigned_int_clrbit(i32* nocapture %p) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}={{ *}}clrbit({{ *}}#5{{ *}})
+ %0 = load i32* %p, align 4, !tbaa !3
+ %and = and i32 %0, -33
+ store i32 %and, i32* %p, align 4, !tbaa !3
+ ret void
+}
+
+define void @memop_unsigned_int_setbit(i32* nocapture %p) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}={{ *}}setbit({{ *}}#7{{ *}})
+ %0 = load i32* %p, align 4, !tbaa !3
+ %or = or i32 %0, 128
+ store i32 %or, i32* %p, align 4, !tbaa !3
+ ret void
+}
+
+define void @memop_unsigned_int_add5_index(i32* nocapture %p, i32 %i) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}+={{ *}}#5
+ %add.ptr = getelementptr inbounds i32* %p, i32 %i
+ %0 = load i32* %add.ptr, align 4, !tbaa !3
+ %add = add nsw i32 %0, 5
+ store i32 %add, i32* %add.ptr, align 4, !tbaa !3
+ ret void
+}
+
+define void @memop_unsigned_int_add_index(i32* nocapture %p, i32 %i, i32 %x) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}+={{ *}}r{{[0-9]+}}
+ %add.ptr = getelementptr inbounds i32* %p, i32 %i
+ %0 = load i32* %add.ptr, align 4, !tbaa !3
+ %add = add nsw i32 %0, %x
+ store i32 %add, i32* %add.ptr, align 4, !tbaa !3
+ ret void
+}
+
+define void @memop_unsigned_int_sub_index(i32* nocapture %p, i32 %i, i32 %x) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}-={{ *}}r{{[0-9]+}}
+ %add.ptr = getelementptr inbounds i32* %p, i32 %i
+ %0 = load i32* %add.ptr, align 4, !tbaa !3
+ %sub = sub nsw i32 %0, %x
+ store i32 %sub, i32* %add.ptr, align 4, !tbaa !3
+ ret void
+}
+
+define void @memop_unsigned_int_or_index(i32* nocapture %p, i32 %i, i32 %x) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}|={{ *}}r{{[0-9]+}}
+ %add.ptr = getelementptr inbounds i32* %p, i32 %i
+ %0 = load i32* %add.ptr, align 4, !tbaa !3
+ %or = or i32 %0, %x
+ store i32 %or, i32* %add.ptr, align 4, !tbaa !3
+ ret void
+}
+
+define void @memop_unsigned_int_and_index(i32* nocapture %p, i32 %i, i32 %x) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}&={{ *}}r{{[0-9]+}}
+ %add.ptr = getelementptr inbounds i32* %p, i32 %i
+ %0 = load i32* %add.ptr, align 4, !tbaa !3
+ %and = and i32 %0, %x
+ store i32 %and, i32* %add.ptr, align 4, !tbaa !3
+ ret void
+}
+
+define void @memop_unsigned_int_clrbit_index(i32* nocapture %p, i32 %i) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}={{ *}}clrbit({{ *}}#5{{ *}})
+ %add.ptr = getelementptr inbounds i32* %p, i32 %i
+ %0 = load i32* %add.ptr, align 4, !tbaa !3
+ %and = and i32 %0, -33
+ store i32 %and, i32* %add.ptr, align 4, !tbaa !3
+ ret void
+}
+
+define void @memop_unsigned_int_setbit_index(i32* nocapture %p, i32 %i) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#0){{ *}}={{ *}}setbit({{ *}}#7{{ *}})
+ %add.ptr = getelementptr inbounds i32* %p, i32 %i
+ %0 = load i32* %add.ptr, align 4, !tbaa !3
+ %or = or i32 %0, 128
+ store i32 %or, i32* %add.ptr, align 4, !tbaa !3
+ ret void
+}
+
+define void @memop_unsigned_int_add5_index5(i32* nocapture %p) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#20){{ *}}+={{ *}}#5
+ %add.ptr = getelementptr inbounds i32* %p, i32 5
+ %0 = load i32* %add.ptr, align 4, !tbaa !3
+ %add = add nsw i32 %0, 5
+ store i32 %add, i32* %add.ptr, align 4, !tbaa !3
+ ret void
+}
+
+define void @memop_unsigned_int_add_index5(i32* nocapture %p, i32 %x) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#20){{ *}}+={{ *}}r{{[0-9]+}}
+ %add.ptr = getelementptr inbounds i32* %p, i32 5
+ %0 = load i32* %add.ptr, align 4, !tbaa !3
+ %add = add nsw i32 %0, %x
+ store i32 %add, i32* %add.ptr, align 4, !tbaa !3
+ ret void
+}
+
+define void @memop_unsigned_int_sub_index5(i32* nocapture %p, i32 %x) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#20){{ *}}-={{ *}}r{{[0-9]+}}
+ %add.ptr = getelementptr inbounds i32* %p, i32 5
+ %0 = load i32* %add.ptr, align 4, !tbaa !3
+ %sub = sub nsw i32 %0, %x
+ store i32 %sub, i32* %add.ptr, align 4, !tbaa !3
+ ret void
+}
+
+define void @memop_unsigned_int_or_index5(i32* nocapture %p, i32 %x) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#20){{ *}}|={{ *}}r{{[0-9]+}}
+ %add.ptr = getelementptr inbounds i32* %p, i32 5
+ %0 = load i32* %add.ptr, align 4, !tbaa !3
+ %or = or i32 %0, %x
+ store i32 %or, i32* %add.ptr, align 4, !tbaa !3
+ ret void
+}
+
+define void @memop_unsigned_int_and_index5(i32* nocapture %p, i32 %x) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#20){{ *}}&={{ *}}r{{[0-9]+}}
+ %add.ptr = getelementptr inbounds i32* %p, i32 5
+ %0 = load i32* %add.ptr, align 4, !tbaa !3
+ %and = and i32 %0, %x
+ store i32 %and, i32* %add.ptr, align 4, !tbaa !3
+ ret void
+}
+
+define void @memop_unsigned_int_clrbit_index5(i32* nocapture %p) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#20){{ *}}={{ *}}clrbit({{ *}}#5{{ *}})
+ %add.ptr = getelementptr inbounds i32* %p, i32 5
+ %0 = load i32* %add.ptr, align 4, !tbaa !3
+ %and = and i32 %0, -33
+ store i32 %and, i32* %add.ptr, align 4, !tbaa !3
+ ret void
+}
+
+define void @memop_unsigned_int_setbit_index5(i32* nocapture %p) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#20){{ *}}={{ *}}setbit({{ *}}#7{{ *}})
+ %add.ptr = getelementptr inbounds i32* %p, i32 5
+ %0 = load i32* %add.ptr, align 4, !tbaa !3
+ %or = or i32 %0, 128
+ store i32 %or, i32* %add.ptr, align 4, !tbaa !3
+ ret void
+}
+
+!0 = metadata !{metadata !"omnipotent char", metadata !1}
+!1 = metadata !{metadata !"Simple C/C++ TBAA"}
+!2 = metadata !{metadata !"short", metadata !0}
+!3 = metadata !{metadata !"int", metadata !0}
diff --git a/test/CodeGen/Hexagon/memops1.ll b/test/CodeGen/Hexagon/memops1.ll
new file mode 100644
index 0000000000..2babdc848d
--- /dev/null
+++ b/test/CodeGen/Hexagon/memops1.ll
@@ -0,0 +1,33 @@
+; RUN: llc -march=hexagon -mcpu=hexagonv5 < %s | FileCheck %s
+; Generate MemOps for V4 and above.
+
+
+define void @f(i32* %p) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#40){{ *}}-={{ *}}#1
+ %p.addr = alloca i32*, align 4
+ store i32* %p, i32** %p.addr, align 4
+ %0 = load i32** %p.addr, align 4
+ %add.ptr = getelementptr inbounds i32* %0, i32 10
+ %1 = load i32* %add.ptr, align 4
+ %sub = sub nsw i32 %1, 1
+ store i32 %sub, i32* %add.ptr, align 4
+ ret void
+}
+
+define void @g(i32* %p, i32 %i) nounwind {
+entry:
+; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#40){{ *}}-={{ *}}#1
+ %p.addr = alloca i32*, align 4
+ %i.addr = alloca i32, align 4
+ store i32* %p, i32** %p.addr, align 4
+ store i32 %i, i32* %i.addr, align 4
+ %0 = load i32** %p.addr, align 4
+ %1 = load i32* %i.addr, align 4
+ %add.ptr = getelementptr inbounds i32* %0, i32 %1
+ %add.ptr1 = getelementptr inbounds i32* %add.ptr, i32 10
+ %2 = load i32* %add.ptr1, align 4
+ %sub = sub nsw i32 %2, 1
+ store i32 %sub, i32* %add.ptr1, align 4
+ ret void
+}
diff --git a/test/CodeGen/Hexagon/memops2.ll b/test/CodeGen/Hexagon/memops2.ll
new file mode 100644
index 0000000000..b1b25445c0
--- /dev/null
+++ b/test/CodeGen/Hexagon/memops2.ll
@@ -0,0 +1,32 @@
+; RUN: llc -march=hexagon -mcpu=hexagonv5 < %s | FileCheck %s
+; Generate MemOps for V4 and above.
+
+
+define void @f(i16* nocapture %p) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#20){{ *}}-={{ *}}#1
+ %add.ptr = getelementptr inbounds i16* %p, i32 10
+ %0 = load i16* %add.ptr, align 2, !tbaa !0
+ %conv2 = zext i16 %0 to i32
+ %sub = add nsw i32 %conv2, 65535
+ %conv1 = trunc i32 %sub to i16
+ store i16 %conv1, i16* %add.ptr, align 2, !tbaa !0
+ ret void
+}
+
+define void @g(i16* nocapture %p, i32 %i) nounwind {
+entry:
+; CHECK: memh(r{{[0-9]+}}{{ *}}+{{ *}}#20){{ *}}-={{ *}}#1
+ %add.ptr.sum = add i32 %i, 10
+ %add.ptr1 = getelementptr inbounds i16* %p, i32 %add.ptr.sum
+ %0 = load i16* %add.ptr1, align 2, !tbaa !0
+ %conv3 = zext i16 %0 to i32
+ %sub = add nsw i32 %conv3, 65535
+ %conv2 = trunc i32 %sub to i16
+ store i16 %conv2, i16* %add.ptr1, align 2, !tbaa !0
+ ret void
+}
+
+!0 = metadata !{metadata !"short", metadata !1}
+!1 = metadata !{metadata !"omnipotent char", metadata !2}
+!2 = metadata !{metadata !"Simple C/C++ TBAA"}
diff --git a/test/CodeGen/Hexagon/memops3.ll b/test/CodeGen/Hexagon/memops3.ll
new file mode 100644
index 0000000000..5b8bd6c87b
--- /dev/null
+++ b/test/CodeGen/Hexagon/memops3.ll
@@ -0,0 +1,31 @@
+; RUN: llc -march=hexagon -mcpu=hexagonv5 < %s | FileCheck %s
+; Generate MemOps for V4 and above.
+
+
+define void @f(i8* nocapture %p) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#10){{ *}}-={{ *}}#1
+ %add.ptr = getelementptr inbounds i8* %p, i32 10
+ %0 = load i8* %add.ptr, align 1, !tbaa !0
+ %conv = zext i8 %0 to i32
+ %sub = add nsw i32 %conv, 255
+ %conv1 = trunc i32 %sub to i8
+ store i8 %conv1, i8* %add.ptr, align 1, !tbaa !0
+ ret void
+}
+
+define void @g(i8* nocapture %p, i32 %i) nounwind {
+entry:
+; CHECK: memb(r{{[0-9]+}}{{ *}}+{{ *}}#10){{ *}}-={{ *}}#1
+ %add.ptr.sum = add i32 %i, 10
+ %add.ptr1 = getelementptr inbounds i8* %p, i32 %add.ptr.sum
+ %0 = load i8* %add.ptr1, align 1, !tbaa !0
+ %conv = zext i8 %0 to i32
+ %sub = add nsw i32 %conv, 255
+ %conv2 = trunc i32 %sub to i8
+ store i8 %conv2, i8* %add.ptr1, align 1, !tbaa !0
+ ret void
+}
+
+!0 = metadata !{metadata !"omnipotent char", metadata !1}
+!1 = metadata !{metadata !"Simple C/C++ TBAA"}