Skip to content

Commit 1c5f82b

Browse files
author
git apple-llvm automerger
committed
Merge commit '6c4f37a0eb46' from apple/stable/20200714 into swift/main
2 parents 0083fd8 + 6c4f37a commit 1c5f82b

File tree

2 files changed

+197
-6
lines changed

2 files changed

+197
-6
lines changed

llvm/lib/Transforms/Scalar/ConstraintElimination.cpp

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,29 @@ static SmallVector<std::pair<int64_t, Value *>, 4> decompose(Value *V) {
5050
return {{CI->getSExtValue(), nullptr}};
5151
}
5252
auto *GEP = dyn_cast<GetElementPtrInst>(V);
53-
if (GEP && GEP->getNumOperands() == 2 &&
54-
isa<ConstantInt>(GEP->getOperand(GEP->getNumOperands() - 1))) {
55-
return {{cast<ConstantInt>(GEP->getOperand(GEP->getNumOperands() - 1))
56-
->getSExtValue(),
57-
nullptr},
58-
{1, GEP->getPointerOperand()}};
53+
if (GEP && GEP->getNumOperands() == 2) {
54+
if (isa<ConstantInt>(GEP->getOperand(GEP->getNumOperands() - 1))) {
55+
return {{cast<ConstantInt>(GEP->getOperand(GEP->getNumOperands() - 1))
56+
->getSExtValue(),
57+
nullptr},
58+
{1, GEP->getPointerOperand()}};
59+
}
60+
Value *Op0;
61+
ConstantInt *CI;
62+
if (match(GEP->getOperand(GEP->getNumOperands() - 1),
63+
m_NUWShl(m_Value(Op0), m_ConstantInt(CI))))
64+
return {{0, nullptr},
65+
{1, GEP->getPointerOperand()},
66+
{pow(2, CI->getSExtValue()), Op0}};
67+
if (match(GEP->getOperand(GEP->getNumOperands() - 1),
68+
m_ZExt(m_NUWShl(m_Value(Op0), m_ConstantInt(CI)))))
69+
return {{0, nullptr},
70+
{1, GEP->getPointerOperand()},
71+
{pow(2, CI->getSExtValue()), Op0}};
72+
73+
return {{0, nullptr},
74+
{1, GEP->getPointerOperand()},
75+
{1, GEP->getOperand(GEP->getNumOperands() - 1)}};
5976
}
6077

6178
Value *Op0;

llvm/test/Transforms/ConstraintElimination/geps.ll

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,180 @@ if.end: ; preds = %entry
327327
ret void
328328
}
329329

330+
define void @test.not.uge.uge.nonconst(i8* %start, i8* %low, i8* %high, i64 %off) {
331+
; CHECK-LABEL: @test.not.uge.uge.nonconst(
332+
; CHECK-NEXT: entry:
333+
; CHECK-NEXT: [[ADD_PTR_I:%.*]] = getelementptr inbounds i8, i8* [[START:%.*]], i64 [[OFF:%.*]]
334+
; CHECK-NEXT: [[C_1:%.*]] = icmp uge i8* [[ADD_PTR_I]], [[HIGH:%.*]]
335+
; CHECK-NEXT: br i1 [[C_1]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
336+
; CHECK: if.then:
337+
; CHECK-NEXT: [[START_OFF_2:%.*]] = getelementptr inbounds i8, i8* [[START]], i64 [[OFF]]
338+
; CHECK-NEXT: [[T_0:%.*]] = icmp uge i8* [[START_OFF_2]], [[HIGH]]
339+
; CHECK-NEXT: call void @use(i1 true)
340+
; CHECK-NEXT: ret void
341+
; CHECK: if.end:
342+
; CHECK-NEXT: [[START_1:%.*]] = getelementptr inbounds i8, i8* [[START]], i64 1
343+
; CHECK-NEXT: [[C_0:%.*]] = icmp uge i8* [[START_1]], [[HIGH]]
344+
; CHECK-NEXT: call void @use(i1 [[C_0]])
345+
; CHECK-NEXT: [[START_OFF:%.*]] = getelementptr inbounds i8, i8* [[START]], i64 [[OFF]]
346+
; CHECK-NEXT: [[F_0:%.*]] = icmp uge i8* [[START_OFF]], [[HIGH]]
347+
; CHECK-NEXT: call void @use(i1 false)
348+
; CHECK-NEXT: ret void
349+
;
350+
entry:
351+
%add.ptr.i = getelementptr inbounds i8, i8* %start, i64 %off
352+
%c.1 = icmp uge i8* %add.ptr.i, %high
353+
br i1 %c.1, label %if.then, label %if.end
354+
355+
if.then: ; preds = %entry
356+
%start.off.2 = getelementptr inbounds i8, i8* %start, i64 %off
357+
%t.0 = icmp uge i8* %start.off.2, %high
358+
call void @use(i1 %t.0)
359+
360+
ret void
361+
362+
if.end: ; preds = %entry
363+
%start.1 = getelementptr inbounds i8, i8* %start, i64 1
364+
%c.0 = icmp uge i8* %start.1, %high
365+
call void @use(i1 %c.0)
366+
367+
%start.off = getelementptr inbounds i8, i8* %start, i64 %off
368+
%f.0 = icmp uge i8* %start.off, %high
369+
call void @use(i1 %f.0)
370+
371+
ret void
372+
}
373+
374+
; Test which requires decomposing GEP %ptr, SHL().
375+
define void @test.ult.gep.shl(i32* readonly %src, i32* readnone %max, i32 %idx, i32 %j) {
376+
; CHECK-LABEL: @test.ult.gep.shl(
377+
; CHECK-NEXT: check.0.min:
378+
; CHECK-NEXT: [[ADD_10:%.*]] = getelementptr inbounds i32, i32* [[SRC:%.*]], i32 10
379+
; CHECK-NEXT: [[C_ADD_10_MAX:%.*]] = icmp ugt i32* [[ADD_10]], [[MAX:%.*]]
380+
; CHECK-NEXT: br i1 [[C_ADD_10_MAX]], label [[TRAP:%.*]], label [[CHECK_IDX:%.*]]
381+
; CHECK: trap:
382+
; CHECK-NEXT: ret void
383+
; CHECK: check.idx:
384+
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[IDX:%.*]], 5
385+
; CHECK-NEXT: br i1 [[CMP]], label [[CHECK_MAX:%.*]], label [[TRAP]]
386+
; CHECK: check.max:
387+
; CHECK-NEXT: [[IDX_SHL_1:%.*]] = shl nuw i32 [[IDX]], 1
388+
; CHECK-NEXT: [[ADD_PTR_SHL_1:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i32 [[IDX_SHL_1]]
389+
; CHECK-NEXT: [[C_MAX_0:%.*]] = icmp ult i32* [[ADD_PTR_SHL_1]], [[MAX]]
390+
; CHECK-NEXT: call void @use(i1 true)
391+
; CHECK-NEXT: [[IDX_SHL_2:%.*]] = shl nuw i32 [[IDX]], 2
392+
; CHECK-NEXT: [[ADD_PTR_SHL_2:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i32 [[IDX_SHL_2]]
393+
; CHECK-NEXT: [[C_MAX_1:%.*]] = icmp ult i32* [[ADD_PTR_SHL_2]], [[MAX]]
394+
; CHECK-NEXT: call void @use(i1 [[C_MAX_1]])
395+
; CHECK-NEXT: [[IDX_SHL_NOT_NUW:%.*]] = shl i32 [[IDX]], 1
396+
; CHECK-NEXT: [[ADD_PTR_SHL_NOT_NUW:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i32 [[IDX_SHL_NOT_NUW]]
397+
; CHECK-NEXT: [[C_MAX_2:%.*]] = icmp ult i32* [[ADD_PTR_SHL_NOT_NUW]], [[MAX]]
398+
; CHECK-NEXT: call void @use(i1 [[C_MAX_2]])
399+
; CHECK-NEXT: [[IDX_SHL_3:%.*]] = shl nuw i32 [[IDX]], 3
400+
; CHECK-NEXT: [[ADD_PTR_SHL_3:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i32 [[IDX_SHL_3]]
401+
; CHECK-NEXT: [[C_MAX_3:%.*]] = icmp ult i32* [[ADD_PTR_SHL_3]], [[MAX]]
402+
; CHECK-NEXT: call void @use(i1 [[C_MAX_3]])
403+
; CHECK-NEXT: ret void
404+
;
405+
check.0.min:
406+
%add.10 = getelementptr inbounds i32, i32* %src, i32 10
407+
%c.add.10.max = icmp ugt i32* %add.10, %max
408+
br i1 %c.add.10.max, label %trap, label %check.idx
409+
410+
trap:
411+
ret void
412+
413+
check.idx: ; preds = %check.0.min
414+
%cmp = icmp ult i32 %idx, 5
415+
br i1 %cmp, label %check.max, label %trap
416+
417+
check.max: ; preds = %check.0.min
418+
%idx.shl.1 = shl nuw i32 %idx, 1
419+
%add.ptr.shl.1 = getelementptr inbounds i32, i32* %src, i32 %idx.shl.1
420+
%c.max.0 = icmp ult i32* %add.ptr.shl.1, %max
421+
call void @use(i1 %c.max.0)
422+
423+
%idx.shl.2 = shl nuw i32 %idx, 2
424+
%add.ptr.shl.2 = getelementptr inbounds i32, i32* %src, i32 %idx.shl.2
425+
%c.max.1 = icmp ult i32* %add.ptr.shl.2, %max
426+
call void @use(i1 %c.max.1)
427+
428+
%idx.shl.not.nuw = shl i32 %idx, 1
429+
%add.ptr.shl.not.nuw = getelementptr inbounds i32, i32* %src, i32 %idx.shl.not.nuw
430+
%c.max.2 = icmp ult i32* %add.ptr.shl.not.nuw, %max
431+
call void @use(i1 %c.max.2)
432+
433+
%idx.shl.3 = shl nuw i32 %idx, 3
434+
%add.ptr.shl.3 = getelementptr inbounds i32, i32* %src, i32 %idx.shl.3
435+
%c.max.3 = icmp ult i32* %add.ptr.shl.3, %max
436+
call void @use(i1 %c.max.3)
437+
438+
ret void
439+
}
440+
441+
; Test which requires decomposing GEP %ptr, ZEXT(SHL()).
442+
define void @test.ult.gep.shl.zext(i32* readonly %src, i32* readnone %max, i32 %idx, i32 %j) {
443+
; CHECK-LABEL: @test.ult.gep.shl.zext(
444+
; CHECK-NEXT: check.0.min:
445+
; CHECK-NEXT: [[ADD_10:%.*]] = getelementptr inbounds i32, i32* [[SRC:%.*]], i32 10
446+
; CHECK-NEXT: [[C_ADD_10_MAX:%.*]] = icmp ugt i32* [[ADD_10]], [[MAX:%.*]]
447+
; CHECK-NEXT: br i1 [[C_ADD_10_MAX]], label [[TRAP:%.*]], label [[CHECK_IDX:%.*]]
448+
; CHECK: trap:
449+
; CHECK-NEXT: ret void
450+
; CHECK: check.idx:
451+
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[IDX:%.*]], 5
452+
; CHECK-NEXT: br i1 [[CMP]], label [[CHECK_MAX:%.*]], label [[TRAP]]
453+
; CHECK: check.max:
454+
; CHECK-NEXT: [[IDX_SHL:%.*]] = shl nuw i32 [[IDX]], 1
455+
; CHECK-NEXT: [[EXT_1:%.*]] = zext i32 [[IDX_SHL]] to i64
456+
; CHECK-NEXT: [[ADD_PTR_SHL:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i64 [[EXT_1]]
457+
; CHECK-NEXT: [[C_MAX_0:%.*]] = icmp ult i32* [[ADD_PTR_SHL]], [[MAX]]
458+
; CHECK-NEXT: call void @use(i1 true)
459+
; CHECK-NEXT: [[IDX_SHL_NOT_NUW:%.*]] = shl i32 [[IDX]], 1
460+
; CHECK-NEXT: [[EXT_2:%.*]] = zext i32 [[IDX_SHL_NOT_NUW]] to i64
461+
; CHECK-NEXT: [[ADD_PTR_SHL_NOT_NUW:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i64 [[EXT_2]]
462+
; CHECK-NEXT: [[C_MAX_1:%.*]] = icmp ult i32* [[ADD_PTR_SHL_NOT_NUW]], [[MAX]]
463+
; CHECK-NEXT: call void @use(i1 [[C_MAX_1]])
464+
; CHECK-NEXT: [[IDX_SHL_3:%.*]] = shl nuw i32 [[IDX]], 2
465+
; CHECK-NEXT: [[EXT_3:%.*]] = zext i32 [[IDX_SHL_3]] to i64
466+
; CHECK-NEXT: [[ADD_PTR_SHL_3:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i64 [[EXT_3]]
467+
; CHECK-NEXT: [[C_MAX_2:%.*]] = icmp ult i32* [[ADD_PTR_SHL_3]], [[MAX]]
468+
; CHECK-NEXT: call void @use(i1 [[C_MAX_2]])
469+
; CHECK-NEXT: ret void
470+
;
471+
check.0.min:
472+
%add.10 = getelementptr inbounds i32, i32* %src, i32 10
473+
%c.add.10.max = icmp ugt i32* %add.10, %max
474+
br i1 %c.add.10.max, label %trap, label %check.idx
475+
476+
trap:
477+
ret void
478+
479+
check.idx: ; preds = %check.0.min
480+
%cmp = icmp ult i32 %idx, 5
481+
br i1 %cmp, label %check.max, label %trap
482+
483+
check.max: ; preds = %check.0.min
484+
%idx.shl = shl nuw i32 %idx, 1
485+
%ext.1 = zext i32 %idx.shl to i64
486+
%add.ptr.shl = getelementptr inbounds i32, i32* %src, i64 %ext.1
487+
%c.max.0 = icmp ult i32* %add.ptr.shl, %max
488+
call void @use(i1 %c.max.0)
489+
490+
%idx.shl.not.nuw = shl i32 %idx, 1
491+
%ext.2 = zext i32 %idx.shl.not.nuw to i64
492+
%add.ptr.shl.not.nuw = getelementptr inbounds i32, i32* %src, i64 %ext.2
493+
%c.max.1 = icmp ult i32* %add.ptr.shl.not.nuw, %max
494+
call void @use(i1 %c.max.1)
495+
496+
%idx.shl.3 = shl nuw i32 %idx, 2
497+
%ext.3 = zext i32 %idx.shl.3 to i64
498+
%add.ptr.shl.3 = getelementptr inbounds i32, i32* %src, i64 %ext.3
499+
%c.max.2 = icmp ult i32* %add.ptr.shl.3, %max
500+
call void @use(i1 %c.max.2)
501+
502+
ret void
503+
}
330504

331505
declare void @use(i1)
332506
declare void @llvm.trap()

0 commit comments

Comments
 (0)