aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Target/JSBackend/CallHandlers.h12
-rw-r--r--test/CodeGen/JS/mem-intrinsics.ll36
2 files changed, 42 insertions, 6 deletions
diff --git a/lib/Target/JSBackend/CallHandlers.h b/lib/Target/JSBackend/CallHandlers.h
index b8ad71662d..7a2bf4bb86 100644
--- a/lib/Target/JSBackend/CallHandlers.h
+++ b/lib/Target/JSBackend/CallHandlers.h
@@ -255,8 +255,6 @@ DEF_CALL_HANDLER(llvm_nacl_atomic_store_i32, {
#define WRITE_LOOP_MAX 128
DEF_CALL_HANDLER(llvm_memcpy_p0i8_p0i8_i32, {
- Declares.insert("memcpy");
- Redirects["llvm_memcpy_p0i8_p0i8_i32"] = "memcpy";
if (CI) {
ConstantInt *AlignInt = dyn_cast<ConstantInt>(CI->getOperand(3));
if (AlignInt) {
@@ -288,7 +286,7 @@ DEF_CALL_HANDLER(llvm_memcpy_p0i8_p0i8_i32, {
} else {
// emit a loop
UsedVars["dest"] = UsedVars["src"] = UsedVars["stop"] = Type::getInt32Ty(TheModule->getContext())->getTypeID();
- Ret += "dest=" + Dest + "+" + utostr(Pos) + "|0; src=" + Src + "+" + utostr(Pos) + "|0; stop=dest+" + utostr(CurrLen) + "|0; do { " + getHeapAccess("dest", Align) + "=" + getHeapAccess("src", Align) + "|0; dest=dest+" + utostr(Align) + "|0; src=src+" + utostr(Align) + "|0; } while ((dest|0) < (stop|0));";
+ Ret += "dest=" + Dest + "+" + utostr(Pos) + "|0; src=" + Src + "+" + utostr(Pos) + "|0; stop=dest+" + utostr(CurrLen) + "|0; do { " + getHeapAccess("dest", Align) + "=" + getHeapAccess("src", Align) + "|0; dest=dest+" + utostr(Align) + "|0; src=src+" + utostr(Align) + "|0; } while ((dest|0) < (stop|0))";
}
Pos += CurrLen;
Len -= CurrLen;
@@ -299,12 +297,12 @@ DEF_CALL_HANDLER(llvm_memcpy_p0i8_p0i8_i32, {
}
}
}
+ Declares.insert("memcpy");
+ Redirects["llvm_memcpy_p0i8_p0i8_i32"] = "memcpy";
return CH___default__(CI, "_memcpy", 3) + "|0";
})
DEF_CALL_HANDLER(llvm_memset_p0i8_i32, {
- Declares.insert("memset");
- Redirects["llvm_memset_p0i8_i32"] = "memset";
if (CI) {
ConstantInt *AlignInt = dyn_cast<ConstantInt>(CI->getOperand(3));
if (AlignInt) {
@@ -343,7 +341,7 @@ DEF_CALL_HANDLER(llvm_memset_p0i8_i32, {
} else {
// emit a loop
UsedVars["dest"] = UsedVars["stop"] = Type::getInt32Ty(TheModule->getContext())->getTypeID();
- Ret += "dest=" + Dest + "+" + utostr(Pos) + "|0; stop=dest+" + utostr(CurrLen) + "|0; do { " + getHeapAccess("dest", Align) + "=" + utostr(FullVal) + "|0; dest=dest+" + utostr(Align) + "|0; } while ((dest|0) < (stop|0));";
+ Ret += "dest=" + Dest + "+" + utostr(Pos) + "|0; stop=dest+" + utostr(CurrLen) + "|0; do { " + getHeapAccess("dest", Align) + "=" + utostr(FullVal) + "|0; dest=dest+" + utostr(Align) + "|0; } while ((dest|0) < (stop|0))";
}
Pos += CurrLen;
Len -= CurrLen;
@@ -355,6 +353,8 @@ DEF_CALL_HANDLER(llvm_memset_p0i8_i32, {
}
}
}
+ Declares.insert("memset");
+ Redirects["llvm_memset_p0i8_i32"] = "memset";
return CH___default__(CI, "_memset", 3) + "|0";
})
diff --git a/test/CodeGen/JS/mem-intrinsics.ll b/test/CodeGen/JS/mem-intrinsics.ll
new file mode 100644
index 0000000000..2fb834beaa
--- /dev/null
+++ b/test/CodeGen/JS/mem-intrinsics.ll
@@ -0,0 +1,36 @@
+; RUN: llc -march=js < %s | FileCheck %s
+
+; llc should emit small aligned memcpy and memset inline.
+
+; CHECK: test_unrolled_memcpy
+; CHECK: HEAP32[$d+0>>2]=HEAP32[$s+0>>2]|0;HEAP32[$d+4>>2]=HEAP32[$s+4>>2]|0;HEAP32[$d+8>>2]=HEAP32[$s+8>>2]|0;HEAP32[$d+12>>2]=HEAP32[$s+12>>2]|0;HEAP32[$d+16>>2]=HEAP32[$s+16>>2]|0;HEAP32[$d+20>>2]=HEAP32[$s+20>>2]|0;HEAP32[$d+24>>2]=HEAP32[$s+24>>2]|0;HEAP32[$d+28>>2]=HEAP32[$s+28>>2]|0;
+define void @test_unrolled_memcpy(i8* %d, i8* %s) {
+ call void @llvm.memcpy.p0i8.p0i8.i32(i8* %d, i8* %s, i32 32, i32 4, i1 false)
+ ret void
+}
+
+; CHECK: test_loop_memcpy
+; CHECK: dest=$d+0|0; src=$s+0|0; stop=dest+64|0; do { HEAP32[dest>>2]=HEAP32[src>>2]|0; dest=dest+4|0; src=src+4|0; } while ((dest|0) < (stop|0))
+define void @test_loop_memcpy(i8* %d, i8* %s) {
+ call void @llvm.memcpy.p0i8.p0i8.i32(i8* %d, i8* %s, i32 64, i32 4, i1 false)
+ ret void
+}
+
+; CHECK: test_unrolled_memset
+; CHECK: HEAP32[$d+0>>2]=0|0;HEAP32[$d+4>>2]=0|0;HEAP32[$d+8>>2]=0|0;HEAP32[$d+12>>2]=0|0;HEAP32[$d+16>>2]=0|0;HEAP32[$d+20>>2]=0|0;HEAP32[$d+24>>2]=0|0;HEAP32[$d+28>>2]=0|0;
+define void @test_unrolled_memset(i8* %d, i8* %s) {
+ call void @llvm.memset.p0i8.i32(i8* %d, i8 0, i32 32, i32 4, i1 false)
+ ret void
+}
+
+; CHECK: test_loop_memset
+; CHECK: dest=$d+0|0; stop=dest+64|0; do { HEAP32[dest>>2]=0|0; dest=dest+4|0; } while ((dest|0) < (stop|0));
+define void @test_loop_memset(i8* %d, i8* %s) {
+ call void @llvm.memset.p0i8.i32(i8* %d, i8 0, i32 64, i32 4, i1 false)
+ ret void
+}
+
+declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i32, i1) #0
+declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i32, i1) #0
+
+attributes #0 = { nounwind }