These tests rely on SCEV looking recognizing an "or" with no common bits as an "add". Add the disjoint flag to relevant or instructions in preparation for switching SCEV to use the flag instead of the ValueTracking query. The IR with disjoint flag matches what InstCombine would produce.
128 lines
5.5 KiB
LLVM
128 lines
5.5 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt -passes=loop-idiom < %s -S | FileCheck %s
|
|
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
|
|
|
|
; CHECK: @.memset_pattern = private unnamed_addr constant [4 x i32] [i32 2, i32 2, i32 2, i32 2], align 16
|
|
|
|
target triple = "x86_64-apple-darwin10.0.0"
|
|
|
|
;void test(int *f, unsigned n) {
|
|
; for (unsigned i = 0; i < 2 * n; i += 2) {
|
|
; f[i] = 0;
|
|
; f[i+1] = 0;
|
|
; }
|
|
;}
|
|
define void @test(ptr %f, i32 %n) nounwind ssp {
|
|
; CHECK-LABEL: @test(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[MUL:%.*]] = shl i32 [[N:%.*]], 1
|
|
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[MUL]], 0
|
|
; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_END:%.*]], label [[FOR_BODY_PREHEADER:%.*]]
|
|
; CHECK: for.body.preheader:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[MUL]] to i64
|
|
; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[TMP0]], -1
|
|
; CHECK-NEXT: [[TMP2:%.*]] = lshr i64 [[TMP1]], 1
|
|
; CHECK-NEXT: [[TMP3:%.*]] = shl i64 [[TMP2]], 3
|
|
; CHECK-NEXT: [[TMP4:%.*]] = add i64 [[TMP3]], 8
|
|
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 4 [[F:%.*]], i8 0, i64 [[TMP4]], i1 false)
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ]
|
|
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[F]], i64 [[INDVARS_IV]]
|
|
; CHECK-NEXT: [[TMP5:%.*]] = or disjoint i64 [[INDVARS_IV]], 1
|
|
; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, ptr [[F]], i64 [[TMP5]]
|
|
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 2
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[INDVARS_IV_NEXT]], [[TMP0]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]]
|
|
; CHECK: for.end.loopexit:
|
|
; CHECK-NEXT: br label [[FOR_END]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%mul = shl i32 %n, 1
|
|
%cmp1 = icmp eq i32 %mul, 0
|
|
br i1 %cmp1, label %for.end, label %for.body.preheader
|
|
|
|
for.body.preheader: ; preds = %entry
|
|
%0 = zext i32 %mul to i64
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %for.body.preheader, %for.body
|
|
%indvars.iv = phi i64 [ 0, %for.body.preheader ], [ %indvars.iv.next, %for.body ]
|
|
%arrayidx = getelementptr inbounds i32, ptr %f, i64 %indvars.iv
|
|
store i32 0, ptr %arrayidx, align 4
|
|
%1 = or disjoint i64 %indvars.iv, 1
|
|
%arrayidx2 = getelementptr inbounds i32, ptr %f, i64 %1
|
|
store i32 0, ptr %arrayidx2, align 4
|
|
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 2
|
|
%cmp = icmp ult i64 %indvars.iv.next, %0
|
|
br i1 %cmp, label %for.body, label %for.end.loopexit
|
|
|
|
for.end.loopexit: ; preds = %for.body
|
|
br label %for.end
|
|
|
|
for.end: ; preds = %for.end.loopexit, %entry
|
|
ret void
|
|
}
|
|
|
|
;void test_pattern(int *f, unsigned n) {
|
|
; for (unsigned i = 0; i < 2 * n; i += 2) {
|
|
; f[i] = 2;
|
|
; f[i+1] = 2;
|
|
; }
|
|
;}
|
|
define void @test_pattern(ptr %f, i32 %n) nounwind ssp {
|
|
; CHECK-LABEL: @test_pattern(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[MUL:%.*]] = shl i32 [[N:%.*]], 1
|
|
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[MUL]], 0
|
|
; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_END:%.*]], label [[FOR_BODY_PREHEADER:%.*]]
|
|
; CHECK: for.body.preheader:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[MUL]] to i64
|
|
; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[TMP0]], -1
|
|
; CHECK-NEXT: [[TMP2:%.*]] = lshr i64 [[TMP1]], 1
|
|
; CHECK-NEXT: [[TMP3:%.*]] = shl i64 [[TMP2]], 3
|
|
; CHECK-NEXT: [[TMP4:%.*]] = add i64 [[TMP3]], 8
|
|
; CHECK-NEXT: call void @memset_pattern16(ptr [[F:%.*]], ptr @.memset_pattern, i64 [[TMP4]])
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ]
|
|
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[F]], i64 [[INDVARS_IV]]
|
|
; CHECK-NEXT: [[TMP5:%.*]] = or disjoint i64 [[INDVARS_IV]], 1
|
|
; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, ptr [[F]], i64 [[TMP5]]
|
|
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 2
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[INDVARS_IV_NEXT]], [[TMP0]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]]
|
|
; CHECK: for.end.loopexit:
|
|
; CHECK-NEXT: br label [[FOR_END]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%mul = shl i32 %n, 1
|
|
%cmp1 = icmp eq i32 %mul, 0
|
|
br i1 %cmp1, label %for.end, label %for.body.preheader
|
|
|
|
for.body.preheader: ; preds = %entry
|
|
%0 = zext i32 %mul to i64
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %for.body.preheader, %for.body
|
|
%indvars.iv = phi i64 [ 0, %for.body.preheader ], [ %indvars.iv.next, %for.body ]
|
|
%arrayidx = getelementptr inbounds i32, ptr %f, i64 %indvars.iv
|
|
store i32 2, ptr %arrayidx, align 4
|
|
%1 = or disjoint i64 %indvars.iv, 1
|
|
%arrayidx2 = getelementptr inbounds i32, ptr %f, i64 %1
|
|
store i32 2, ptr %arrayidx2, align 4
|
|
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 2
|
|
%cmp = icmp ult i64 %indvars.iv.next, %0
|
|
br i1 %cmp, label %for.body, label %for.end.loopexit
|
|
|
|
for.end.loopexit: ; preds = %for.body
|
|
br label %for.end
|
|
|
|
for.end: ; preds = %for.end.loopexit, %entry
|
|
ret void
|
|
}
|