Skip to content

Commit 8aeb2fe

Browse files
committed
[InstCombine] Negator: -(X << C) --> X * (-1 << C)
This shows some regressions in tests, but they are all around GEP's, so i'm not really sure how important those are. https://rise4fun.com/Alive/1Gn
1 parent 8fd57b0 commit 8aeb2fe

File tree

5 files changed

+40
-32
lines changed

5 files changed

+40
-32
lines changed

llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -324,10 +324,16 @@ LLVM_NODISCARD Value *Negator::visitImpl(Value *V, unsigned Depth) {
324324
}
325325
case Instruction::Shl: {
326326
// `shl` is negatible if the first operand is negatible.
327-
Value *NegOp0 = negate(I->getOperand(0), Depth + 1);
328-
if (!NegOp0) // Early return.
327+
if (Value *NegOp0 = negate(I->getOperand(0), Depth + 1))
328+
return Builder.CreateShl(NegOp0, I->getOperand(1), I->getName() + ".neg");
329+
// Otherwise, `shl %x, C` can be interpreted as `mul %x, 1<<C`.
330+
auto *Op1C = dyn_cast<Constant>(I->getOperand(1));
331+
if (!Op1C) // Early return.
329332
return nullptr;
330-
return Builder.CreateShl(NegOp0, I->getOperand(1), I->getName() + ".neg");
333+
return Builder.CreateMul(
334+
I->getOperand(0),
335+
ConstantExpr::getShl(Constant::getAllOnesValue(Op1C->getType()), Op1C),
336+
I->getName() + ".neg");
331337
}
332338
case Instruction::Or:
333339
if (!haveNoCommonBitsSet(I->getOperand(0), I->getOperand(1), DL, &AC, I,

llvm/test/Transforms/InstCombine/icmp.ll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,8 @@ define i1 @test24(i64 %i) {
512512
; unsigned overflow does not happen during offset computation
513513
define i1 @test24_neg_offs(i32* %p, i64 %offs) {
514514
; CHECK-LABEL: @test24_neg_offs(
515-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[OFFS:%.*]], -2
515+
; CHECK-NEXT: [[P1_IDX_NEG:%.*]] = mul i64 [[OFFS:%.*]], -4
516+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[P1_IDX_NEG]], 8
516517
; CHECK-NEXT: ret i1 [[CMP]]
517518
;
518519
%p1 = getelementptr inbounds i32, i32* %p, i64 %offs

llvm/test/Transforms/InstCombine/sub-gep.ll

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,8 @@ define i32 @test_inbounds_nuw_trunc([0 x i32]* %base, i64 %idx) {
5858

5959
define i64 @test_inbounds_nuw_swapped([0 x i32]* %base, i64 %idx) {
6060
; CHECK-LABEL: @test_inbounds_nuw_swapped(
61-
; CHECK-NEXT: [[P2_IDX:%.*]] = shl nsw i64 [[IDX:%.*]], 2
62-
; CHECK-NEXT: [[DIFF_NEG:%.*]] = sub i64 0, [[P2_IDX]]
63-
; CHECK-NEXT: ret i64 [[DIFF_NEG]]
61+
; CHECK-NEXT: [[P2_IDX_NEG:%.*]] = mul i64 [[IDX:%.*]], -4
62+
; CHECK-NEXT: ret i64 [[P2_IDX_NEG]]
6463
;
6564
%p1 = getelementptr inbounds [0 x i32], [0 x i32]* %base, i64 0, i64 0
6665
%p2 = getelementptr inbounds [0 x i32], [0 x i32]* %base, i64 0, i64 %idx
@@ -73,8 +72,9 @@ define i64 @test_inbounds_nuw_swapped([0 x i32]* %base, i64 %idx) {
7372
; The sub and shl here could be nuw, but this is harder to handle.
7473
define i64 @test_inbounds_nuw_two_gep([0 x i32]* %base, i64 %idx, i64 %idx2) {
7574
; CHECK-LABEL: @test_inbounds_nuw_two_gep(
76-
; CHECK-NEXT: [[P1_IDX1_NEG:%.*]] = sub i64 [[IDX2:%.*]], [[IDX:%.*]]
77-
; CHECK-NEXT: [[DOTNEG:%.*]] = shl i64 [[P1_IDX1_NEG]], 2
75+
; CHECK-NEXT: [[P1_IDX_NEG:%.*]] = mul i64 [[IDX:%.*]], -4
76+
; CHECK-NEXT: [[P2_IDX_NEG_NEG:%.*]] = shl i64 [[IDX2:%.*]], 2
77+
; CHECK-NEXT: [[DOTNEG:%.*]] = add i64 [[P2_IDX_NEG_NEG]], [[P1_IDX_NEG]]
7878
; CHECK-NEXT: ret i64 [[DOTNEG]]
7979
;
8080
%p1 = getelementptr inbounds [0 x i32], [0 x i32]* %base, i64 0, i64 %idx

llvm/test/Transforms/InstCombine/sub-of-negatible.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1076,8 +1076,8 @@ define i8 @negate_left_shift_by_constant(i8 %x, i8 %y, i8 %z, i8 %k) {
10761076
; CHECK-LABEL: @negate_left_shift_by_constant(
10771077
; CHECK-NEXT: [[T0:%.*]] = sub i8 [[K:%.*]], [[Z:%.*]]
10781078
; CHECK-NEXT: call void @use8(i8 [[T0]])
1079-
; CHECK-NEXT: [[T1:%.*]] = shl i8 [[T0]], 4
1080-
; CHECK-NEXT: [[T2:%.*]] = sub i8 [[X:%.*]], [[T1]]
1079+
; CHECK-NEXT: [[T1_NEG:%.*]] = mul i8 [[T0]], -16
1080+
; CHECK-NEXT: [[T2:%.*]] = add i8 [[T1_NEG]], [[X:%.*]]
10811081
; CHECK-NEXT: ret i8 [[T2]]
10821082
;
10831083
%t0 = sub i8 %k, %z

llvm/test/Transforms/InstCombine/sub.ll

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -506,8 +506,8 @@ define i64 @test24b(i8* %P, i64 %A){
506506

507507
define i64 @test25(i8* %P, i64 %A){
508508
; CHECK-LABEL: @test25(
509-
; CHECK-NEXT: [[B_IDX:%.*]] = shl nsw i64 [[A:%.*]], 1
510-
; CHECK-NEXT: [[DOTNEG:%.*]] = add i64 [[B_IDX]], -84
509+
; CHECK-NEXT: [[B_IDX_NEG_NEG:%.*]] = shl i64 [[A:%.*]], 1
510+
; CHECK-NEXT: [[DOTNEG:%.*]] = add i64 [[B_IDX_NEG_NEG]], -84
511511
; CHECK-NEXT: ret i64 [[DOTNEG]]
512512
;
513513
%B = getelementptr inbounds [42 x i16], [42 x i16]* @Arr, i64 0, i64 %A
@@ -521,8 +521,8 @@ define i64 @test25(i8* %P, i64 %A){
521521
define i16 @test25_as1(i8 addrspace(1)* %P, i64 %A) {
522522
; CHECK-LABEL: @test25_as1(
523523
; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[A:%.*]] to i16
524-
; CHECK-NEXT: [[B_IDX:%.*]] = shl nsw i16 [[TMP1]], 1
525-
; CHECK-NEXT: [[DOTNEG:%.*]] = add i16 [[B_IDX]], -84
524+
; CHECK-NEXT: [[B_IDX_NEG_NEG:%.*]] = shl i16 [[TMP1]], 1
525+
; CHECK-NEXT: [[DOTNEG:%.*]] = add i16 [[B_IDX_NEG_NEG]], -84
526526
; CHECK-NEXT: ret i16 [[DOTNEG]]
527527
;
528528
%B = getelementptr inbounds [42 x i16], [42 x i16] addrspace(1)* @Arr_as1, i64 0, i64 %A
@@ -557,9 +557,8 @@ define i64 @test_neg_shl_sub_extra_use1(i64 %a, i64 %b, i64* %p) {
557557
; CHECK-LABEL: @test_neg_shl_sub_extra_use1(
558558
; CHECK-NEXT: [[SUB:%.*]] = sub i64 [[A:%.*]], [[B:%.*]]
559559
; CHECK-NEXT: store i64 [[SUB]], i64* [[P:%.*]], align 8
560-
; CHECK-NEXT: [[MUL:%.*]] = shl i64 [[SUB]], 2
561-
; CHECK-NEXT: [[NEG:%.*]] = sub i64 0, [[MUL]]
562-
; CHECK-NEXT: ret i64 [[NEG]]
560+
; CHECK-NEXT: [[MUL_NEG:%.*]] = mul i64 [[SUB]], -4
561+
; CHECK-NEXT: ret i64 [[MUL_NEG]]
563562
;
564563
%sub = sub i64 %a, %b
565564
store i64 %sub, i64* %p
@@ -840,9 +839,10 @@ define i64 @test29(i8* %foo, i64 %i, i64 %j) {
840839

841840
define i64 @test30(i8* %foo, i64 %i, i64 %j) {
842841
; CHECK-LABEL: @test30(
843-
; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nsw i64 [[I:%.*]], 2
844-
; CHECK-NEXT: [[DOTNEG:%.*]] = sub i64 [[GEP1_IDX]], [[J:%.*]]
845-
; CHECK-NEXT: ret i64 [[DOTNEG]]
842+
; CHECK-NEXT: [[GEP1_IDX_NEG:%.*]] = mul i64 [[I:%.*]], -4
843+
; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[GEP1_IDX_NEG]], [[J:%.*]]
844+
; CHECK-NEXT: [[DIFF_NEG:%.*]] = sub i64 0, [[TMP1]]
845+
; CHECK-NEXT: ret i64 [[DIFF_NEG]]
846846
;
847847
%bit = bitcast i8* %foo to i32*
848848
%gep1 = getelementptr inbounds i32, i32* %bit, i64 %i
@@ -855,9 +855,10 @@ define i64 @test30(i8* %foo, i64 %i, i64 %j) {
855855

856856
define i16 @test30_as1(i8 addrspace(1)* %foo, i16 %i, i16 %j) {
857857
; CHECK-LABEL: @test30_as1(
858-
; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nsw i16 [[I:%.*]], 2
859-
; CHECK-NEXT: [[DOTNEG:%.*]] = sub i16 [[GEP1_IDX]], [[J:%.*]]
860-
; CHECK-NEXT: ret i16 [[DOTNEG]]
858+
; CHECK-NEXT: [[GEP1_IDX_NEG:%.*]] = mul i16 [[I:%.*]], -4
859+
; CHECK-NEXT: [[TMP1:%.*]] = add i16 [[GEP1_IDX_NEG]], [[J:%.*]]
860+
; CHECK-NEXT: [[DIFF_NEG:%.*]] = sub i16 0, [[TMP1]]
861+
; CHECK-NEXT: ret i16 [[DIFF_NEG]]
861862
;
862863
%bit = bitcast i8 addrspace(1)* %foo to i32 addrspace(1)*
863864
%gep1 = getelementptr inbounds i32, i32 addrspace(1)* %bit, i16 %i
@@ -1310,8 +1311,8 @@ define i64 @test61([100 x [100 x i8]]* %foo, i64 %i, i64 %j) {
13101311

13111312
define i32 @test62(i32 %A) {
13121313
; CHECK-LABEL: @test62(
1313-
; CHECK-NEXT: [[B:%.*]] = shl i32 [[A:%.*]], 1
1314-
; CHECK-NEXT: [[C:%.*]] = sub i32 2, [[B]]
1314+
; CHECK-NEXT: [[B_NEG:%.*]] = mul i32 [[A:%.*]], -2
1315+
; CHECK-NEXT: [[C:%.*]] = add i32 [[B_NEG]], 2
13151316
; CHECK-NEXT: ret i32 [[C]]
13161317
;
13171318
%B = sub i32 1, %A
@@ -1321,8 +1322,8 @@ define i32 @test62(i32 %A) {
13211322

13221323
define <2 x i32> @test62vec(<2 x i32> %A) {
13231324
; CHECK-LABEL: @test62vec(
1324-
; CHECK-NEXT: [[B:%.*]] = shl <2 x i32> [[A:%.*]], <i32 1, i32 1>
1325-
; CHECK-NEXT: [[C:%.*]] = sub <2 x i32> <i32 2, i32 2>, [[B]]
1325+
; CHECK-NEXT: [[B_NEG:%.*]] = mul <2 x i32> [[A:%.*]], <i32 -2, i32 -2>
1326+
; CHECK-NEXT: [[C:%.*]] = add <2 x i32> [[B_NEG]], <i32 2, i32 2>
13261327
; CHECK-NEXT: ret <2 x i32> [[C]]
13271328
;
13281329
%B = sub <2 x i32> <i32 1, i32 1>, %A
@@ -1332,8 +1333,8 @@ define <2 x i32> @test62vec(<2 x i32> %A) {
13321333

13331334
define i32 @test63(i32 %A) {
13341335
; CHECK-LABEL: @test63(
1335-
; CHECK-NEXT: [[B:%.*]] = shl i32 [[A:%.*]], 1
1336-
; CHECK-NEXT: ret i32 [[B]]
1336+
; CHECK-NEXT: [[B_NEG_NEG:%.*]] = shl i32 [[A:%.*]], 1
1337+
; CHECK-NEXT: ret i32 [[B_NEG_NEG]]
13371338
;
13381339
%B = sub i32 1, %A
13391340
%C = shl i32 %B, 1
@@ -1343,8 +1344,8 @@ define i32 @test63(i32 %A) {
13431344

13441345
define <2 x i32> @test63vec(<2 x i32> %A) {
13451346
; CHECK-LABEL: @test63vec(
1346-
; CHECK-NEXT: [[B:%.*]] = shl <2 x i32> [[A:%.*]], <i32 1, i32 1>
1347-
; CHECK-NEXT: ret <2 x i32> [[B]]
1347+
; CHECK-NEXT: [[B_NEG_NEG:%.*]] = shl <2 x i32> [[A:%.*]], <i32 1, i32 1>
1348+
; CHECK-NEXT: ret <2 x i32> [[B_NEG_NEG]]
13481349
;
13491350
%B = sub <2 x i32> <i32 1, i32 1>, %A
13501351
%C = shl <2 x i32> %B, <i32 1, i32 1>

0 commit comments

Comments
 (0)