Original message: We still have to keep the noCommonBitsSet call to handle multiple reassociations in one pass. We'll lose the flag on the first reassociation.
77 lines
2.6 KiB
LLVM
77 lines
2.6 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt < %s -passes=reassociate -S | FileCheck %s
|
|
|
|
define i32 @shl_add(i8 %x) {
|
|
; CHECK-LABEL: @shl_add(
|
|
; CHECK-NEXT: [[CONV:%.*]] = zext i8 [[X:%.*]] to i32
|
|
; CHECK-NEXT: [[SHL:%.*]] = shl nuw nsw i32 [[CONV]], 8
|
|
; CHECK-NEXT: [[SHL2:%.*]] = shl nuw nsw i32 [[CONV]], 16
|
|
; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[SHL]], [[SHL2]]
|
|
; CHECK-NEXT: ret i32 [[ADD]]
|
|
;
|
|
%conv = zext i8 %x to i32
|
|
%shl = shl nuw nsw i32 %conv, 8
|
|
%shl2 = shl nuw nsw i32 %conv, 16
|
|
%add = or i32 %shl, %shl2
|
|
ret i32 %add
|
|
}
|
|
|
|
; If we don't know that operands have no common bits set,
|
|
; we can't convert the `or` into an `add`.
|
|
define i32 @test1(i32 %a, i32 %b) {
|
|
; CHECK-LABEL: @test1(
|
|
; CHECK-NEXT: [[C:%.*]] = or i32 [[B:%.*]], [[A:%.*]]
|
|
; CHECK-NEXT: [[C_PLUS_ONE:%.*]] = add i32 [[C]], 1
|
|
; CHECK-NEXT: ret i32 [[C_PLUS_ONE]]
|
|
;
|
|
%c = or i32 %a, %b
|
|
%c.plus.one = add i32 %c, 1
|
|
ret i32 %c.plus.one
|
|
}
|
|
|
|
; But if we *do* know that operands have no common bits set,
|
|
; we *can* convert the `or` into an `add`.
|
|
define i32 @test2(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: @test2(
|
|
; CHECK-NEXT: [[X_NUMLZ:%.*]] = tail call i32 @llvm.ctlz.i32(i32 [[X:%.*]], i1 true), [[RNG0:!range !.*]]
|
|
; CHECK-NEXT: [[RES:%.*]] = add nuw nsw i32 [[X_NUMLZ]], -32
|
|
; CHECK-NEXT: [[RES_PLUS_ONE:%.*]] = add i32 [[RES]], [[Y:%.*]]
|
|
; CHECK-NEXT: ret i32 [[RES_PLUS_ONE]]
|
|
;
|
|
%x.numlz = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true), !range !0
|
|
%res = or i32 %x.numlz, -32
|
|
%res.plus.one = add i32 %res, %y
|
|
ret i32 %res.plus.one
|
|
}
|
|
|
|
; And that allows reassociation in general.
|
|
define i32 @test3(i32 %x, i32 %bit) {
|
|
; CHECK-LABEL: @test3(
|
|
; CHECK-NEXT: [[X_NUMLZ:%.*]] = tail call i32 @llvm.ctlz.i32(i32 [[X:%.*]], i1 true), [[RNG0]]
|
|
; CHECK-NEXT: [[BIT_PLUS_ONE:%.*]] = add i32 [[BIT:%.*]], -31
|
|
; CHECK-NEXT: [[RES:%.*]] = add i32 [[BIT_PLUS_ONE]], [[X_NUMLZ]]
|
|
; CHECK-NEXT: ret i32 [[RES]]
|
|
;
|
|
%x.numlz = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true), !range !0
|
|
%zero.minus.x.numactivebits = or i32 %x.numlz, -32
|
|
%bit.plus.one = add i32 %bit, 1
|
|
%res = add i32 %bit.plus.one, %zero.minus.x.numactivebits
|
|
ret i32 %res
|
|
}
|
|
|
|
; Test that disjoint allow reassociation.
|
|
define i32 @test4(i32 %a, i32 %b) {
|
|
; CHECK-LABEL: @test4(
|
|
; CHECK-NEXT: [[C:%.*]] = add i32 [[A:%.*]], 1
|
|
; CHECK-NEXT: [[C_PLUS_ONE:%.*]] = add i32 [[C]], [[B:%.*]]
|
|
; CHECK-NEXT: ret i32 [[C_PLUS_ONE]]
|
|
;
|
|
%c = or disjoint i32 %a, %b
|
|
%c.plus.one = add i32 %c, 1
|
|
ret i32 %c.plus.one
|
|
}
|
|
|
|
declare i32 @llvm.ctlz.i32(i32, i1 immarg) #2
|
|
|
|
!0 = !{i32 0, i32 33}
|