if (NewOpc == I.getOpcode())
return false;
+ MachineOperand BaseAddr = I.getOperand(1);
+ int64_t SignedOffset = 0;
+ // Try to fold load/store + G_GEP + G_CONSTANT
+ // %SignedOffset:(s32) = G_CONSTANT i32 16_bit_signed_immediate
+ // %Addr:(p0) = G_GEP %BaseAddr, %SignedOffset
+ // %LoadResult/%StoreSrc = load/store %Addr(p0)
+ // into:
+ // %LoadResult/%StoreSrc = NewOpc %BaseAddr(p0), 16_bit_signed_immediate
+
+ MachineInstr *Addr = MRI.getVRegDef(I.getOperand(1).getReg());
+ if (Addr->getOpcode() == G_GEP) {
+ MachineInstr *Offset = MRI.getVRegDef(Addr->getOperand(2).getReg());
+ if (Offset->getOpcode() == G_CONSTANT) {
+ APInt OffsetValue = Offset->getOperand(1).getCImm()->getValue();
+ if (OffsetValue.isSignedIntN(16)) {
+ BaseAddr = Addr->getOperand(1);
+ SignedOffset = OffsetValue.getSExtValue();
+ }
+ }
+ }
+
MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(NewOpc))
.add(I.getOperand(0))
- .add(I.getOperand(1))
- .addImm(0)
+ .add(BaseAddr)
+ .addImm(SignedOffset)
.addMemOperand(*I.memoperands_begin());
break;
}
--- /dev/null
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -O0 -mtriple=mipsel-linux-gnu -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32
+--- |
+
+ define void @_16_bit_positive_offset() {entry: ret void}
+ define void @_16_bit_negative_offset() {entry: ret void}
+ define void @_large_positive_offset() {entry: ret void}
+ define void @_large_negative_offset() {entry: ret void}
+ define void @fold_f32_load() {entry: ret void}
+ define void @fold_f64_store() {entry: ret void}
+ define void @fold_i16_load() {entry: ret void}
+ define void @fold_i32_store() {entry: ret void}
+
+...
+---
+name: _16_bit_positive_offset
+alignment: 2
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $a0
+
+ ; MIPS32-LABEL: name: _16_bit_positive_offset
+ ; MIPS32: liveins: $a0
+ ; MIPS32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
+ ; MIPS32: [[LBu:%[0-9]+]]:gpr32 = LBu [[COPY]], 32767 :: (load 1)
+ ; MIPS32: $v0 = COPY [[LBu]]
+ ; MIPS32: RetRA implicit $v0
+ %0:gprb(p0) = COPY $a0
+ %1:gprb(s32) = G_CONSTANT i32 32767
+ %2:gprb(p0) = G_GEP %0, %1(s32)
+ %4:gprb(s32) = G_ZEXTLOAD %2(p0) :: (load 1)
+ $v0 = COPY %4(s32)
+ RetRA implicit $v0
+
+...
+---
+name: _16_bit_negative_offset
+alignment: 2
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $a0, $a1
+
+ ; MIPS32-LABEL: name: _16_bit_negative_offset
+ ; MIPS32: liveins: $a0, $a1
+ ; MIPS32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
+ ; MIPS32: [[COPY1:%[0-9]+]]:gpr32 = COPY $a1
+ ; MIPS32: SB [[COPY]], [[COPY1]], -32768 :: (store 1)
+ ; MIPS32: RetRA
+ %2:gprb(s32) = COPY $a0
+ %1:gprb(p0) = COPY $a1
+ %3:gprb(s32) = G_CONSTANT i32 -32768
+ %4:gprb(p0) = G_GEP %1, %3(s32)
+ %5:gprb(s32) = COPY %2(s32)
+ G_STORE %5(s32), %4(p0) :: (store 1)
+ RetRA
+
+...
+---
+name: _large_positive_offset
+alignment: 2
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $a0, $a1
+
+ ; MIPS32-LABEL: name: _large_positive_offset
+ ; MIPS32: liveins: $a0, $a1
+ ; MIPS32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
+ ; MIPS32: [[COPY1:%[0-9]+]]:gpr32 = COPY $a1
+ ; MIPS32: [[ORi:%[0-9]+]]:gpr32 = ORi $zero, 32768
+ ; MIPS32: [[ADDu:%[0-9]+]]:gpr32 = ADDu [[COPY1]], [[ORi]]
+ ; MIPS32: SB [[COPY]], [[ADDu]], 0 :: (store 1)
+ ; MIPS32: RetRA
+ %2:gprb(s32) = COPY $a0
+ %1:gprb(p0) = COPY $a1
+ %3:gprb(s32) = G_CONSTANT i32 32768
+ %4:gprb(p0) = G_GEP %1, %3(s32)
+ %5:gprb(s32) = COPY %2(s32)
+ G_STORE %5(s32), %4(p0) :: (store 1)
+ RetRA
+
+...
+---
+name: _large_negative_offset
+alignment: 2
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $a0
+
+ ; MIPS32-LABEL: name: _large_negative_offset
+ ; MIPS32: liveins: $a0
+ ; MIPS32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
+ ; MIPS32: [[LUi:%[0-9]+]]:gpr32 = LUi 65535
+ ; MIPS32: [[ORi:%[0-9]+]]:gpr32 = ORi [[LUi]], 32767
+ ; MIPS32: [[ADDu:%[0-9]+]]:gpr32 = ADDu [[COPY]], [[ORi]]
+ ; MIPS32: [[LB:%[0-9]+]]:gpr32 = LB [[ADDu]], 0 :: (load 1)
+ ; MIPS32: $v0 = COPY [[LB]]
+ ; MIPS32: RetRA implicit $v0
+ %0:gprb(p0) = COPY $a0
+ %1:gprb(s32) = G_CONSTANT i32 -32769
+ %2:gprb(p0) = G_GEP %0, %1(s32)
+ %4:gprb(s32) = G_SEXTLOAD %2(p0) :: (load 1)
+ $v0 = COPY %4(s32)
+ RetRA implicit $v0
+
+...
+---
+name: fold_f32_load
+alignment: 2
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $a0
+
+ ; MIPS32-LABEL: name: fold_f32_load
+ ; MIPS32: liveins: $a0
+ ; MIPS32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
+ ; MIPS32: [[LWC1_:%[0-9]+]]:fgr32 = LWC1 [[COPY]], 40 :: (load 4)
+ ; MIPS32: $f0 = COPY [[LWC1_]]
+ ; MIPS32: RetRA implicit $f0
+ %0:gprb(p0) = COPY $a0
+ %1:gprb(s32) = G_CONSTANT i32 40
+ %2:gprb(p0) = G_GEP %0, %1(s32)
+ %3:fprb(s32) = G_LOAD %2(p0) :: (load 4)
+ $f0 = COPY %3(s32)
+ RetRA implicit $f0
+
+...
+---
+name: fold_f64_store
+alignment: 2
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $a2, $d6
+
+ ; MIPS32-LABEL: name: fold_f64_store
+ ; MIPS32: liveins: $a2, $d6
+ ; MIPS32: [[COPY:%[0-9]+]]:afgr64 = COPY $d6
+ ; MIPS32: [[COPY1:%[0-9]+]]:gpr32 = COPY $a2
+ ; MIPS32: SDC1 [[COPY]], [[COPY1]], -80 :: (store 8)
+ ; MIPS32: RetRA
+ %0:fprb(s64) = COPY $d6
+ %1:gprb(p0) = COPY $a2
+ %2:gprb(s32) = G_CONSTANT i32 -80
+ %3:gprb(p0) = G_GEP %1, %2(s32)
+ G_STORE %0(s64), %3(p0) :: (store 8)
+ RetRA
+
+...
+---
+name: fold_i16_load
+alignment: 2
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $a0
+
+ ; MIPS32-LABEL: name: fold_i16_load
+ ; MIPS32: liveins: $a0
+ ; MIPS32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
+ ; MIPS32: [[LHu:%[0-9]+]]:gpr32 = LHu [[COPY]], -20 :: (load 2)
+ ; MIPS32: $v0 = COPY [[LHu]]
+ ; MIPS32: RetRA implicit $v0
+ %0:gprb(p0) = COPY $a0
+ %1:gprb(s32) = G_CONSTANT i32 -20
+ %2:gprb(p0) = G_GEP %0, %1(s32)
+ %4:gprb(s32) = G_LOAD %2(p0) :: (load 2)
+ $v0 = COPY %4(s32)
+ RetRA implicit $v0
+
+...
+---
+name: fold_i32_store
+alignment: 2
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $a0, $a1
+
+ ; MIPS32-LABEL: name: fold_i32_store
+ ; MIPS32: liveins: $a0, $a1
+ ; MIPS32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
+ ; MIPS32: [[COPY1:%[0-9]+]]:gpr32 = COPY $a1
+ ; MIPS32: SW [[COPY]], [[COPY1]], 40 :: (store 4)
+ ; MIPS32: RetRA
+ %0:gprb(s32) = COPY $a0
+ %1:gprb(p0) = COPY $a1
+ %2:gprb(s32) = G_CONSTANT i32 40
+ %3:gprb(p0) = G_GEP %1, %2(s32)
+ G_STORE %0(s32), %3(p0) :: (store 4)
+ RetRA
+
+...
+
; MIPS32: $a2 = COPY [[COPY2]]
; MIPS32: $a3 = COPY [[COPY3]]
; MIPS32: [[COPY4:%[0-9]+]]:gpr32 = COPY $sp
- ; MIPS32: [[ORi:%[0-9]+]]:gpr32 = ORi $zero, 1
- ; MIPS32: [[ADDu:%[0-9]+]]:gpr32 = ADDu [[COPY4]], [[ORi]]
- ; MIPS32: SW [[LW]], [[ADDu]], 0 :: (store 4 into stack + 16)
+ ; MIPS32: SW [[LW]], [[COPY4]], 16 :: (store 4 into stack + 16)
; MIPS32: JAL @f, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit $a2, implicit $a3, implicit-def $v0
; MIPS32: [[COPY5:%[0-9]+]]:gpr32 = COPY $v0
; MIPS32: ADJCALLSTACKUP 24, 0, implicit-def $sp, implicit $sp
; MIPS32-LABEL: load_i64:
; MIPS32: # %bb.0: # %entry
; MIPS32-NEXT: lw $2, 0($4)
-; MIPS32-NEXT: ori $1, $zero, 4
-; MIPS32-NEXT: addu $1, $4, $1
-; MIPS32-NEXT: lw $3, 0($1)
+; MIPS32-NEXT: lw $3, 4($4)
; MIPS32-NEXT: jr $ra
; MIPS32-NEXT: nop
entry:
--- /dev/null
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -O0 -mtriple=mipsel-linux-gnu -global-isel -verify-machineinstrs %s -o -| FileCheck %s -check-prefixes=MIPS32
+
+define zeroext i8 @_16_bit_positive_offset(i8* %a) {
+; MIPS32-LABEL: _16_bit_positive_offset:
+; MIPS32: # %bb.0: # %entry
+; MIPS32-NEXT: lbu $2, 32767($4)
+; MIPS32-NEXT: jr $ra
+; MIPS32-NEXT: nop
+entry:
+ %arrayidx = getelementptr inbounds i8, i8* %a, i32 32767
+ %0 = load i8, i8* %arrayidx
+ ret i8 %0
+}
+
+define void @_16_bit_negative_offset(i8 %val, i8* %a) {
+; MIPS32-LABEL: _16_bit_negative_offset:
+; MIPS32: # %bb.0: # %entry
+; MIPS32-NEXT: sb $4, -32768($5)
+; MIPS32-NEXT: jr $ra
+; MIPS32-NEXT: nop
+entry:
+ %arrayidx = getelementptr inbounds i8, i8* %a, i32 -32768
+ store i8 %val, i8* %arrayidx
+ ret void
+}
+
+define void @_large_positive_offset(i8 %val, i8* %a) {
+; MIPS32-LABEL: _large_positive_offset:
+; MIPS32: # %bb.0: # %entry
+; MIPS32-NEXT: ori $1, $zero, 32768
+; MIPS32-NEXT: addu $1, $5, $1
+; MIPS32-NEXT: sb $4, 0($1)
+; MIPS32-NEXT: jr $ra
+; MIPS32-NEXT: nop
+entry:
+ %arrayidx = getelementptr inbounds i8, i8* %a, i32 32768
+ store i8 %val, i8* %arrayidx
+ ret void
+}
+
+define signext i8 @_large_negative_offset(i8* %a) {
+; MIPS32-LABEL: _large_negative_offset:
+; MIPS32: # %bb.0: # %entry
+; MIPS32-NEXT: lui $1, 65535
+; MIPS32-NEXT: ori $1, $1, 32767
+; MIPS32-NEXT: addu $1, $4, $1
+; MIPS32-NEXT: lb $2, 0($1)
+; MIPS32-NEXT: jr $ra
+; MIPS32-NEXT: nop
+entry:
+ %arrayidx = getelementptr inbounds i8, i8* %a, i32 -32769
+ %0 = load i8, i8* %arrayidx
+ ret i8 %0
+}
+
+define float @fold_f32_load(float* %a) {
+; MIPS32-LABEL: fold_f32_load:
+; MIPS32: # %bb.0: # %entry
+; MIPS32-NEXT: lwc1 $f0, 40($4)
+; MIPS32-NEXT: jr $ra
+; MIPS32-NEXT: nop
+entry:
+ %arrayidx = getelementptr inbounds float, float* %a, i32 10
+ %0 = load float, float* %arrayidx
+ ret float %0
+}
+
+define void @fold_f64_store(double %val, double* %a) {
+; MIPS32-LABEL: fold_f64_store:
+; MIPS32: # %bb.0: # %entry
+; MIPS32-NEXT: sdc1 $f12, -80($6)
+; MIPS32-NEXT: jr $ra
+; MIPS32-NEXT: nop
+entry:
+ %arrayidx = getelementptr inbounds double, double* %a, i32 -10
+ store double %val, double* %arrayidx
+ ret void
+}
+
+define i16 @fold_i16_load(i16* %a) {
+; MIPS32-LABEL: fold_i16_load:
+; MIPS32: # %bb.0: # %entry
+; MIPS32-NEXT: lhu $2, -20($4)
+; MIPS32-NEXT: jr $ra
+; MIPS32-NEXT: nop
+entry:
+ %arrayidx = getelementptr inbounds i16, i16* %a, i32 -10
+ %0 = load i16, i16* %arrayidx
+ ret i16 %0
+}
+
+define void @fold_i32_store(i32 %val, i32* %a) {
+; MIPS32-LABEL: fold_i32_store:
+; MIPS32: # %bb.0: # %entry
+; MIPS32-NEXT: sw $4, 40($5)
+; MIPS32-NEXT: jr $ra
+; MIPS32-NEXT: nop
+entry:
+ %arrayidx = getelementptr inbounds i32, i32* %a, i32 10
+ store i32 %val, i32* %arrayidx
+ ret void
+}
+
+
; MIPS32-NEXT: # %bb.3: # %b.PHI.1.0
; MIPS32-NEXT: lw $1, 60($sp) # 4-byte Folded Reload
; MIPS32-NEXT: lw $2, 0($1)
-; MIPS32-NEXT: ori $3, $zero, 4
-; MIPS32-NEXT: addu $3, $1, $3
-; MIPS32-NEXT: lw $3, 0($3)
+; MIPS32-NEXT: lw $3, 4($1)
; MIPS32-NEXT: sw $2, 44($sp) # 4-byte Folded Spill
; MIPS32-NEXT: sw $3, 40($sp) # 4-byte Folded Spill
; MIPS32-NEXT: j $BB1_6
; MIPS32-NEXT: $BB1_4: # %b.PHI.1.1
; MIPS32-NEXT: lw $1, 76($sp) # 4-byte Folded Reload
; MIPS32-NEXT: lw $2, 0($1)
-; MIPS32-NEXT: ori $3, $zero, 4
-; MIPS32-NEXT: addu $3, $1, $3
-; MIPS32-NEXT: lw $3, 0($3)
+; MIPS32-NEXT: lw $3, 4($1)
; MIPS32-NEXT: sw $2, 44($sp) # 4-byte Folded Spill
; MIPS32-NEXT: sw $3, 40($sp) # 4-byte Folded Spill
; MIPS32-NEXT: j $BB1_6
; MIPS32-NEXT: $BB1_5: # %b.PHI.1.2
; MIPS32-NEXT: lw $1, 56($sp) # 4-byte Folded Reload
; MIPS32-NEXT: lw $2, 0($1)
-; MIPS32-NEXT: ori $3, $zero, 4
-; MIPS32-NEXT: addu $3, $1, $3
-; MIPS32-NEXT: lw $3, 0($3)
+; MIPS32-NEXT: lw $3, 4($1)
; MIPS32-NEXT: sw $2, 44($sp) # 4-byte Folded Spill
; MIPS32-NEXT: sw $3, 40($sp) # 4-byte Folded Spill
; MIPS32-NEXT: $BB1_6: # %b.PHI.1
; MIPS32-NEXT: lw $1, 32($sp) # 4-byte Folded Reload
; MIPS32-NEXT: lw $2, 52($sp) # 4-byte Folded Reload
; MIPS32-NEXT: sw $1, 0($2)
-; MIPS32-NEXT: ori $3, $zero, 4
-; MIPS32-NEXT: addu $3, $2, $3
-; MIPS32-NEXT: lw $4, 36($sp) # 4-byte Folded Reload
-; MIPS32-NEXT: sw $4, 0($3)
+; MIPS32-NEXT: lw $3, 36($sp) # 4-byte Folded Reload
+; MIPS32-NEXT: sw $3, 4($2)
; MIPS32-NEXT: addiu $sp, $sp, 80
; MIPS32-NEXT: jr $ra
; MIPS32-NEXT: nop
; MIPS32-NEXT: $BB1_11: # %b.PHI.2.0
; MIPS32-NEXT: lw $1, 60($sp) # 4-byte Folded Reload
; MIPS32-NEXT: lw $2, 0($1)
-; MIPS32-NEXT: ori $3, $zero, 4
-; MIPS32-NEXT: addu $3, $1, $3
-; MIPS32-NEXT: lw $3, 0($3)
+; MIPS32-NEXT: lw $3, 4($1)
; MIPS32-NEXT: sw $2, 12($sp) # 4-byte Folded Spill
; MIPS32-NEXT: sw $3, 8($sp) # 4-byte Folded Spill
; MIPS32-NEXT: j $BB1_13
; MIPS32-NEXT: $BB1_12: # %b.PHI.2.1
; MIPS32-NEXT: lw $1, 76($sp) # 4-byte Folded Reload
; MIPS32-NEXT: lw $2, 0($1)
-; MIPS32-NEXT: ori $3, $zero, 4
-; MIPS32-NEXT: addu $3, $1, $3
-; MIPS32-NEXT: lw $3, 0($3)
+; MIPS32-NEXT: lw $3, 4($1)
; MIPS32-NEXT: sw $2, 12($sp) # 4-byte Folded Spill
; MIPS32-NEXT: sw $3, 8($sp) # 4-byte Folded Spill
; MIPS32-NEXT: $BB1_13: # %b.PHI.2
; MIPS32-NEXT: lw $1, 0($sp) # 4-byte Folded Reload
; MIPS32-NEXT: lw $2, 52($sp) # 4-byte Folded Reload
; MIPS32-NEXT: sw $1, 0($2)
-; MIPS32-NEXT: ori $3, $zero, 4
-; MIPS32-NEXT: addu $3, $2, $3
-; MIPS32-NEXT: lw $4, 4($sp) # 4-byte Folded Reload
-; MIPS32-NEXT: sw $4, 0($3)
+; MIPS32-NEXT: lw $3, 4($sp) # 4-byte Folded Reload
+; MIPS32-NEXT: sw $3, 4($2)
; MIPS32-NEXT: addiu $sp, $sp, 80
; MIPS32-NEXT: jr $ra
; MIPS32-NEXT: nop
; MIPS32-NEXT: movn $2, $1, $5
; MIPS32-NEXT: lw $1, 52($sp) # 4-byte Folded Reload
; MIPS32-NEXT: sw $8, 0($1)
-; MIPS32-NEXT: ori $5, $zero, 4
-; MIPS32-NEXT: addu $5, $1, $5
-; MIPS32-NEXT: sw $2, 0($5)
+; MIPS32-NEXT: sw $2, 4($1)
; MIPS32-NEXT: sw $4, 0($1)
-; MIPS32-NEXT: ori $2, $zero, 4
-; MIPS32-NEXT: addu $2, $1, $2
-; MIPS32-NEXT: sw $3, 0($2)
+; MIPS32-NEXT: sw $3, 4($1)
; MIPS32-NEXT: addiu $sp, $sp, 80
; MIPS32-NEXT: jr $ra
; MIPS32-NEXT: nop
; MIPS32-NEXT: addiu $1, $sp, 48
; MIPS32-NEXT: lw $1, 0($1)
; MIPS32-NEXT: move $2, $sp
-; MIPS32-NEXT: ori $3, $zero, 16
-; MIPS32-NEXT: addu $2, $2, $3
-; MIPS32-NEXT: sw $1, 0($2)
+; MIPS32-NEXT: sw $1, 16($2)
; MIPS32-NEXT: jal f
; MIPS32-NEXT: nop
; MIPS32-NEXT: lw $ra, 28($sp) # 4-byte Folded Reload
; MIPS32-LABEL: store_i64:
; MIPS32: # %bb.0: # %entry
; MIPS32-NEXT: sw $4, 0($6)
-; MIPS32-NEXT: ori $1, $zero, 4
-; MIPS32-NEXT: addu $1, $6, $1
-; MIPS32-NEXT: sw $5, 0($1)
+; MIPS32-NEXT: sw $5, 4($6)
; MIPS32-NEXT: jr $ra
; MIPS32-NEXT: nop
entry: