Skip to content

Commit 61157d1

Browse files
committed
[ValueTracking] add test for use of assume to compute overflowResult. (NFC)
1 parent 82fecab commit 61157d1

File tree

1 file changed

+157
-0
lines changed

1 file changed

+157
-0
lines changed

llvm/test/Transforms/InstCombine/with_overflow.ll

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1064,3 +1064,160 @@ define i8 @smul_7(i8 %x, ptr %p) {
10641064
store i1 %ov, ptr %p
10651065
ret i8 %r
10661066
}
1067+
1068+
define i8 @uadd_assume_no_overflow(i8 noundef %a, i8 noundef %b) {
1069+
; CHECK-LABEL: @uadd_assume_no_overflow(
1070+
; CHECK-NEXT: [[CALL1:%.*]] = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 [[A:%.*]], i8 [[B:%.*]])
1071+
; CHECK-NEXT: [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[CALL1]], 1
1072+
; CHECK-NEXT: [[CALL:%.*]] = extractvalue { i8, i1 } [[CALL1]], 0
1073+
; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[OVERFLOW]], true
1074+
; CHECK-NEXT: call void @llvm.assume(i1 [[NOT]])
1075+
; CHECK-NEXT: ret i8 [[CALL]]
1076+
;
1077+
%call = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 %a, i8 %b)
1078+
%overflow = extractvalue { i8, i1 } %call, 1
1079+
%ret = extractvalue { i8, i1 } %call, 0
1080+
%not = xor i1 %overflow, true
1081+
call void @llvm.assume(i1 %not)
1082+
ret i8 %ret
1083+
}
1084+
1085+
define i8 @sadd_assume_no_overflow(i8 noundef %a, i8 noundef %b) {
1086+
; CHECK-LABEL: @sadd_assume_no_overflow(
1087+
; CHECK-NEXT: [[CALL1:%.*]] = call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[A:%.*]], i8 [[B:%.*]])
1088+
; CHECK-NEXT: [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[CALL1]], 1
1089+
; CHECK-NEXT: [[CALL:%.*]] = extractvalue { i8, i1 } [[CALL1]], 0
1090+
; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[OVERFLOW]], true
1091+
; CHECK-NEXT: call void @llvm.assume(i1 [[NOT]])
1092+
; CHECK-NEXT: ret i8 [[CALL]]
1093+
;
1094+
%call = call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %a, i8 %b)
1095+
%overflow = extractvalue { i8, i1 } %call, 1
1096+
%ret = extractvalue { i8, i1 } %call, 0
1097+
%not = xor i1 %overflow, true
1098+
call void @llvm.assume(i1 %not)
1099+
ret i8 %ret
1100+
}
1101+
1102+
define i8 @usub_assume_no_overflow(i8 noundef %a, i8 noundef %b) {
1103+
; CHECK-LABEL: @usub_assume_no_overflow(
1104+
; CHECK-NEXT: [[CALL1:%.*]] = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[A:%.*]], i8 [[B:%.*]])
1105+
; CHECK-NEXT: [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[CALL1]], 1
1106+
; CHECK-NEXT: [[CALL:%.*]] = extractvalue { i8, i1 } [[CALL1]], 0
1107+
; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[OVERFLOW]], true
1108+
; CHECK-NEXT: call void @llvm.assume(i1 [[NOT]])
1109+
; CHECK-NEXT: ret i8 [[CALL]]
1110+
;
1111+
%call = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %a, i8 %b)
1112+
%overflow = extractvalue { i8, i1 } %call, 1
1113+
%ret = extractvalue { i8, i1 } %call, 0
1114+
%not = xor i1 %overflow, true
1115+
call void @llvm.assume(i1 %not)
1116+
ret i8 %ret
1117+
}
1118+
1119+
define i8 @ssub_assume_no_overflow(i8 noundef %a, i8 noundef %b) {
1120+
; CHECK-LABEL: @ssub_assume_no_overflow(
1121+
; CHECK-NEXT: [[CALL1:%.*]] = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[A:%.*]], i8 [[B:%.*]])
1122+
; CHECK-NEXT: [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[CALL1]], 1
1123+
; CHECK-NEXT: [[CALL:%.*]] = extractvalue { i8, i1 } [[CALL1]], 0
1124+
; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[OVERFLOW]], true
1125+
; CHECK-NEXT: call void @llvm.assume(i1 [[NOT]])
1126+
; CHECK-NEXT: ret i8 [[CALL]]
1127+
;
1128+
%call = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %a, i8 %b)
1129+
%overflow = extractvalue { i8, i1 } %call, 1
1130+
%ret = extractvalue { i8, i1 } %call, 0
1131+
%not = xor i1 %overflow, true
1132+
call void @llvm.assume(i1 %not)
1133+
ret i8 %ret
1134+
}
1135+
1136+
define i8 @umul_assume_no_overflow(i8 noundef %a, i8 noundef %b) {
1137+
; CHECK-LABEL: @umul_assume_no_overflow(
1138+
; CHECK-NEXT: [[CALL1:%.*]] = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 [[A:%.*]], i8 [[B:%.*]])
1139+
; CHECK-NEXT: [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[CALL1]], 1
1140+
; CHECK-NEXT: [[CALL:%.*]] = extractvalue { i8, i1 } [[CALL1]], 0
1141+
; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[OVERFLOW]], true
1142+
; CHECK-NEXT: call void @llvm.assume(i1 [[NOT]])
1143+
; CHECK-NEXT: ret i8 [[CALL]]
1144+
;
1145+
%call = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 %a, i8 %b)
1146+
%overflow = extractvalue { i8, i1 } %call, 1
1147+
%ret = extractvalue { i8, i1 } %call, 0
1148+
%not = xor i1 %overflow, true
1149+
call void @llvm.assume(i1 %not)
1150+
ret i8 %ret
1151+
}
1152+
1153+
define i8 @smul_assume_no_overflow(i8 noundef %a, i8 noundef %b) {
1154+
; CHECK-LABEL: @smul_assume_no_overflow(
1155+
; CHECK-NEXT: [[CALL1:%.*]] = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[A:%.*]], i8 [[B:%.*]])
1156+
; CHECK-NEXT: [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[CALL1]], 1
1157+
; CHECK-NEXT: [[CALL:%.*]] = extractvalue { i8, i1 } [[CALL1]], 0
1158+
; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[OVERFLOW]], true
1159+
; CHECK-NEXT: call void @llvm.assume(i1 [[NOT]])
1160+
; CHECK-NEXT: ret i8 [[CALL]]
1161+
;
1162+
%call = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %a, i8 %b)
1163+
%overflow = extractvalue { i8, i1 } %call, 1
1164+
%ret = extractvalue { i8, i1 } %call, 0
1165+
%not = xor i1 %overflow, true
1166+
call void @llvm.assume(i1 %not)
1167+
ret i8 %ret
1168+
}
1169+
1170+
define i1 @ephemeral_call_assume_no_overflow(i8 noundef %a, i8 noundef %b) {
1171+
; CHECK-LABEL: @ephemeral_call_assume_no_overflow(
1172+
; CHECK-NEXT: [[CALL:%.*]] = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[A:%.*]], i8 [[B:%.*]])
1173+
; CHECK-NEXT: [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[CALL]], 1
1174+
; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[OVERFLOW]], true
1175+
; CHECK-NEXT: call void @llvm.assume(i1 [[NOT]])
1176+
; CHECK-NEXT: ret i1 [[NOT]]
1177+
;
1178+
%call = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %a, i8 %b)
1179+
%overflow = extractvalue { i8, i1 } %call, 1
1180+
%not = xor i1 %overflow, true
1181+
call void @llvm.assume(i1 %not)
1182+
ret i1 %not
1183+
}
1184+
1185+
define i8 @neg_assume_overflow(i8 noundef %a, i8 noundef %b) {
1186+
; CHECK-LABEL: @neg_assume_overflow(
1187+
; CHECK-NEXT: [[CALL:%.*]] = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[A:%.*]], i8 [[B:%.*]])
1188+
; CHECK-NEXT: [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[CALL]], 1
1189+
; CHECK-NEXT: [[RET:%.*]] = extractvalue { i8, i1 } [[CALL]], 0
1190+
; CHECK-NEXT: call void @llvm.assume(i1 [[OVERFLOW]])
1191+
; CHECK-NEXT: ret i8 [[RET]]
1192+
;
1193+
%call = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %a, i8 %b)
1194+
%overflow = extractvalue { i8, i1 } %call, 1
1195+
%ret = extractvalue { i8, i1 } %call, 0
1196+
call void @llvm.assume(i1 %overflow)
1197+
ret i8 %ret
1198+
}
1199+
1200+
define i8 @neg_assume_not_guaranteed_to_execute(i8 noundef %a, i8 noundef %b, i1 %cond) {
1201+
; CHECK-LABEL: @neg_assume_not_guaranteed_to_execute(
1202+
; CHECK-NEXT: [[CALL:%.*]] = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[A:%.*]], i8 [[B:%.*]])
1203+
; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
1204+
; CHECK: bb1:
1205+
; CHECK-NEXT: [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[CALL]], 1
1206+
; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[OVERFLOW]], true
1207+
; CHECK-NEXT: call void @llvm.assume(i1 [[NOT]])
1208+
; CHECK-NEXT: br label [[BB2]]
1209+
; CHECK: bb2:
1210+
; CHECK-NEXT: [[RET:%.*]] = extractvalue { i8, i1 } [[CALL]], 0
1211+
; CHECK-NEXT: ret i8 [[RET]]
1212+
;
1213+
%call = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %a, i8 %b)
1214+
%overflow = extractvalue { i8, i1 } %call, 1
1215+
%ret = extractvalue { i8, i1 } %call, 0
1216+
br i1 %cond, label %bb1, label %bb2
1217+
bb1:
1218+
%not = xor i1 %overflow, true
1219+
call void @llvm.assume(i1 %not)
1220+
br label %bb2
1221+
bb2:
1222+
ret i8 %ret
1223+
}

0 commit comments

Comments
 (0)