Files
clang-p2996/llvm/test/Transforms/JumpThreading/codesize-loop.ll
Nikita Popov 6f0ca6fd23 [JumpThreading] Insert freeze when unfolding select
JumpThreading may convert selects into branch instructions,
in which case the condition needs to be frozen (as branch on
poison is immediate undefined behavior, unlike select on poison).

The necessary code for this is already in place, this just enables
the option.

Differential Revision: https://reviews.llvm.org/D125869
2022-05-21 11:24:27 +02:00

157 lines
8.3 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -jump-threading -S %s -o - | FileCheck %s --check-prefix=DEFAULT
; RUN: opt -jump-threading -S -jump-threading-threshold=6 %s -o - | FileCheck %s --check-prefix=OVERIDE
@.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
define i32 @test_minsize(i32 %argc, i8** nocapture readonly %argv) local_unnamed_addr #0 {
; DEFAULT-LABEL: @test_minsize(
; DEFAULT-NEXT: entry:
; DEFAULT-NEXT: [[CMP:%.*]] = icmp eq i32 [[ARGC:%.*]], 2
; DEFAULT-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_END:%.*]]
; DEFAULT: cond.true:
; DEFAULT-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8*, i8** [[ARGV:%.*]], i32 1
; DEFAULT-NEXT: [[TMP0:%.*]] = load i8*, i8** [[ARRAYIDX]], align 4
; DEFAULT-NEXT: [[CALL:%.*]] = tail call i32 @atoi(i8* [[TMP0]])
; DEFAULT-NEXT: br label [[COND_END]]
; DEFAULT: cond.end:
; DEFAULT-NEXT: [[COND:%.*]] = phi i32 [ [[CALL]], [[COND_TRUE]] ], [ 46, [[ENTRY:%.*]] ]
; DEFAULT-NEXT: [[TMP1:%.*]] = mul i32 [[COND]], [[COND]]
; DEFAULT-NEXT: [[TMP2:%.*]] = mul i32 [[TMP1]], [[TMP1]]
; DEFAULT-NEXT: [[TMP3:%.*]] = mul i32 [[COND]], [[TMP2]]
; DEFAULT-NEXT: [[TMP4:%.*]] = icmp sgt i32 [[COND]], 0
; DEFAULT-NEXT: [[COND_FR:%.*]] = freeze i1 [[TMP4]]
; DEFAULT-NEXT: br i1 [[COND_FR]], label [[TMP5:%.*]], label [[TMP6:%.*]]
; DEFAULT: 5:
; DEFAULT-NEXT: br label [[TMP6]]
; DEFAULT: 6:
; DEFAULT-NEXT: [[TMP7:%.*]] = phi i32 [ [[COND]], [[TMP5]] ], [ 0, [[COND_END]] ]
; DEFAULT-NEXT: [[TMP8:%.*]] = mul i32 [[TMP3]], [[TMP7]]
; DEFAULT-NEXT: [[CALL33:%.*]] = tail call i32 (i8*, ...) @printf(i8* nonnull dereferenceable(1) getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32 [[TMP8]])
; DEFAULT-NEXT: ret i32 0
;
; OVERIDE-LABEL: @test_minsize(
; OVERIDE-NEXT: entry:
; OVERIDE-NEXT: [[CMP:%.*]] = icmp eq i32 [[ARGC:%.*]], 2
; OVERIDE-NEXT: br i1 [[CMP]], label [[COND_END:%.*]], label [[COND_END_THREAD:%.*]]
; OVERIDE: cond.end:
; OVERIDE-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8*, i8** [[ARGV:%.*]], i32 1
; OVERIDE-NEXT: [[TMP0:%.*]] = load i8*, i8** [[ARRAYIDX]], align 4
; OVERIDE-NEXT: [[CALL:%.*]] = tail call i32 @atoi(i8* [[TMP0]])
; OVERIDE-NEXT: [[TMP1:%.*]] = mul i32 [[CALL]], [[CALL]]
; OVERIDE-NEXT: [[TMP2:%.*]] = mul i32 [[TMP1]], [[TMP1]]
; OVERIDE-NEXT: [[TMP3:%.*]] = mul i32 [[CALL]], [[TMP2]]
; OVERIDE-NEXT: [[TMP4:%.*]] = icmp sgt i32 [[CALL]], 0
; OVERIDE-NEXT: [[COND_FR:%.*]] = freeze i1 [[TMP4]]
; OVERIDE-NEXT: br i1 [[COND_FR]], label [[COND_END_THREAD]], label [[TMP6:%.*]]
; OVERIDE: cond.end.thread:
; OVERIDE-NEXT: [[TMP5:%.*]] = phi i32 [ [[TMP3]], [[COND_END]] ], [ 205962976, [[ENTRY:%.*]] ]
; OVERIDE-NEXT: [[COND3:%.*]] = phi i32 [ [[CALL]], [[COND_END]] ], [ 46, [[ENTRY]] ]
; OVERIDE-NEXT: br label [[TMP6]]
; OVERIDE: 6:
; OVERIDE-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP5]], [[COND_END_THREAD]] ], [ [[TMP3]], [[COND_END]] ]
; OVERIDE-NEXT: [[TMP8:%.*]] = phi i32 [ [[COND3]], [[COND_END_THREAD]] ], [ 0, [[COND_END]] ]
; OVERIDE-NEXT: [[TMP9:%.*]] = mul i32 [[TMP7]], [[TMP8]]
; OVERIDE-NEXT: [[CALL33:%.*]] = tail call i32 (i8*, ...) @printf(i8* nonnull dereferenceable(1) getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32 [[TMP9]])
; OVERIDE-NEXT: ret i32 0
;
entry:
%cmp = icmp eq i32 %argc, 2
br i1 %cmp, label %cond.true, label %cond.end
cond.true: ; preds = %entry
%arrayidx = getelementptr inbounds i8*, i8** %argv, i32 1
%0 = load i8*, i8** %arrayidx, align 4
%call = tail call i32 @atoi(i8* %0)
br label %cond.end
cond.end: ; preds = %entry, %cond.true
%cond = phi i32 [ %call, %cond.true ], [ 46, %entry ]
%1 = mul i32 %cond, %cond
%2 = mul i32 %1, %1
%3 = mul i32 %cond, %2
%4 = icmp sgt i32 %cond, 0
%spec.select = select i1 %4, i32 %cond, i32 0
%5 = mul i32 %3, %spec.select
%call33 = tail call i32 (i8*, ...) @printf(i8* nonnull dereferenceable(1) getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32 %5) #4
ret i32 0
}
define i32 @test_optsize(i32 %argc, i8** nocapture readonly %argv) local_unnamed_addr #1 {
; DEFAULT-LABEL: @test_optsize(
; DEFAULT-NEXT: entry:
; DEFAULT-NEXT: [[CMP:%.*]] = icmp eq i32 [[ARGC:%.*]], 2
; DEFAULT-NEXT: br i1 [[CMP]], label [[COND_END:%.*]], label [[COND_END_THREAD:%.*]]
; DEFAULT: cond.end:
; DEFAULT-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8*, i8** [[ARGV:%.*]], i32 1
; DEFAULT-NEXT: [[TMP0:%.*]] = load i8*, i8** [[ARRAYIDX]], align 4
; DEFAULT-NEXT: [[CALL:%.*]] = tail call i32 @atoi(i8* [[TMP0]])
; DEFAULT-NEXT: [[TMP1:%.*]] = mul i32 [[CALL]], [[CALL]]
; DEFAULT-NEXT: [[TMP2:%.*]] = mul i32 [[TMP1]], [[TMP1]]
; DEFAULT-NEXT: [[TMP3:%.*]] = mul i32 [[CALL]], [[TMP2]]
; DEFAULT-NEXT: [[TMP4:%.*]] = icmp sgt i32 [[CALL]], 0
; DEFAULT-NEXT: [[COND_FR:%.*]] = freeze i1 [[TMP4]]
; DEFAULT-NEXT: br i1 [[COND_FR]], label [[COND_END_THREAD]], label [[TMP6:%.*]]
; DEFAULT: cond.end.thread:
; DEFAULT-NEXT: [[TMP5:%.*]] = phi i32 [ [[TMP3]], [[COND_END]] ], [ 205962976, [[ENTRY:%.*]] ]
; DEFAULT-NEXT: [[COND3:%.*]] = phi i32 [ [[CALL]], [[COND_END]] ], [ 46, [[ENTRY]] ]
; DEFAULT-NEXT: br label [[TMP6]]
; DEFAULT: 6:
; DEFAULT-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP5]], [[COND_END_THREAD]] ], [ [[TMP3]], [[COND_END]] ]
; DEFAULT-NEXT: [[TMP8:%.*]] = phi i32 [ [[COND3]], [[COND_END_THREAD]] ], [ 0, [[COND_END]] ]
; DEFAULT-NEXT: [[TMP9:%.*]] = mul i32 [[TMP7]], [[TMP8]]
; DEFAULT-NEXT: [[CALL33:%.*]] = tail call i32 (i8*, ...) @printf(i8* nonnull dereferenceable(1) getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32 [[TMP9]])
; DEFAULT-NEXT: ret i32 0
;
; OVERIDE-LABEL: @test_optsize(
; OVERIDE-NEXT: entry:
; OVERIDE-NEXT: [[CMP:%.*]] = icmp eq i32 [[ARGC:%.*]], 2
; OVERIDE-NEXT: br i1 [[CMP]], label [[COND_END:%.*]], label [[COND_END_THREAD:%.*]]
; OVERIDE: cond.end:
; OVERIDE-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8*, i8** [[ARGV:%.*]], i32 1
; OVERIDE-NEXT: [[TMP0:%.*]] = load i8*, i8** [[ARRAYIDX]], align 4
; OVERIDE-NEXT: [[CALL:%.*]] = tail call i32 @atoi(i8* [[TMP0]])
; OVERIDE-NEXT: [[TMP1:%.*]] = mul i32 [[CALL]], [[CALL]]
; OVERIDE-NEXT: [[TMP2:%.*]] = mul i32 [[TMP1]], [[TMP1]]
; OVERIDE-NEXT: [[TMP3:%.*]] = mul i32 [[CALL]], [[TMP2]]
; OVERIDE-NEXT: [[TMP4:%.*]] = icmp sgt i32 [[CALL]], 0
; OVERIDE-NEXT: [[COND_FR:%.*]] = freeze i1 [[TMP4]]
; OVERIDE-NEXT: br i1 [[COND_FR]], label [[COND_END_THREAD]], label [[TMP6:%.*]]
; OVERIDE: cond.end.thread:
; OVERIDE-NEXT: [[TMP5:%.*]] = phi i32 [ [[TMP3]], [[COND_END]] ], [ 205962976, [[ENTRY:%.*]] ]
; OVERIDE-NEXT: [[COND3:%.*]] = phi i32 [ [[CALL]], [[COND_END]] ], [ 46, [[ENTRY]] ]
; OVERIDE-NEXT: br label [[TMP6]]
; OVERIDE: 6:
; OVERIDE-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP5]], [[COND_END_THREAD]] ], [ [[TMP3]], [[COND_END]] ]
; OVERIDE-NEXT: [[TMP8:%.*]] = phi i32 [ [[COND3]], [[COND_END_THREAD]] ], [ 0, [[COND_END]] ]
; OVERIDE-NEXT: [[TMP9:%.*]] = mul i32 [[TMP7]], [[TMP8]]
; OVERIDE-NEXT: [[CALL33:%.*]] = tail call i32 (i8*, ...) @printf(i8* nonnull dereferenceable(1) getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32 [[TMP9]])
; OVERIDE-NEXT: ret i32 0
;
entry:
%cmp = icmp eq i32 %argc, 2
br i1 %cmp, label %cond.true, label %cond.end
cond.true: ; preds = %entry
%arrayidx = getelementptr inbounds i8*, i8** %argv, i32 1
%0 = load i8*, i8** %arrayidx, align 4
%call = tail call i32 @atoi(i8* %0)
br label %cond.end
cond.end: ; preds = %entry, %cond.true
%cond = phi i32 [ %call, %cond.true ], [ 46, %entry ]
%1 = mul i32 %cond, %cond
%2 = mul i32 %1, %1
%3 = mul i32 %cond, %2
%4 = icmp sgt i32 %cond, 0
%spec.select = select i1 %4, i32 %cond, i32 0
%5 = mul i32 %3, %spec.select
%call33 = tail call i32 (i8*, ...) @printf(i8* nonnull dereferenceable(1) getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32 %5) #4
ret i32 0
}
declare i32 @atoi(i8* nocapture) local_unnamed_addr
declare i32 @printf(i8* nocapture readonly, ...) local_unnamed_addr
attributes #0 = { minsize optsize }
attributes #1 = { optsize }