Ticket #5208: 0001-Add-test-for-unrolling-memcpy-memset-in-the-x86-back.patch
| File 0001-Add-test-for-unrolling-memcpy-memset-in-the-x86-back.patch, 11.7 KB (added by tibbe, 2 years ago) |
|---|
-
tests/ghc-regress/codeGen/should_run/cgrun069.hs
From 2fa63c3d2f55f1519410deafb3dec2620643d292 Mon Sep 17 00:00:00 2001 From: Johan Tibell <johan.tibell@gmail.com> Date: Wed, 8 Jun 2011 17:27:59 +0200 Subject: [PATCH] Add test for unrolling memcpy/memset in the x86 backend --- tests/ghc-regress/codeGen/should_run/cgrun069.hs | 72 +++++++++++- .../codeGen/should_run/cgrun069_cmm.cmm | 121 +++++++++++++++++++- 2 files changed, 186 insertions(+), 7 deletions(-) diff --git a/tests/ghc-regress/codeGen/should_run/cgrun069.hs b/tests/ghc-regress/codeGen/should_run/cgrun069.hs index d49e7f5..0c6bf7a 100644
a b 5 5 import Control.Exception 6 6 import System.IO 7 7 8 foreign import prim "memintrinTest" memcpyTest :: Int# -> Int# 8 foreign import prim "memintrinTest" basicTest :: Int# -> Int# 9 10 foreign import prim "testMemset8_0" testMemset8_0 :: Int# -> Int# 11 foreign import prim "testMemset8_8" testMemset8_8 :: Int# -> Int# 12 foreign import prim "testMemset8_9" testMemset8_9 :: Int# -> Int# 13 foreign import prim "testMemset8_10" testMemset8_10 :: Int# -> Int# 14 foreign import prim "testMemset8_11" testMemset8_11 :: Int# -> Int# 15 foreign import prim "testMemset8_12" testMemset8_12 :: Int# -> Int# 16 foreign import prim "testMemset8_13" testMemset8_13 :: Int# -> Int# 17 foreign import prim "testMemset8_14" testMemset8_14 :: Int# -> Int# 18 foreign import prim "testMemset8_15" testMemset8_15 :: Int# -> Int# 19 foreign import prim "testMemset8_16" testMemset8_16 :: Int# -> Int# 20 foreign import prim "testMemset4_0" testMemset4_0 :: Int# -> Int# 21 foreign import prim "testMemset4_4" testMemset4_4 :: Int# -> Int# 22 foreign import prim "testMemset4_5" testMemset4_5 :: Int# -> Int# 23 foreign import prim "testMemset4_6" testMemset4_6 :: Int# -> Int# 24 foreign import prim "testMemset4_7" testMemset4_7 :: Int# -> Int# 25 foreign import prim "testMemset4_8" testMemset4_8 :: Int# -> Int# 26 27 foreign import prim "testMemcpy8_0" testMemcpy8_0 :: Int# -> Int# 28 foreign import prim "testMemcpy8_8" testMemcpy8_8 :: Int# -> Int# 29 foreign import prim "testMemcpy8_9" testMemcpy8_9 :: Int# -> Int# 30 foreign import prim "testMemcpy8_10" testMemcpy8_10 :: Int# -> Int# 31 foreign import prim "testMemcpy8_11" testMemcpy8_11 :: Int# -> Int# 32 foreign import prim "testMemcpy8_12" testMemcpy8_12 :: Int# -> Int# 33 foreign import prim "testMemcpy8_13" testMemcpy8_13 :: Int# -> Int# 34 foreign import prim "testMemcpy8_14" testMemcpy8_14 :: Int# -> Int# 35 foreign import prim "testMemcpy8_15" testMemcpy8_15 :: Int# -> Int# 36 foreign import prim "testMemcpy8_16" testMemcpy8_16 :: Int# -> Int# 37 foreign import prim "testMemcpy4_0" testMemcpy4_0 :: Int# -> Int# 38 foreign import prim "testMemcpy4_4" testMemcpy4_4 :: Int# -> Int# 39 foreign import prim "testMemcpy4_5" testMemcpy4_5 :: Int# -> Int# 40 foreign import prim "testMemcpy4_6" testMemcpy4_6 :: Int# -> Int# 41 foreign import prim "testMemcpy4_7" testMemcpy4_7 :: Int# -> Int# 42 foreign import prim "testMemcpy4_8" testMemcpy4_8 :: Int# -> Int# 9 43 10 44 main = do 11 45 putStrLn "Mem{cpy,set,move} Intrinsics Test..." 12 _ <- evaluate (I# (memcpyTest 1#)) 46 _ <- evaluate (I# (basicTest 1#)) 47 48 _ <- evaluate (I# (testMemset8_0 1#)) 49 _ <- evaluate (I# (testMemset8_8 1#)) 50 _ <- evaluate (I# (testMemset8_9 1#)) 51 _ <- evaluate (I# (testMemset8_10 1#)) 52 _ <- evaluate (I# (testMemset8_11 1#)) 53 _ <- evaluate (I# (testMemset8_12 1#)) 54 _ <- evaluate (I# (testMemset8_13 1#)) 55 _ <- evaluate (I# (testMemset8_14 1#)) 56 _ <- evaluate (I# (testMemset8_15 1#)) 57 _ <- evaluate (I# (testMemset8_16 1#)) 58 _ <- evaluate (I# (testMemset4_0 1#)) 59 _ <- evaluate (I# (testMemset4_4 1#)) 60 _ <- evaluate (I# (testMemset4_5 1#)) 61 _ <- evaluate (I# (testMemset4_6 1#)) 62 _ <- evaluate (I# (testMemset4_7 1#)) 63 _ <- evaluate (I# (testMemset4_8 1#)) 64 65 _ <- evaluate (I# (testMemcpy8_0 1#)) 66 _ <- evaluate (I# (testMemcpy8_8 1#)) 67 _ <- evaluate (I# (testMemcpy8_9 1#)) 68 _ <- evaluate (I# (testMemcpy8_10 1#)) 69 _ <- evaluate (I# (testMemcpy8_11 1#)) 70 _ <- evaluate (I# (testMemcpy8_12 1#)) 71 _ <- evaluate (I# (testMemcpy8_13 1#)) 72 _ <- evaluate (I# (testMemcpy8_14 1#)) 73 _ <- evaluate (I# (testMemcpy8_15 1#)) 74 _ <- evaluate (I# (testMemcpy8_16 1#)) 75 _ <- evaluate (I# (testMemcpy4_0 1#)) 76 _ <- evaluate (I# (testMemcpy4_4 1#)) 77 _ <- evaluate (I# (testMemcpy4_5 1#)) 78 _ <- evaluate (I# (testMemcpy4_6 1#)) 79 _ <- evaluate (I# (testMemcpy4_7 1#)) 80 _ <- evaluate (I# (testMemcpy4_8 1#)) 13 81 putStrLn "Test Passed!" 14 82 return () 15 83 -
tests/ghc-regress/codeGen/should_run/cgrun069_cmm.cmm
diff --git a/tests/ghc-regress/codeGen/should_run/cgrun069_cmm.cmm b/tests/ghc-regress/codeGen/should_run/cgrun069_cmm.cmm index 2239697..9953181 100644
a b 3 3 // Test that the Memcpy, Memmove, Memset GHC intrinsic functions 4 4 // are working correctly. 5 5 6 section "rodata" { memsetErr : bits8[] "Memset Error Occured\n"; }7 section "rodata" { memcpyErr : bits8[] "Memcpy Error Occured\n"; }6 section "rodata" { memsetErr : bits8[] "Memset Error - align: %d size: %d\n"; } 7 section "rodata" { memcpyErr : bits8[] "Memcpy Error - align: %d size: %d\n"; } 8 8 section "rodata" { memmoveErr : bits8[] "Memmove Error Occured\n"; } 9 9 10 10 memintrinTest … … 42 42 off = off + 1; 43 43 goto while1; 44 44 45 while1_end: 45 while1_end: 46 46 47 47 // Test memcpy 48 48 prim %memcpy(dst "ptr", src "ptr", size, alignV) []; … … 62 62 off = off + 1; 63 63 goto while2; 64 64 65 while2_end: 65 while2_end: 66 66 67 67 // Test memove 68 68 set = 8; … … 89 89 off = off + 1; 90 90 goto while3; 91 91 92 while3_end: 92 while3_end: 93 93 94 94 foreign "C" free(src); 95 95 foreign "C" free(dst); … … 97 97 jump %ENTRY_CODE(Sp(0)); 98 98 } 99 99 100 // --------------------------------------------------------------------- 101 // Tests for unrolling 102 103 // We generate code for each configuration of alignment and size rather 104 // than looping over the possible alignments/sizes as the alignment and 105 // size needs to be statically known for unrolling to happen. 106 107 // Below we need both 'set' and 'set8' as memset takes a word for 108 // historical reasons but really its a bits8. We check that setting 109 // has ben done correctly at the bits8 level, so need bits8 version 110 // for checking. 111 #define TEST_MEMSET(ALIGN,SIZE) \ 112 W_ size, src, dst, off, alignV, set; \ 113 bits8 set8; \ 114 set = 4; \ 115 set8 = 4::bits8; \ 116 size = SIZE; \ 117 alignV = ALIGN; \ 118 ("ptr" src) = foreign "C" malloc(size); \ 119 ("ptr" dst) = foreign "C" malloc(size); \ 120 prim %memset(src "ptr", set, size, alignV) []; \ 121 off = 0; \ 122 loop: \ 123 if (off == size) { \ 124 goto loop_end; \ 125 } \ 126 if (bits8[src + off] != set8) { \ 127 foreign "C" printf(memsetErr "ptr", ALIGN, SIZE) []; \ 128 goto loop_end; \ 129 } \ 130 off = off + 1; \ 131 goto loop; \ 132 loop_end: \ 133 foreign "C" free(src); \ 134 foreign "C" free(dst); \ 135 jump %ENTRY_CODE(Sp(0)); 136 137 // This is not exactly beutiful but we need the separate functions to 138 // avoid collisions between labels. 139 // 140 // The specific tests are selected with knowledge of the implementation 141 // in mind in order to try to cover all branches and interesting corner 142 // cases. 143 144 testMemset8_0 { TEST_MEMSET(8,0); } 145 testMemset8_8 { TEST_MEMSET(8,8); } 146 testMemset8_9 { TEST_MEMSET(8,9); } 147 testMemset8_10 { TEST_MEMSET(8,10); } 148 testMemset8_11 { TEST_MEMSET(8,11); } 149 testMemset8_12 { TEST_MEMSET(8,12); } 150 testMemset8_13 { TEST_MEMSET(8,13); } 151 testMemset8_14 { TEST_MEMSET(8,14); } 152 testMemset8_15 { TEST_MEMSET(8,15); } 153 testMemset8_16 { TEST_MEMSET(8,16); } 154 155 testMemset4_0 { TEST_MEMSET(4,0); } 156 testMemset4_4 { TEST_MEMSET(4,4); } 157 testMemset4_5 { TEST_MEMSET(4,5); } 158 testMemset4_6 { TEST_MEMSET(4,6); } 159 testMemset4_7 { TEST_MEMSET(4,7); } 160 testMemset4_8 { TEST_MEMSET(4,8); } 161 162 #define TEST_MEMCPY(ALIGN,SIZE) \ 163 W_ size, src, dst, off, alignV; \ 164 size = SIZE; \ 165 alignV = ALIGN; \ 166 ("ptr" src) = foreign "C" malloc(size); \ 167 ("ptr" dst) = foreign "C" malloc(size); \ 168 off = 0; \ 169 init: \ 170 if (off == size) { \ 171 goto init_end; \ 172 } \ 173 bits8[src + off] = 0xaa; \ 174 off = off + 1; \ 175 goto init; \ 176 init_end: \ 177 prim %memcpy(dst "ptr", src "ptr", size, alignV) []; \ 178 off = 0; \ 179 loop: \ 180 if (off == size) { \ 181 goto loop_end; \ 182 } \ 183 if (bits8[dst + off] != bits8[src + off]) { \ 184 foreign "C" printf(memcpyErr "ptr", ALIGN, SIZE) []; \ 185 goto loop_end; \ 186 } \ 187 off = off + 1; \ 188 goto loop; \ 189 loop_end: \ 190 foreign "C" free(src); \ 191 foreign "C" free(dst); \ 192 jump %ENTRY_CODE(Sp(0)); 193 194 testMemcpy8_0 { TEST_MEMCPY(8,0); } 195 testMemcpy8_8 { TEST_MEMCPY(8,8); } 196 testMemcpy8_9 { TEST_MEMCPY(8,9); } 197 testMemcpy8_10 { TEST_MEMCPY(8,10); } 198 testMemcpy8_11 { TEST_MEMCPY(8,11); } 199 testMemcpy8_12 { TEST_MEMCPY(8,12); } 200 testMemcpy8_13 { TEST_MEMCPY(8,13); } 201 testMemcpy8_14 { TEST_MEMCPY(8,14); } 202 testMemcpy8_15 { TEST_MEMCPY(8,15); } 203 testMemcpy8_16 { TEST_MEMCPY(8,16); } 204 205 testMemcpy4_0 { TEST_MEMCPY(4,0); } 206 testMemcpy4_4 { TEST_MEMCPY(4,4); } 207 testMemcpy4_5 { TEST_MEMCPY(4,5); } 208 testMemcpy4_6 { TEST_MEMCPY(4,6); } 209 testMemcpy4_7 { TEST_MEMCPY(4,7); } 210 testMemcpy4_8 { TEST_MEMCPY(4,8); }
