Skip to content

Commit 41f4b64

Browse files
committedMay 22, 2018
[InstCombine] Calloc-ed strings optimizations
Summary: Example cases: strlen(calloc(...)) -> 0 Reviewers: efriedma, bkramer Reviewed By: bkramer Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D47059 llvm-svn: 332990
1 parent 1ff6b27 commit 41f4b64

File tree

5 files changed

+110
-19
lines changed

5 files changed

+110
-19
lines changed
 

‎llvm/include/llvm/Analysis/ValueTracking.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ class Value;
274274

275275
/// If we can compute the length of the string pointed to by the specified
276276
/// pointer, return 'len+1'. If we can't, return 0.
277-
uint64_t GetStringLength(const Value *V, unsigned CharSize = 8);
277+
uint64_t GetStringLength(const Value *V, const TargetLibraryInfo *TLI, unsigned CharSize = 8);
278278

279279
/// This method strips off any GEP address adjustments and pointer casts from
280280
/// the specified value, returning the original object being addressed. Note

‎llvm/lib/Analysis/MemoryBuiltins.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -589,7 +589,7 @@ SizeOffsetType ObjectSizeOffsetVisitor::visitCallSite(CallSite CS) {
589589

590590
// Handle strdup-like functions separately.
591591
if (FnData->AllocTy == StrDupLike) {
592-
APInt Size(IntTyBits, GetStringLength(CS.getArgument(0)));
592+
APInt Size(IntTyBits, GetStringLength(CS.getArgument(0), TLI));
593593
if (!Size)
594594
return unknown();
595595

‎llvm/lib/Analysis/ValueTracking.cpp

+31-2
Original file line numberDiff line numberDiff line change
@@ -3372,10 +3372,39 @@ static uint64_t GetStringLengthH(const Value *V,
33723372
return NullIndex + 1;
33733373
}
33743374

3375+
static bool isStringFromCalloc(const Value *Str, const TargetLibraryInfo *TLI) {
3376+
const CallInst *Calloc = dyn_cast<CallInst>(Str);
3377+
if (!Calloc)
3378+
return false;
3379+
3380+
const Function *InnerCallee = Calloc->getCalledFunction();
3381+
if (!InnerCallee)
3382+
return false;
3383+
3384+
LibFunc Func;
3385+
if (!TLI->getLibFunc(*InnerCallee, Func) || !TLI->has(Func) ||
3386+
Func != LibFunc_calloc)
3387+
return false;
3388+
3389+
const ConstantInt *N = dyn_cast<ConstantInt>(Calloc->getOperand(0));
3390+
const ConstantInt *Size = dyn_cast<ConstantInt>(Calloc->getOperand(1));
3391+
3392+
if (!N || !Size)
3393+
return false;
3394+
3395+
if (N->isNullValue() || Size->isNullValue())
3396+
return false;
3397+
3398+
return true;
3399+
}
3400+
33753401
/// If we can compute the length of the string pointed to by
33763402
/// the specified pointer, return 'len+1'. If we can't, return 0.
3377-
uint64_t llvm::GetStringLength(const Value *V, unsigned CharSize) {
3378-
if (!V->getType()->isPointerTy()) return 0;
3403+
uint64_t llvm::GetStringLength(const Value *V, const TargetLibraryInfo *TLI, unsigned CharSize) {
3404+
if (!V->getType()->isPointerTy())
3405+
return 0;
3406+
if (isStringFromCalloc(V, TLI))
3407+
return 1;
33793408

33803409
SmallPtrSet<const PHINode*, 32> PHIs;
33813410
uint64_t Len = GetStringLengthH(V, PHIs, CharSize);

‎llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp

+15-15
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ Value *LibCallSimplifier::optimizeStrCat(CallInst *CI, IRBuilder<> &B) {
160160
Value *Src = CI->getArgOperand(1);
161161

162162
// See if we can get the length of the input string.
163-
uint64_t Len = GetStringLength(Src);
163+
uint64_t Len = GetStringLength(Src, TLI);
164164
if (Len == 0)
165165
return nullptr;
166166
--Len; // Unbias length.
@@ -205,7 +205,7 @@ Value *LibCallSimplifier::optimizeStrNCat(CallInst *CI, IRBuilder<> &B) {
205205
return nullptr;
206206

207207
// See if we can get the length of the input string.
208-
uint64_t SrcLen = GetStringLength(Src);
208+
uint64_t SrcLen = GetStringLength(Src, TLI);
209209
if (SrcLen == 0)
210210
return nullptr;
211211
--SrcLen; // Unbias length.
@@ -234,7 +234,7 @@ Value *LibCallSimplifier::optimizeStrChr(CallInst *CI, IRBuilder<> &B) {
234234
// of the input string and turn this into memchr.
235235
ConstantInt *CharC = dyn_cast<ConstantInt>(CI->getArgOperand(1));
236236
if (!CharC) {
237-
uint64_t Len = GetStringLength(SrcStr);
237+
uint64_t Len = GetStringLength(SrcStr, TLI);
238238
if (Len == 0 || !FT->getParamType(1)->isIntegerTy(32)) // memchr needs i32.
239239
return nullptr;
240240

@@ -313,8 +313,8 @@ Value *LibCallSimplifier::optimizeStrCmp(CallInst *CI, IRBuilder<> &B) {
313313
return B.CreateZExt(B.CreateLoad(Str1P, "strcmpload"), CI->getType());
314314

315315
// strcmp(P, "x") -> memcmp(P, "x", 2)
316-
uint64_t Len1 = GetStringLength(Str1P);
317-
uint64_t Len2 = GetStringLength(Str2P);
316+
uint64_t Len1 = GetStringLength(Str1P, TLI);
317+
uint64_t Len2 = GetStringLength(Str2P, TLI);
318318
if (Len1 && Len2) {
319319
return emitMemCmp(Str1P, Str2P,
320320
ConstantInt::get(DL.getIntPtrType(CI->getContext()),
@@ -370,7 +370,7 @@ Value *LibCallSimplifier::optimizeStrCpy(CallInst *CI, IRBuilder<> &B) {
370370
return Src;
371371

372372
// See if we can get the length of the input string.
373-
uint64_t Len = GetStringLength(Src);
373+
uint64_t Len = GetStringLength(Src, TLI);
374374
if (Len == 0)
375375
return nullptr;
376376

@@ -390,7 +390,7 @@ Value *LibCallSimplifier::optimizeStpCpy(CallInst *CI, IRBuilder<> &B) {
390390
}
391391

392392
// See if we can get the length of the input string.
393-
uint64_t Len = GetStringLength(Src);
393+
uint64_t Len = GetStringLength(Src, TLI);
394394
if (Len == 0)
395395
return nullptr;
396396

@@ -412,7 +412,7 @@ Value *LibCallSimplifier::optimizeStrNCpy(CallInst *CI, IRBuilder<> &B) {
412412
Value *LenOp = CI->getArgOperand(2);
413413

414414
// See if we can get the length of the input string.
415-
uint64_t SrcLen = GetStringLength(Src);
415+
uint64_t SrcLen = GetStringLength(Src, TLI);
416416
if (SrcLen == 0)
417417
return nullptr;
418418
--SrcLen;
@@ -448,7 +448,7 @@ Value *LibCallSimplifier::optimizeStringLength(CallInst *CI, IRBuilder<> &B,
448448
Value *Src = CI->getArgOperand(0);
449449

450450
// Constant folding: strlen("xyz") -> 3
451-
if (uint64_t Len = GetStringLength(Src, CharSize))
451+
if (uint64_t Len = GetStringLength(Src, TLI, CharSize))
452452
return ConstantInt::get(CI->getType(), Len - 1);
453453

454454
// If s is a constant pointer pointing to a string literal, we can fold
@@ -512,8 +512,8 @@ Value *LibCallSimplifier::optimizeStringLength(CallInst *CI, IRBuilder<> &B,
512512

513513
// strlen(x?"foo":"bars") --> x ? 3 : 4
514514
if (SelectInst *SI = dyn_cast<SelectInst>(Src)) {
515-
uint64_t LenTrue = GetStringLength(SI->getTrueValue(), CharSize);
516-
uint64_t LenFalse = GetStringLength(SI->getFalseValue(), CharSize);
515+
uint64_t LenTrue = GetStringLength(SI->getTrueValue(), TLI, CharSize);
516+
uint64_t LenFalse = GetStringLength(SI->getFalseValue(), TLI, CharSize);
517517
if (LenTrue && LenFalse) {
518518
ORE.emit([&]() {
519519
return OptimizationRemark("instcombine", "simplify-libcalls", CI)
@@ -2142,7 +2142,7 @@ Value *LibCallSimplifier::optimizeFPuts(CallInst *CI, IRBuilder<> &B) {
21422142
}
21432143

21442144
// fputs(s,F) --> fwrite(s,1,strlen(s),F)
2145-
uint64_t Len = GetStringLength(CI->getArgOperand(0));
2145+
uint64_t Len = GetStringLength(CI->getArgOperand(0), TLI);
21462146
if (!Len)
21472147
return nullptr;
21482148

@@ -2565,7 +2565,7 @@ bool FortifiedLibCallSimplifier::isFortifiedCallFoldable(CallInst *CI,
25652565
if (OnlyLowerUnknownSize)
25662566
return false;
25672567
if (isString) {
2568-
uint64_t Len = GetStringLength(CI->getArgOperand(SizeOp));
2568+
uint64_t Len = GetStringLength(CI->getArgOperand(SizeOp), TLI);
25692569
// If the length is 0 we don't know how long it is and so we can't
25702570
// remove the check.
25712571
if (Len == 0)
@@ -2637,7 +2637,7 @@ Value *FortifiedLibCallSimplifier::optimizeStrpCpyChk(CallInst *CI,
26372637
return nullptr;
26382638

26392639
// Maybe we can stil fold __st[rp]cpy_chk to __memcpy_chk.
2640-
uint64_t Len = GetStringLength(Src);
2640+
uint64_t Len = GetStringLength(Src, TLI);
26412641
if (Len == 0)
26422642
return nullptr;
26432643

@@ -2716,4 +2716,4 @@ Value *FortifiedLibCallSimplifier::optimizeCall(CallInst *CI) {
27162716

27172717
FortifiedLibCallSimplifier::FortifiedLibCallSimplifier(
27182718
const TargetLibraryInfo *TLI, bool OnlyLowerUnknownSize)
2719-
: TLI(TLI), OnlyLowerUnknownSize(OnlyLowerUnknownSize) {}
2719+
: TLI(TLI), OnlyLowerUnknownSize(OnlyLowerUnknownSize) {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2+
; RUN: opt < %s -instcombine -S | FileCheck %s
3+
4+
declare i32 @strlen(i8* nocapture)
5+
declare noalias i8* @calloc(i32, i32)
6+
declare noalias i8* @malloc(i32)
7+
8+
define i32 @calloc_strlen() {
9+
; CHECK-LABEL: @calloc_strlen(
10+
; CHECK-NEXT: ret i32 0
11+
;
12+
%call = tail call noalias i8* @calloc(i32 10, i32 1)
13+
%call1 = tail call i32 @strlen(i8* %call)
14+
ret i32 %call1
15+
}
16+
17+
define i32 @calloc_strlen_not_const_nmemb(i32 %n) {
18+
; CHECK-LABEL: @calloc_strlen_not_const_nmemb(
19+
; CHECK-NEXT: [[CALL:%.*]] = tail call noalias i8* @calloc(i32 [[N:%.*]], i32 10)
20+
; CHECK-NEXT: [[CALL1:%.*]] = tail call i32 @strlen(i8* [[CALL]])
21+
; CHECK-NEXT: ret i32 [[CALL1]]
22+
;
23+
%call = tail call noalias i8* @calloc(i32 %n, i32 10)
24+
%call1 = tail call i32 @strlen(i8* %call) #4
25+
ret i32 %call1
26+
}
27+
28+
29+
define i32 @calloc_strlen_not_const_size(i32 %size) {
30+
; CHECK-LABEL: @calloc_strlen_not_const_size(
31+
; CHECK-NEXT: [[CALL:%.*]] = tail call noalias i8* @calloc(i32 1, i32 [[SIZE:%.*]])
32+
; CHECK-NEXT: [[CALL1:%.*]] = tail call i32 @strlen(i8* [[CALL]])
33+
; CHECK-NEXT: ret i32 [[CALL1]]
34+
;
35+
%call = tail call noalias i8* @calloc(i32 1, i32 %size)
36+
%call1 = tail call i32 @strlen(i8* %call) #4
37+
ret i32 %call1
38+
}
39+
40+
41+
define i32 @calloc_strlen_not_const_args(i32 %n, i32 %size) {
42+
; CHECK-LABEL: @calloc_strlen_not_const_args(
43+
; CHECK-NEXT: [[CALL:%.*]] = tail call noalias i8* @calloc(i32 [[N:%.*]], i32 [[SIZE:%.*]])
44+
; CHECK-NEXT: [[CALL1:%.*]] = tail call i32 @strlen(i8* [[CALL]])
45+
; CHECK-NEXT: ret i32 [[CALL1]]
46+
;
47+
%call = tail call noalias i8* @calloc(i32 %n, i32 %size)
48+
%call1 = tail call i32 @strlen(i8* %call) #4
49+
ret i32 %call1
50+
}
51+
52+
53+
define i32 @malloc_strlen() {
54+
; CHECK-LABEL: @malloc_strlen(
55+
; CHECK-NEXT: [[CALL:%.*]] = tail call noalias i8* @malloc(i32 10)
56+
; CHECK-NEXT: [[CALL1:%.*]] = tail call i32 @strlen(i8* [[CALL]])
57+
; CHECK-NEXT: ret i32 [[CALL1]]
58+
;
59+
%call = tail call noalias i8* @malloc(i32 10)
60+
%call1 = tail call i32 @strlen(i8* %call)
61+
ret i32 %call1
62+

0 commit comments

Comments
 (0)
Please sign in to comment.