From f3c21b857b8449bcde35e499ef8268c0fec9514d Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Tue, 30 Jun 2009 02:15:48 +0000 Subject: [PATCH] A few more load instructions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@74500 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMInstrFormats.td | 5 +- lib/Target/ARM/ARMInstrInfo.h | 29 ++++----- lib/Target/ARM/ARMInstrThumb.td | 10 +-- lib/Target/ARM/ARMInstrThumb2.td | 88 ++++++++++++++++++++++----- test/CodeGen/Thumb2/thumb2-ldr_ext.ll | 28 +++++++++ test/CodeGen/Thumb2/thumb2-ldrb.ll | 60 ++++++++++++++++++ test/CodeGen/Thumb2/thumb2-ldrh.ll | 59 ++++++++++++++++++ 7 files changed, 243 insertions(+), 36 deletions(-) create mode 100644 test/CodeGen/Thumb2/thumb2-ldr_ext.ll create mode 100644 test/CodeGen/Thumb2/thumb2-ldrb.ll create mode 100644 test/CodeGen/Thumb2/thumb2-ldrh.ll diff --git a/lib/Target/ARM/ARMInstrFormats.td b/lib/Target/ARM/ARMInstrFormats.td index a98bf1e8567..f49e38fb2ce 100644 --- a/lib/Target/ARM/ARMInstrFormats.td +++ b/lib/Target/ARM/ARMInstrFormats.td @@ -79,7 +79,8 @@ def AddrModeT1_s : AddrMode<9>; def AddrModeT2_i12: AddrMode<10>; def AddrModeT2_i8 : AddrMode<11>; def AddrModeT2_so : AddrMode<12>; -def AddrModeT2_pc : AddrMode<13>; +def AddrModeT2_pc : AddrMode<13>; +def AddrModeT2_i8s4 : AddrMode<14>; // Instruction size. class SizeFlagVal val> { @@ -856,6 +857,8 @@ class T2Iso pattern> : Thumb2I; class T2Ipc pattern> : Thumb2I; +class T2Ii8s4 pattern> + : Thumb2I; class T2sI pattern> : Thumb2sI; diff --git a/lib/Target/ARM/ARMInstrInfo.h b/lib/Target/ARM/ARMInstrInfo.h index ac1eec0921c..cdc420820d5 100644 --- a/lib/Target/ARM/ARMInstrInfo.h +++ b/lib/Target/ARM/ARMInstrInfo.h @@ -33,20 +33,21 @@ namespace ARMII { // This four-bit field describes the addressing mode used. AddrModeMask = 0xf, - AddrModeNone = 0, - AddrMode1 = 1, - AddrMode2 = 2, - AddrMode3 = 3, - AddrMode4 = 4, - AddrMode5 = 5, - AddrModeT1_1 = 6, - AddrModeT1_2 = 7, - AddrModeT1_4 = 8, - AddrModeT1_s = 9, // i8 * 4 for pc and sp relative data - AddrModeT2_i12= 10, - AddrModeT2_i8 = 11, - AddrModeT2_so = 12, - AddrModeT2_pc = 13, // +/- i12 for pc relative data + AddrModeNone = 0, + AddrMode1 = 1, + AddrMode2 = 2, + AddrMode3 = 3, + AddrMode4 = 4, + AddrMode5 = 5, + AddrModeT1_1 = 6, + AddrModeT1_2 = 7, + AddrModeT1_4 = 8, + AddrModeT1_s = 9, // i8 * 4 for pc and sp relative data + AddrModeT2_i12 = 10, + AddrModeT2_i8 = 11, + AddrModeT2_so = 12, + AddrModeT2_pc = 13, // +/- i12 for pc relative data + AddrModeT2_i8s4 = 14, // i8 * 4 // Size* - Flags to keep track of the size of an instruction. SizeShift = 4, diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td index ae54a884ddd..c8e75384849 100644 --- a/lib/Target/ARM/ARMInstrThumb.td +++ b/lib/Target/ARM/ARMInstrThumb.td @@ -622,13 +622,13 @@ def : Tv5Pat<(ARMcall texternalsym:$func), (tBLXi texternalsym:$func)>; def : Tv5Pat<(ARMcall tGPR:$dst), (tBLXr tGPR:$dst)>; // zextload i1 -> zextload i8 -def : TPat<(zextloadi1 t_addrmode_s1:$addr), - (tLDRB t_addrmode_s1:$addr)>; +def : T1Pat<(zextloadi1 t_addrmode_s1:$addr), + (tLDRB t_addrmode_s1:$addr)>; // extload -> zextload -def : TPat<(extloadi1 t_addrmode_s1:$addr), (tLDRB t_addrmode_s1:$addr)>; -def : TPat<(extloadi8 t_addrmode_s1:$addr), (tLDRB t_addrmode_s1:$addr)>; -def : TPat<(extloadi16 t_addrmode_s2:$addr), (tLDRH t_addrmode_s2:$addr)>; +def : T1Pat<(extloadi1 t_addrmode_s1:$addr), (tLDRB t_addrmode_s1:$addr)>; +def : T1Pat<(extloadi8 t_addrmode_s1:$addr), (tLDRB t_addrmode_s1:$addr)>; +def : T1Pat<(extloadi16 t_addrmode_s2:$addr), (tLDRH t_addrmode_s2:$addr)>; // Large immediate handling. diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td index 7a56fd75970..f848550a45b 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -136,7 +136,7 @@ def t2addrmode_imm12 : Operand, let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm); } -// t2addrmode_imm8 := reg - imm8 +// t2addrmode_imm8 := reg - imm8 (also reg + imm8 for some instructions) def t2addrmode_imm8 : Operand, ComplexPattern { let PrintMethod = "printT2AddrModeImm8Operand"; @@ -383,6 +383,22 @@ multiclass T2I_cmp_is { } } +/// T2I_ld - Defines a set of (op r, {imm12|imm8|so_reg}) load patterns. +multiclass T2I_ld { + def i12 : T2Ii12<(outs GPR:$dst), (ins t2addrmode_imm12:$addr), + opc, " $dst, $addr", + [(set GPR:$dst, (opnode t2addrmode_imm12:$addr))]>; + def i8 : T2Ii8 <(outs GPR:$dst), (ins t2addrmode_imm8:$addr), + opc, " $dst, $addr", + [(set GPR:$dst, (opnode t2addrmode_imm8:$addr))]>; + def s : T2Iso <(outs GPR:$dst), (ins t2addrmode_so_reg:$addr), + opc, " $dst, $addr", + [(set GPR:$dst, (opnode t2addrmode_so_reg:$addr))]>; + def pci : T2Ipc <(outs GPR:$dst), (ins i32imm:$addr), + opc, " $dst, $addr", + [(set GPR:$dst, (opnode (ARMWrapper tconstpool:$addr)))]>; +} + //===----------------------------------------------------------------------===// // Instructions //===----------------------------------------------------------------------===// @@ -434,24 +450,64 @@ def t2ADDrSPs : T2XI<(outs GPR:$dst), (ins GPR:$sp, t2_so_reg:$rhs), // // Load -let canFoldAsLoad = 1 in { -def t2LDRi12 : T2Ii12<(outs GPR:$dst), (ins t2addrmode_imm12:$addr), - "ldr", " $dst, $addr", - [(set GPR:$dst, (load t2addrmode_imm12:$addr))]>; +let canFoldAsLoad = 1 in +defm t2LDR : T2I_ld<"ldr", UnOpFrag<(load node:$Src)>>; -def t2LDRi8 : T2Ii8<(outs GPR:$dst), (ins t2addrmode_imm8:$addr), - "ldr", " $dst, $addr", - [(set GPR:$dst, (load t2addrmode_imm8:$addr))]>; +// Loads with zero extension +defm t2LDRH : T2I_ld<"ldrh", UnOpFrag<(zextloadi16 node:$Src)>>; +defm t2LDRB : T2I_ld<"ldrb", UnOpFrag<(zextloadi8 node:$Src)>>; -def t2LDRs : T2Iso<(outs GPR:$dst), (ins t2addrmode_so_reg:$addr), - "ldr", " $dst, $addr", - [(set GPR:$dst, (load t2addrmode_so_reg:$addr))]>; +// Loads with sign extension +defm t2LDRSH : T2I_ld<"ldrsh", UnOpFrag<(sextloadi16 node:$Src)>>; +defm t2LDRSB : T2I_ld<"ldrsb", UnOpFrag<(sextloadi8 node:$Src)>>; -// Load tconstpool -def t2LDRpci : T2Ipc<(outs GPR:$dst), (ins i32imm:$addr), - "ldr", " $dst, $addr", - [(set GPR:$dst, (load (ARMWrapper tconstpool:$addr)))]>; -} // canFoldAsLoad +let mayLoad = 1 in { +// Load doubleword +def t2LDRDi8 : T2Ii8s4<(outs GPR:$dst), (ins t2addrmode_imm8:$addr), + "ldrd", " $dst, $addr", []>; +def t2LDRDpci : T2Ii8s4<(outs GPR:$dst), (ins i32imm:$addr), + "ldrd", " $dst, $addr", []>; +} + +// zextload i1 -> zextload i8 +def : T2Pat<(zextloadi1 t2addrmode_imm12:$addr), + (t2LDRBi12 t2addrmode_imm12:$addr)>; +def : T2Pat<(zextloadi1 t2addrmode_imm8:$addr), + (t2LDRBi8 t2addrmode_imm8:$addr)>; +def : T2Pat<(zextloadi1 t2addrmode_so_reg:$addr), + (t2LDRBs t2addrmode_so_reg:$addr)>; +def : T2Pat<(zextloadi1 (ARMWrapper tconstpool:$addr)), + (t2LDRBpci tconstpool:$addr)>; + +// extload -> zextload +// FIXME: Reduce the number of patterns by legalizing extload to zextload +// earlier? +def : T2Pat<(extloadi1 t2addrmode_imm12:$addr), + (t2LDRBi12 t2addrmode_imm12:$addr)>; +def : T2Pat<(extloadi1 t2addrmode_imm8:$addr), + (t2LDRBi8 t2addrmode_imm8:$addr)>; +def : T2Pat<(extloadi1 t2addrmode_so_reg:$addr), + (t2LDRBs t2addrmode_so_reg:$addr)>; +def : T2Pat<(extloadi1 (ARMWrapper tconstpool:$addr)), + (t2LDRBpci tconstpool:$addr)>; + +def : T2Pat<(extloadi8 t2addrmode_imm12:$addr), + (t2LDRBi12 t2addrmode_imm12:$addr)>; +def : T2Pat<(extloadi8 t2addrmode_imm8:$addr), + (t2LDRBi8 t2addrmode_imm8:$addr)>; +def : T2Pat<(extloadi8 t2addrmode_so_reg:$addr), + (t2LDRBs t2addrmode_so_reg:$addr)>; +def : T2Pat<(extloadi8 (ARMWrapper tconstpool:$addr)), + (t2LDRBpci tconstpool:$addr)>; + +def : T2Pat<(extloadi16 t2addrmode_imm12:$addr), + (t2LDRHi12 t2addrmode_imm12:$addr)>; +def : T2Pat<(extloadi16 t2addrmode_imm8:$addr), + (t2LDRHi8 t2addrmode_imm8:$addr)>; +def : T2Pat<(extloadi16 t2addrmode_so_reg:$addr), + (t2LDRHs t2addrmode_so_reg:$addr)>; +def : T2Pat<(extloadi16 (ARMWrapper tconstpool:$addr)), + (t2LDRHpci tconstpool:$addr)>; //===----------------------------------------------------------------------===// // Move Instructions. diff --git a/test/CodeGen/Thumb2/thumb2-ldr_ext.ll b/test/CodeGen/Thumb2/thumb2-ldr_ext.ll new file mode 100644 index 00000000000..d48ecef1c11 --- /dev/null +++ b/test/CodeGen/Thumb2/thumb2-ldr_ext.ll @@ -0,0 +1,28 @@ +; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep ldrb | count 1 +; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep ldrh | count 1 +; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep ldrsb | count 1 +; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep ldrsh | count 1 + +define i32 @test1(i8* %v.pntr.s0.u1) { + %tmp.u = load i8* %v.pntr.s0.u1 + %tmp1.s = zext i8 %tmp.u to i32 + ret i32 %tmp1.s +} + +define i32 @test2(i16* %v.pntr.s0.u1) { + %tmp.u = load i16* %v.pntr.s0.u1 + %tmp1.s = zext i16 %tmp.u to i32 + ret i32 %tmp1.s +} + +define i32 @test3(i8* %v.pntr.s1.u0) { + %tmp.s = load i8* %v.pntr.s1.u0 + %tmp1.s = sext i8 %tmp.s to i32 + ret i32 %tmp1.s +} + +define i32 @test4() { + %tmp.s = load i16* null + %tmp1.s = sext i16 %tmp.s to i32 + ret i32 %tmp1.s +} diff --git a/test/CodeGen/Thumb2/thumb2-ldrb.ll b/test/CodeGen/Thumb2/thumb2-ldrb.ll new file mode 100644 index 00000000000..5bacb8eb2b4 --- /dev/null +++ b/test/CodeGen/Thumb2/thumb2-ldrb.ll @@ -0,0 +1,60 @@ +; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep {ldrb r0} | count 7 +; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep mov | grep 1 +; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | not grep mvn +; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep ldrb | grep lsl +; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep lsr | not grep ldrb + +define i8 @f1(i8* %v) { +entry: + %tmp = load i8* %v + ret i8 %tmp +} + +define i8 @f2(i8* %v) { +entry: + %tmp2 = getelementptr i8* %v, i8 1023 + %tmp = load i8* %tmp2 + ret i8 %tmp +} + +define i8 @f3(i32 %base) { +entry: + %tmp1 = add i32 %base, 4096 + %tmp2 = inttoptr i32 %tmp1 to i8* + %tmp3 = load i8* %tmp2 + ret i8 %tmp3 +} + +define i8 @f4(i32 %base) { +entry: + %tmp1 = sub i32 %base, 128 + %tmp2 = inttoptr i32 %tmp1 to i8* + %tmp3 = load i8* %tmp2 + ret i8 %tmp3 +} + +define i8 @f5(i32 %base, i32 %offset) { +entry: + %tmp1 = add i32 %base, %offset + %tmp2 = inttoptr i32 %tmp1 to i8* + %tmp3 = load i8* %tmp2 + ret i8 %tmp3 +} + +define i8 @f6(i32 %base, i32 %offset) { +entry: + %tmp1 = shl i32 %offset, 2 + %tmp2 = add i32 %base, %tmp1 + %tmp3 = inttoptr i32 %tmp2 to i8* + %tmp4 = load i8* %tmp3 + ret i8 %tmp4 +} + +define i8 @f7(i32 %base, i32 %offset) { +entry: + %tmp1 = lshr i32 %offset, 2 + %tmp2 = add i32 %base, %tmp1 + %tmp3 = inttoptr i32 %tmp2 to i8* + %tmp4 = load i8* %tmp3 + ret i8 %tmp4 +} diff --git a/test/CodeGen/Thumb2/thumb2-ldrh.ll b/test/CodeGen/Thumb2/thumb2-ldrh.ll new file mode 100644 index 00000000000..15f803e1108 --- /dev/null +++ b/test/CodeGen/Thumb2/thumb2-ldrh.ll @@ -0,0 +1,59 @@ +; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep {ldrh r0} | count 7 +; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep mov | grep 1 +; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | not grep mvn +; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep ldrh | grep lsl +; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep lsr | not grep ldrh + +define i16 @f1(i16* %v) { +entry: + %tmp = load i16* %v + ret i16 %tmp +} + +define i16 @f2(i16* %v) { +entry: + %tmp2 = getelementptr i16* %v, i16 1023 + %tmp = load i16* %tmp2 + ret i16 %tmp +} + +define i16 @f3(i16* %v) { +entry: + %tmp2 = getelementptr i16* %v, i16 2048 + %tmp = load i16* %tmp2 + ret i16 %tmp +} + +define i16 @f4(i32 %base) { +entry: + %tmp1 = sub i32 %base, 128 + %tmp2 = inttoptr i32 %tmp1 to i16* + %tmp3 = load i16* %tmp2 + ret i16 %tmp3 +} + +define i16 @f5(i32 %base, i32 %offset) { +entry: + %tmp1 = add i32 %base, %offset + %tmp2 = inttoptr i32 %tmp1 to i16* + %tmp3 = load i16* %tmp2 + ret i16 %tmp3 +} + +define i16 @f6(i32 %base, i32 %offset) { +entry: + %tmp1 = shl i32 %offset, 2 + %tmp2 = add i32 %base, %tmp1 + %tmp3 = inttoptr i32 %tmp2 to i16* + %tmp4 = load i16* %tmp3 + ret i16 %tmp4 +} + +define i16 @f7(i32 %base, i32 %offset) { +entry: + %tmp1 = lshr i32 %offset, 2 + %tmp2 = add i32 %base, %tmp1 + %tmp3 = inttoptr i32 %tmp2 to i16* + %tmp4 = load i16* %tmp3 + ret i16 %tmp4 +}