1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
|
;=========================== begin_copyright_notice ============================
;
; Copyright (C) 2024 Intel Corporation
;
; SPDX-License-Identifier: MIT
;
;============================ end_copyright_notice =============================
; Note that we could run the test with an additional cleanup pass like EarlyCSE
; to get a tidier output. The current preference is towards the check lines that
; would correspond to the input instructions more explicitly.
; RUN: igc_opt --opaque-pointers -debugify --igc-gen-specific-pattern -check-debugify -S < %s 2>&1 | FileCheck %s
; ------------------------------------------------
; GenSpecificPattern:
; ------------------------------------------------
; Debug-info related check
; CHECK-NOT: WARNING
; CHECK: CheckModuleDebugify: PASS
define void @test_simple_mul_pow2(i32 %arg) {
%1 = mul i32 %arg, 16
call void @use.i32(i32 %1)
ret void
}
; CHECK-LABEL: @test_simple_mul_pow2(i32 %arg
; CHECK: %[[SHL:.+]] = shl i32 %arg, 4
; CHECK: call void @use.i32(i32 %[[SHL]])
; CHECK: ret void
; COM: Negative edge case test
define void @test_mul_pow2_skip_ones(i32 %arg) {
%1 = mul i32 %arg, 1
call void @use.i32(i32 %1)
%2 = mul i32 -1, %arg
call void @use.i32(i32 %2)
ret void
}
; CHECK-LABEL: @test_mul_pow2_skip_ones(i32 %arg
; CHECK: %[[MUL_PLUS:.+]] = mul i32 %arg, 1
; CHECK: call void @use.i32(i32 %[[MUL_PLUS]])
; CHECK: %[[MUL_MINUS:.+]] = mul i32 -1, %arg
; CHECK: call void @use.i32(i32 %[[MUL_MINUS]])
; CHECK: ret void
define void @test_mul_pow2_overflow_flags(i64 %arg) {
%1 = mul nsw i64 %arg, 256
call void @use.i64(i64 %1)
%2 = mul nuw i64 %arg, 256
call void @use.i64(i64 %2)
%3 = mul nuw nsw i64 %arg, 1024
call void @use.i64(i64 %3)
ret void
}
; CHECK-LABEL: @test_mul_pow2_overflow_flags(i64 %arg
; CHECK: %[[SHL_NSW:.+]] = shl nsw i64 %arg, 8
; CHECK: call void @use.i64(i64 %[[SHL_NSW]])
; CHECK: %[[SHL_NUW:.+]] = shl nuw i64 %arg, 8
; CHECK: call void @use.i64(i64 %[[SHL_NUW]])
; CHECK: %[[SHL_NUW_NSW:.+]] = shl nuw nsw i64 %arg, 10
; CHECK: call void @use.i64(i64 %[[SHL_NUW_NSW]])
; CHECK: ret void
define void @test_mul_neg_pow2_overflow_flags(i64 %arg) {
%1 = mul nsw i64 %arg, -256
call void @use.i64(i64 %1)
%2 = mul nuw i64 %arg, -256
call void @use.i64(i64 %2)
%3 = mul nuw nsw i64 %arg, -1024
call void @use.i64(i64 %3)
ret void
}
; CHECK-LABEL: @test_mul_neg_pow2_overflow_flags(i64 %arg
; COM: Only 'mul's without NUW can be transformed
; CHECK: %[[SHL_NSW:.+]] = shl nsw i64 %arg, 8
; CHECK: %[[NEG_NSW:.+]] = sub nsw i64 0, %[[SHL_NSW]]
; CHECK: call void @use.i64(i64 %[[NEG_NSW]])
; CHECK: %[[MUL_NUW:.+]] = mul nuw i64 %arg, -256
; CHECK: call void @use.i64(i64 %[[MUL_NUW]])
; CHECK: %[[MUL_NUW_NSW:.+]] = mul nuw nsw i64 %arg, -1024
; CHECK: call void @use.i64(i64 %[[MUL_NUW_NSW]])
; CHECK: ret void
define void @test_mul_neg_pow2_with_binops(i32 %arg0, i32 %arg1, i32 %arg2) {
entry:
; COM: The mul itself + simple use
%0 = mul i32 %arg0, -1024
call void @use.i32(i32 %0)
br label %.add1
.add1:
; COM: mul + addend
%1 = add i32 %0, %arg1
call void @use.i32(i32 %1)
br label %.add2
.add2:
; COM: addend + mul
%2 = add i32 %arg2, %0
call void @use.i32(i32 %2)
ret void
}
; CHECK-LABEL: @test_mul_neg_pow2_with_binops(i32 %arg0, i32 %arg1, i32 %arg2
; COM: The mul itself + simple use
; CHECK: entry:
; CHECK: %[[SHL:.+]] = shl i32 %arg0, 10
; CHECK: %[[NEG:.+]] = sub i32 0, %[[SHL]]
; CHECK: call void @use.i32(i32 %[[NEG]])
; CHECK: br label %.add1
; COM: mul + addend -> addend - shl
; CHECK: .add1:
; CHECK: %[[SUB1:.+]] = sub i32 %arg1, %[[SHL]]
; CHECK: call void @use.i32(i32 %[[SUB1]])
; CHECK: br label %.add2
; COM: addend + mul -> addend - shl
; CHECK: .add2:
; CHECK: %[[SUB2:.+]] = sub i32 %arg2, %[[SHL]]
; CHECK: call void @use.i32(i32 %[[SUB2]])
; CHECK: ret void
define void @test_mul_neg_pow2_with_binops_overflow_flags(i64 %arg0, i64 %arg1) {
; COM: 'mul' with no flags - 'add's with all combinations of flags
%1 = mul i64 %arg0, -256
%2 = add i64 %1, %arg1
call void @use.i64(i64 %2)
%3 = add nuw i64 %arg1, %1
call void @use.i64(i64 %3)
%4 = add nsw i64 %1, %arg1
call void @use.i64(i64 %4)
%5 = add nuw nsw i64 %arg1, %1
call void @use.i64(i64 %5)
; COM: 'mul' with 'nsw' - 'add's with all combinations of flags
%6 = mul nsw i64 %arg0, -512
%7 = add i64 %6, %arg1
call void @use.i64(i64 %7)
%8 = add nuw i64 %arg1, %6
call void @use.i64(i64 %8)
%9 = add nsw i64 %6, %arg1
call void @use.i64(i64 %9)
%10 = add nuw nsw i64 %arg1, %6
call void @use.i64(i64 %10)
ret void
}
; CHECK-LABEL: @test_mul_neg_pow2_with_binops_overflow_flags(i64 %arg0, i64 %arg1
; COM: 'mul' with no flags
; CHECK: %[[SHL_NO_FLAG:.+]] = shl i64 %arg0, 8
; CHECK: %[[NEG_NO_FLAG:.+]] = sub i64 0, %[[SHL_NO_FLAG]]
; COM: 'add's without 'nsw' can be simplified
; CHECK: %[[ADD_NO_FLAG:.+]] = sub i64 %arg1, %[[SHL_NO_FLAG]]
; CHECK: call void @use.i64(i64 %[[ADD_NO_FLAG]])
; CHECK: %[[ADD_NUW:.+]] = sub nuw i64 %arg1, %[[SHL_NO_FLAG]]
; CHECK: call void @use.i64(i64 %[[ADD_NUW]])
; CHECK: %[[ADD_NSW:.+]] = add nsw i64 %[[NEG_NO_FLAG]], %arg1
; CHECK: call void @use.i64(i64 %[[ADD_NSW]])
; CHECK: %[[ADD_NUW_NSW:.+]] = add nuw nsw i64 %arg1, %[[NEG_NO_FLAG]]
; CHECK: call void @use.i64(i64 %[[ADD_NUW_NSW]])
; COM: 'mul' with 'nsw'
; CHECK: %[[SHL_NSW:.+]] = shl nsw i64 %arg0, 9
; CHECK: %[[NEG_NSW:.+]] = sub nsw i64 0, %[[SHL_NSW]]
; COM: Any 'add's with 'nsw' can be simplified
; CHECK: %[[ADD_NO_FLAG:.+]] = add i64 %[[NEG_NSW]], %arg1
; CHECK: call void @use.i64(i64 %[[ADD_NO_FLAG]])
; CHECK: %[[ADD_NUW:.+]] = add nuw i64 %arg1, %[[NEG_NSW]]
; CHECK: call void @use.i64(i64 %[[ADD_NUW]])
; CHECK: %[[ADD_NSW:.+]] = sub nsw i64 %arg1, %[[SHL_NSW]]
; CHECK: call void @use.i64(i64 %[[ADD_NSW]])
; CHECK: %[[ADD_NUW_NSW:.+]] = sub nuw nsw i64 %arg1, %[[SHL_NSW]]
; CHECK: call void @use.i64(i64 %[[ADD_NUW_NSW]])
; CHECK: ret void
declare void @use.i64(i64)
declare void @use.i32(i32)
|