Optimize strlen(p) when p is a constant char array
MODIFY
llvm_util/known_fns.cpp
llvm_util/known_fns.cpp
@@ -48,6 +48,17 @@ known_call(llvm::CallInst &i, const llvm::TargetLibraryInfo &TLI,
RETURN_KNOWN(make_unique<UnaryOp>(*ty, value_name(i), *args[0],
UnaryOp::Copy));
case llvm::LibFunc_strlen:
+ if (auto BI = llvm::dyn_cast<llvm::BitCastInst>(i.getArgOperand(0))) {
+ auto G = llvm::dyn_cast<llvm::GlobalVariable>(BI->getOperand(0));
+ if (G && G->isConstant() && G->hasDefinitiveInitializer()) {
+ auto C = llvm::dyn_cast<llvm::ConstantDataArray>(G->getInitializer());
+ if (C && C->isCString()) {
+ RETURN_KNOWN(make_unique<UnaryOp>(*ty, value_name(i),
+ *make_intconst(C->getAsCString().size(), ty->bits()),
+ UnaryOp::Copy));
+ }
+ }
+ }
RETURN_KNOWN(make_unique<Strlen>(*ty, value_name(i), *args[0]));
default:
RETURN_FAIL_KNOWN();

ADD
tests/alive-tv/memory/strlen-long-fail.srctgt.ll
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+
+@c = constant [51 x i8] c"aaaaabbbbbcccccdddddeeeeeaaaaabbbbbcccccdddddeeeee\00"
+
+define i64 @src() {
+ %p = bitcast [51 x i8]* @c to i8*
+ %l = call i64 @strlen(i8* %p)
+ ret i64 %l
+}
+
+define i64 @tgt() {
+ ret i64 51
+}
+
+declare i64 @strlen(i8*)
+; ERROR: Value mismatch

ADD
tests/alive-tv/memory/strlen-long.srctgt.ll
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+
+@c = constant [51 x i8] c"aaaaabbbbbcccccdddddeeeeeaaaaabbbbbcccccdddddeeeee\00"
+
+define i64 @src() {
+ %p = bitcast [51 x i8]* @c to i8*
+ %l = call i64 @strlen(i8* %p)
+ ret i64 %l
+}
+
+define i64 @tgt() {
+ ret i64 50
+}
+
+declare i64 @strlen(i8*)

Optimize strlen(p) when p is a constant char array (#311)