Skip to content

Commit

Permalink
[MIPS GlobalISel] Fold load/store + G_GEP + G_CONSTANT
Browse files Browse the repository at this point in the history
Fold load/store + G_GEP + G_CONSTANT when
immediate in G_CONSTANT fits into 16 bit signed integer.

Differential Revision: https://reviews.llvm.org/D65507

llvm-svn: 367535
  • Loading branch information
Petar Avramovic authored and Petar Avramovic committed Aug 1, 2019
1 parent 0cfa72e commit 8a40ced
Show file tree
Hide file tree
Showing 8 changed files with 357 additions and 43 deletions.
25 changes: 23 additions & 2 deletions llvm/lib/Target/Mips/MipsInstructionSelector.cpp
Expand Up @@ -318,10 +318,31 @@ bool MipsInstructionSelector::select(MachineInstr &I,
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;
}
Expand Down
@@ -0,0 +1,214 @@
# 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
...

Expand Up @@ -32,9 +32,7 @@ body: |
; 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
Expand Down
4 changes: 1 addition & 3 deletions llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/load.ll
Expand Up @@ -16,9 +16,7 @@ define i64 @load_i64(i64* %ptr) {
; 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:
Expand Down
105 changes: 105 additions & 0 deletions llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/load_store_fold.ll
@@ -0,0 +1,105 @@
; 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
}


0 comments on commit 8a40ced

Please sign in to comment.